[
  {
    "path": ".editorconfig",
    "content": "# editorconfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Default settings:\n# Use 4 spaces as indentation\n[*]\nindent_style = space\nindent_size = 4\n\n[Makefile]\nindent_style = tab\nindent_size = 4\n"
  },
  {
    "path": ".gitignore",
    "content": "# User data\nmeka/Debug\nmeka/Music\nmeka/Saves\nmeka/Screenshots\n\n# Builds\nmeka/Dist\n\n# Developer data\nmeka/objs\nmeka/meka\nmeka/meka.cfg\nmeka/meka.dsk\nmeka/meka.fdb\nmeka/meka\nmeka/mekaw.cfg\nmeka/mekaw.exe\nmeka/mekaw.ilk\nmeka/smsid.exe\nmeka/smsid.ilk\nmeka/srcs/obj\nmeka/srcs/projects/msvc/Meka.ncb\nmeka/srcs/projects/msvc/.vs\nmeka/srcs/projects/msvc/packages/\nmeka/libs/allegro\nmeka/libs/allegro_deps\nallegro.log\nimgui.ini\n*.opensdf\n*.sdf\n*.suo\n*.ipch\n.vs/\n*.vc.db\n*.user\n.*.swp\n*~\n.*~\n"
  },
  {
    "path": "README.md",
    "content": "MEKA\n====\n\n- Homepage: http://www.smspower.org/meka\n- Forum: http://www.smspower.org/forums/f7-MEKA\n\nLatest Beta Windows binaries:\n- https://github.com/ocornut/meka/releases\n- Also may want to follow this thread: http://www.smspower.org/forums/13019\n\nMEKA is a multi-machine emulator. The following machines are supported by MEKA:\n\n- Sega Game 1000 (SG-1000)\n- Sega Computer 3000 (SC-3000)\n- Sega Super Control Station (SF-7000)\n- Sega Mark III (+ FM Unit)\n- Sega Master System (SMS)\n- Sega Game Gear (GG)\n- ColecoVision (COLECO)\n- Othello Multivision (OMV)\n\nAlong with a wide range of peripherals and exotic games support. \n\nMEKA should compile for MS-Windows, GNU/Linux and OSX (older versions support MS-DOS).\n\nMEKA was started in 1998 and first released on April 3rd 1999. It was my first major C project, so the codebase is old, ugly and messy! It is still being updated sometimes.\n\nIn spite of its old age and very clunky technology, MEKA is among the most exhaustive Sega 8-bit emulator in term of coverage of obscure games, peripherals. And also provide competent debugging and reverse engineering tools. It is still maintained for those purpose but doesn't has much use for the average player. \n\nCredits\n-------\n(old pre-github credits from meka.txt)\n \n```\nOmar Cornut (Bock): Main development, coordination\nMarat Fayzullin (RST38H): Zilog Z80 CPU emulation core. Implemented with modifications in MEKA.\nMitsutaka Okazaki: Software Yamaha 2413 emulator (EMU2413).\nMaxim: Software PSG emulator.\nHiromitsu Shioya (Hiro-shi): Original sound engine (now obsolete).\nUlrich Cordes: FDC765 emulator for SF-7000. Implemented with modifications by Marc Le Douarain.\nValerie Tching (Kittie): Initial version of the Memory Editor.\nJohan Euphrosine (Proppy): GNU/Linux+OSX tweaks.\nDJRobX: Blitters and video improvements, HQ2X interface.\nMaxim Stephin (MaxSt): HQ2X graphics filter.\nDirk Stevens: Eagle graphics filter.\n```\n\nClone\n-----\n\n```\ngit clone --recursive https://github.com/ocornut/meka.git meka\n```\n\nBuild\n-----\n\n- Windows: Using Visual Studio 2022 (free community edition is ok), open `meka/srcs/projects/msvc/Meka.sln` and build. The project is setup to grab dependencies (Allegro, Nasm) using Nuget.\n- Linux: `cd meka/srcs ; make`\n- OSX: `cd meka/srcs ; make` or open `meka/srcs/projects/xcode` with xcode (may be not up to date)\n\nThis project is looking for Linux and OSX maintainers.\n\nGallery\n-------\n\n![Debugger Screenshot](http://www.smspower.org/forums/files/meka_080_wip_debugger_823.png)\n\n![Debugger Screenshot](http://www.smspower.org/meka/gallery/meka072-wip-sagaia.png)\n"
  },
  {
    "path": "appveyor.yml",
    "content": "version: 0.8.{build}\r\nimage: Visual Studio 2022\r\nconfiguration: Release\r\nbefore_build:\r\n- cmd: nuget restore meka/srcs/projects/msvc/meka.sln\r\nbuild:\r\n  project: meka/srcs/projects/msvc/meka.sln\r\n  verbosity: minimal\r\nafter_build:\r\n- cmd: pushd meka\\tools\r\n- cmd: echo | dist_bin_win32.bat\r\nartifacts:\r\n- path: 'meka/Dist/*.zip'"
  },
  {
    "path": "meka/TODO.txt",
    "content": "feature request: add game name to the front of the window title text because the video capture uses that for the capture filename\r\n\r\ndasm 81e1 in wb3 is broken\r\n\r\nIf you are going to work on it, maybe you can take the opportunity to also add full support for graphics modes 1 & 2 in the Tiles Viewer and Tilemap Viewer?\r\nRight now the Tiles Viewer only shows up to 512 tiles but graphics 2 supports up to 768. Also Tiles Viewer doesn't seem to use the color table (even though the game screen view seems to use it properly)\r\nMemory Leak\r\n\r\nBorder Color emulation\r\n\r\nDebugger: STEP OVER broken on line with breakpoint\r\nMemoryViewew: input register/expr in ADDR field\r\n\r\n<48 KB rom should heuristically detect possible use of sega mapper by counting of LD (FFFx),A and discarding those who have also have load in E000.FFF0 range.\r\n\r\nTrackback: optimistically assume that disassembled lines (after >PC) can be included in trackback\r\nTrackback: replace by ROM sized bitfield?\r\n\r\nEasy save slot select in menu?\r\n\r\n- it crashes when I lock the workstation (WinXP)\r\n- single key shortcuts (with F6 and F7 keys for example) for run over (continue to next) and run into (enter) calls so that I can debug with two fingers on the keyboard and two eyes on the screen :)\r\n\r\nI just noticed this thread and after fixing this, it appeared that the Korean version of \"Circus Charlie\" also needs 2KB of RAM at $c000-$ffff\r\n\r\n\r\nbreakpoint crashes\r\n\r\nfm registrers viewer\r\nhttp://www.smspower.org/forums/viewtopic.php?p=76979#76979\r\n\r\n\r\nMenu note:\r\n- CTRL+F12 in SK-1100 mode\r\n- FPS counter toggle\r\n- F1,F2,F3,F4\r\n\r\n--\r\n\r\nHey there,\r\n\r\nI was so happy to see my favourite SMS emulator was having another update! I downloaded the most recent beta in this thread, and discovered that it doesn't like being installed over 0.73, throwing up sound buffer errors. Doing a clean install removes this.\r\n\r\nI've not had time to do much further testing, however one small UI issue that's always been there, and I'd like to see fixed if possible please, is the inability to set controllers outside of the order that Windows sees them in.\r\n\r\nTo explain: You can't change 3/6 Joypad 1 to Player 2, nor can you click it's controls and input any other controller except the one listed first by Windows. In my case, I have currently an MS Sidewinder Pro Flightstick and a Logic3 Arcade Stick both in USB ports, and Joypad 1 will only take input from the Sidewinder. 4/6 Joypad 2 takes the Arcade stick input, but not the Flightstick in turn.\r\n\r\nSuggested Solution: Drop down box to map specific controller to Player X, or allowing Player 1 to be swapped with Player 2 with a click on that line in the box, thus swapping what controller it maps too.\r\n\r\n--\r\n\r\nMy build is the 2012/12/31.\r\n\r\nmarkvt: The 'delete' key does not work in the cheat finder for me, only the 'backspace' key does allow to remove a value in the search box.\r\n\r\nIs there any emulator/setting that handles the Sports Pad input in a way that makes the games playable? Meka allows to use the mouse for it, but it always stops where the mouse pointer would reach the border of the screen. I've tried some other emulators, but none of them seemed to support it at all...\r\n\r\n[B] Debugger: Variables window with live filter.\r\n[B] Debugger: Preview memory regions on hovering register/instruction.\r\n\r\nAdd a super-fast mode (faster than 1/9 for CLOCK-ing things like zexall)\r\n\r\nDebugger seems generally weird at 1/9 frameskip, stepping instructions when not expected?)\r\n> As for the 1/9 bug: I think it is to do with the keyboard repeat code. Entering \"j 0\" gets me to 0 + however many instructions the debugger thinks I have held down Enter for. In frameskip mode I guess it is interpreting repeats after a very short pause. It ought to be realtime-based instead of emulated-frame-based?\r\n\r\n\r\nE-SWAT http://smspower.org/forums/viewtopic.php?t=8069\r\n\r\nMapper_Get_RAM_Infos: Support for multiple RAM regions (eg: Taiwanese 8 KB RAM adapter mapper)\r\n\r\nDebugger: option to auto-start on ROM load (one can always do a RESET)\r\nDebugger: Add \"Did you mean $XX\" when parsing register name that matches two digit hex number (eg: DE)\r\n\r\nSF-7000 emulation: write always access to RAM (even when ROM is mapped) - via honestbob\r\n\r\nZ80 PC history command (great to figure out caller)\r\nZ80 branch history command\r\n\r\n  callee address\r\n  loop 1\r\n     loop 2\r\n       ..\r\n     loop 3\r\n       ..\r\n  ret\r\n\r\n\r\nMeka 0.80 check list\r\n[A]- fix sound: latency, 50 hz, other modes?\r\n- obsolete/hide blitter interface\r\n- debug version leaves allegro.log is current directory\r\n- start window is in background when running from explorer\r\n- solve vsync and refresh rate issues, at least be able to enable vsync?\r\n- have a pass at checking all features\r\n//- tilemap viewer: mode 2: print more infos. add more addr settings.\r\n- new feature: sprite viewer?\r\n- new feature: audio channel disable? (psg & fm)\r\n- reorganize inputs configuration panel?\r\n- pro action replay\r\n- end-user timing (message time, double click) shouldn't be measured in emulated frames\r\n- incorrect rom on command-line leaves a zombie thread? (sometimes?)\r\n//- gui: show shortcuts\r\n- GUI HOVERING SCROLL BAR BROKEN\r\n\r\nIn Hang-On (Safari Hunt) -> glitch even in PAL mode\r\nI've noticed that part of the track shows in the background where it shouldn't (shown in screen shot with a highlighted red square box), also in regards to the track itself when it turns left or right, the track kind of looks like it judders.\r\n\r\nOther than that not noticed any other problems and nice work on the sound :), works fine with my Creative X-Fi Xtreme Gamer, also forgot to mention I'm using the latest 0.80 build.\r\n- bug reports:\r\n  - \"When pausing with the F12 button, the screen becomes out of align by showing a bottom border and a right border. \"\r\n  - \"Sometimes the mouse freezes for a couple of seconds. (I got this 3 times in about a 20 minute play). \"\r\n  - \"I plugged in a USB-PSX converter before starting again and it did not crash then but any input instantly went Stick 0 Axis 0 -\"\r\n\r\n----------\r\n\r\nSuper Boy II (KR).sms is 48 KB with duplicated 16 KB\r\n\r\n5 GG dumps\r\nhttp://smspower.org/forums/viewtopic.php?p=64723#64723\r\n\r\nI would like Meka v0.74 to contain a Extra Debug mode called ''Sprite/OAM Viewer'' as seen by some modern emulators such as\r\nBGB/No$GMB/NO$C64/Etc.\r\n\r\nNot only that, SG1000/SC3000/Ect. and compatible Sprite and Name Table viewer. Can be used as a reference to\r\ngain more programmers for older SEGA systems\r\n\r\nBut the only SEGA console emulators with Sprite viewer capability is a few 16bit Genesis/Mega Drive, Which I could not\r\nfind a modern one yet besides NES/GB(Color) stuff.\r\n\r\nSo I think it will be more helpful to debuggers for doing Sprites, if there is one for MEKA, It will become superior to\r\nthe other Z80+VDP emulators. Beating MSX(2/+) Somehow\r\n\r\n- Speed above 1/9 (for zexall)\r\nDebugger: Count point. or full memmap count points.\r\n\r\n(Actually, some way to enter a super-turbo-fast-forward mode (more than 1/9 frameskip) might be nice, especially if it can still hit a breakpoint directly. Debugger seems generally weird at 1/9 frameskip, stepping instructions when not expected?)\r\n\r\nFix default .sc mapper (eigo sakubun)\r\nNamely if ROM is bigger than 32 KB don't stupidely ignore the rest of the data!!\r\n\r\nDebugger: Many interesting mails from Maxim!\r\nDebugger: Add support for F register in SET command (or individual flag, ZF, CF, etc.)\r\n\r\nCommand line file not found = Win32 console crash\r\n\r\n  /------------------\\\r\n/-|  MEKA TODO LIST  |-------------------------------------------------\\\r\n| \\------------------/                                                 |\r\n| Todo:                                                                |\r\n| - Clean this list, add a bug-priority system.                        |\r\n|   Maybe switch to an internet bug tracking software?                 |\r\n|----------------------------------------------------------------------|\r\n| Note:                                                                |\r\n| - MEKA IS FULL OF INCORRECT EMULATION BEHAVIOURS.                    |\r\n|   MEKA IS NOT THE BEST REFERENCE OF HOW THINGS ARE OR WORKS.         |\r\n|   CONSULT TECHNICAL DOCUMENTATION INSTEAD (eg: SMS Power! dev wiki). |\r\n|   IF YOU HAVE ANY DOUBT, FEEL FREE TO ASK.                           |\r\n|----------------------------------------------------------------------|\r\n| Packager Note: Always make plenty of verifications before packaging. |\r\n| - Check MEKA.INP                                                     |\r\n| - Check MEKA.MSG content, WIP, merge updates                         |\r\n| - Package a default generated .CFG file                              |\r\n|----------------------------------------------------------------------|\r\n| Main axises of work:                                                 |\r\n| - fix sound engine (timing problem, ask me, I can explain why)       |\r\n| - improved video (blitters, stretching, sync, triple buffering)      |\r\n| - inputs system improvement (analog sources, map all features, etc)  |\r\n| - full featured debugger/hacking tools                               |\r\n| - fill new database entries (redump/sort)                            |\r\n| - tape emulation                                                     |\r\n| - better SF-7000 disk support (write & save)                         |\r\n| - new savestate format + better manager (icons, etc)                 |\r\n\\----------------------------------------------------------------------/\r\n\r\n-----------------------------------------------------------------------------\r\nTHE YET UNSORTED MESS (this is my notepad basically)\r\n-----------------------------------------------------------------------------\r\n\r\nDefine a string in the config file, eg:\r\n debug_breakpoint_label_prefix = \"break_\"\r\nThen, when loading .sym files, automatically add breakpoints on\r\nmatching labels. This saves me typing \"b <label>\", and is designed for\r\n\"temporary\" breakpoints on lines that normally would not otherwise\r\nhave a label.\r\n\r\nhttp://www.smspower.org/forums/viewtopic.php?t=9478\r\nNow I have a question. In some Master System games (made at 1993 to be exact) such as\r\nSonic Chaos, Deep Duck Trouble have problems. Sometimes they are fine, other times the\r\ngames crash after they get to the title card(Level Name) as these problems have been\r\nin previous releases.\r\n\r\nProppy session debugger notes:\r\n- 'breakpoint' window list\r\n  - show list\r\n  - with enable checkbox\r\n  - edit/add fields\r\n- breakpoint write: only when values changing, !=\r\n- datadump sprite output is weird\r\nDebugger: bind RELOAD rom on a key, or add 'reload' command\r\n\r\n<cgfm2> can I increase the SMS display window size in GUI mode?\r\n\r\nJacko: Also I was playing Shanghai before with the FM Chip enabled and the music slowed down gradually\r\n(like a record slowly stopping) and then it slowly speed up again, MEKA has only done it once\r\nso it is hard to tell if it was my PC doing something or it was MEKA.\r\n\r\n- Data\r\n  - Update/remove Themes section from web page.\r\n  - Tweak country flags for proper color now that there's no more palette.\r\n\r\nGame Recording:\r\n- Topic\r\n  http://bisqwit.iki.fi/nesvideos/forum/viewtopic.php?t=3726\r\n- VBM Format\r\n  http://bisqwit.iki.fi/nesvideos/VBM.html\r\n- Desired Features Wiki\r\n  http://bisqwit.iki.fi/nesvideos/DesiredFeatures.html\r\n\r\n- Add PAL/SECAM/NTSC (Auto) mode to be more clear\r\n  See http://www.smspower.org/forums/viewtopic.php?t=6656\r\n\r\n\"if you have the option fullscreen on load enabled it only fullscreens\r\n if you load a rom manualy form the filebrowser but if you startup meka\r\n from the command line with a rom name it loads the rom but doesnt go\r\n full screen.\"\r\n --> add a separate option for both cases.\r\n\r\n-----------------------------------------------------------------------------\r\nPRIORITY / FOR UPCOMING NEXT VERSIONS\r\n-----------------------------------------------------------------------------\r\nAlright, those things right here may not be always super important, it's\r\njust that I noted them at the top of the file, thinking it would be worth\r\ndoing them now and some are quick work.\r\n-----------------------------------------------------------------------------\r\n\r\n- Check galaxy force (supposed bug, couldn't reproduce)\r\n  http://www.smspower.org/forum/messages/19568.html\r\n\r\n- Add auto SK-1100 enable.\r\n\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------\r\n WINDOWS PORT PRIORITY/NOTES\r\n-----------------------------\r\n - THE AUTO FRAME SKIPPER SUCKS\r\n - SOUND SUCKS\r\n - Windowed mode should fit the actual game screen size instead of having\r\n   a screen-resolution based size (320x240)\r\n   - This is a problem with how the blitter system works now.\r\n\r\n-----------------------------\r\n CODE\r\n-----------------------------\r\n - Write a MEKA coding style documentation.\r\n\r\n-----------------------------\r\n WEBSITE\r\n-----------------------------\r\n - MEKA 0.59 is missing from all archives?\r\n\r\n-----------------------------\r\n VGM\r\n-----------------------------\r\n - Built-in VGM player (implement Maxim VGM stub)\r\n - GD3:\r\n   - Japanese GD3 (for systems at least)\r\n   - Option to create VGM without GD3.\r\n   - Store user name somewhere, now that MEKA.KEY file is obsolete.\r\n - Check http://isweb38.infoseek.co.jp/art/rophon/data/download.htm\r\n - Tool:\r\n   - Automatic trimming.\r\n   - PSG access addresses logger/hacker (see notes under DEBUGGER).\r\n - Add feature to only start logging \"when sound start\" (for WAV log)\r\n\r\n-----------------------------\r\n ROM INFORMATION\r\n-----------------------------\r\n - Add an applet showing ROM+DB information (checksum, country, version, etc.)\r\n\r\n-----------------------------\r\n NAMES / DATABASE\r\n-----------------------------\r\n - Add Pirate flag ?\r\n - Better syntax error verbosing (currently there's none).\r\n - Generally:\r\n   - Check Maxim's old & new e-mails.\r\n   - Check Kevin Chase e-mails.\r\n   - Fixes missing \"the\".\r\n\r\n-----------------------------\r\n PERIPHERALS/INPUTS EMULATION\r\n-----------------------------\r\n - Emulate port 3F properly.\r\n   Currently, its implementation is a joke.\r\n   This however introduce some \"interface\"/\"user-side\" problems:\r\n   - In-game changing of country may be fatal to non-joypad games.\r\n     Warn for them? What else could be done?\r\n - Test Handle Controller / Bike Controller for SG-1000/SC-3000.\r\n   How does they actually works? Why do they mention only a few games\r\n   on the box, are they actually any different or it is just because\r\n   one is left/right and other is up/down only?\r\n - SDI might supports Sports Pad, figure out hardware detection if so\r\n - Proper/better Light Phaser emulation.\r\n   - Again, implementation is a joke. / but, it works.\r\n   - Check Charles' SmsGun test.\r\n\r\n-----------------------------\r\n PERIPHERALS/INPUTS HOST\r\n-----------------------------\r\n - Support analog axis, damnit!\r\n - Add Message when changing Player 2 input (?)\r\n - Configuration of ALL inputs keys (functions keys, etc...)\r\n - Support mouse wheel for emulation.\r\n - Paddle Controller emulation:\r\n   - Allows to setup sensitivity\r\n   - It is possible to do something better ?\r\n - Support for MD direct pro driver (see unfunk's e-mail)\r\n - Inputs Recording\r\n - Interface mouse driver (who cares anymore).\r\n - Keyboard not qwerty\r\n - Player 2 default inputs on right side of the keyboard ?\r\n - Add both buttons & combo inputs\r\n - Be able to configure Rapid Fire speed.\r\n - Cursor is repositionned when enabling light phaser within GUI\r\n - Support for more than one mouse (for light phaser game)\r\n\r\n-----------------------------\r\n SEGA KEYBOARD (SK-1100)\r\n-----------------------------\r\n - Automatically enable (based on DB directive).\r\n   - Keep a flag to know if was automatically or user activated.\r\n     If automatically, then on ROM change it then can be disabled.\r\n - Clickable picture on the GUI (with sticky keys).\r\n - When SK-1100 is enabled, Monaco GP difficulty selection runs slower.\r\n   It is normal behavior?\r\n - Show sticky keys with PC keyboard leds.\r\n - SK-1100 is difficult to type with, and Mekaw's keyboard is strange:\r\n     \"]\" is \"[\"  \"[\" is \"@\"  \"\\\" is \"]\"\r\n     \"yen\",\":\",\"^\"and\"@\" don't type.\r\n   Maybe more. Please check it.\r\n   I think this is solved.\r\n\r\n-----------------------------\r\n BLITTERS\r\n-----------------------------\r\n - Fallback to safe mode\r\n - Completely revamp the blitter systems.\r\n   - Be able to handle blitter per system (SMS, GG..) and mode.\r\n   - Add x3, x4 blitters, separate X and Y (be able to do a 2x3 blit, etc..).\r\n     All combinations should be working.\r\n   - Add stretching blitters (especially for windows version)\r\n   - Lots of info in mind or on paper. Need to sort out, and maybe write\r\n     a short specification document.\r\n - Selection of GUI video mode in interaction configuration window.\r\n - Avoid to quit when video mode is invalid\r\n   - Handle video mode priority list, etc..\r\n - For Game Gear:\r\n    H*2/Y*3 in 320*480, H*4/Y*3 in 640x480..\r\n - Filters:\r\n   - Implement 2xSai filter.\r\n   - Implement Scale2x filter (scale2x.sourceforge.net)\r\n   - HQ filters\r\n     - 32 bits version\r\n     - HQ2X, HQ4X\r\n - Resize window\r\n   - Easy to do for GUI.\r\n   - Support for fullscreen blitter (hmm..?)\r\n - [Win32] Support OS resolution change.\r\n\r\n-----------------------------\r\n VIDEO\r\n-----------------------------\r\n - 3D glasses:\r\n   - red/green mode (blending)\r\n   - http://www.edimensional.com/products/edglasses.htm\r\n\r\n-----------------------------\r\n VDP/VIDEO EMULATION\r\n-----------------------------\r\n - SMS VDP Tester http://smspower.org/forums/viewtopic.php?t=10695\r\n- 224/240 lines mode should only be activated if both bits are set (see Charles's doc)\r\n - VDP Model differences\r\n   - Add VDP Model selection somewhere in GUI (useful for programmers).\r\n   - VDP Model 315-5124: Doubled sprites bug (see Earthworm Jim)\r\n   - Write to CRAM on legacy VDP (which?) should not update palette (only CRAM).\r\n - Fix interrupt emulation and VDP control over the Z80 IRQ Line.\r\n - Other VDP Model differences (see Interactive Sprite Test, bug on SMS 1)\r\n - Palette\r\n   - Support TMS9918 palette as on Japanese SMS (and Mark III)\r\n     http://www.purose.net/befis/halloffame/msx_col/\r\n   - Support TMS9918 palette from http://junior.apk.net/~drushel/pub/coleco/twwmca/wk961118.html\r\n - TMS9918\r\n   - Render on a line basis to fix \"Zoom Effect #1\" demo (grr..)\r\n - Border emulation (this is a big miss)\r\n - Handle VRAM Accesses while refresh is ongoing (for programmers)\r\n   See http://www.smspower.org/forums/viewtopic.php?t=7849\r\n - Emulate sprite overflow (9th sprite) (VDP status bit 6 set). Should be fairly easy.\r\n\r\n-----------------------------\r\n TECHINFO APPLET\r\n-----------------------------\r\n - Standardize names, registers names, etc.\r\n - Redo from stratch? Separate applets for different system components?\r\n\r\n-----------------------------\r\n DEBUGGER\r\n-----------------------------\r\n - Bugs:\r\n   - inst_after > pc-temp appearing in several cases (eg: Super Basketball demo).\r\n   - Savestate/reset/bios seems to mess with breakpoints?\r\n     Check coherency and switching between mainloops (emulation standard/debug, no emulation)\r\n   - Backspace in memory editor widget reset machine\r\n - Debugger:\r\n   - Console log: add full print history + a scrollbar.\r\n   - Button to enable/disable exclusive focus.\r\n   - Auto reload ROM option\r\n     - Win32: possible to setup a notification\r\n - Disassembly\r\n   - Option to display cycle count next to each instruction.\r\n - Breakpoint:\r\n   - Add breakpoint from memory editor and/or disassembly window.\r\n     - Simple version: click on disassembly window for breakpoint.\r\n   - Conditionnal breakpoints:\r\n     - Simple masking feature\r\n     - Full expression evaluation/test?\r\n     - At nop nop break (macro or helper).\r\n     - Break at register write ?\r\n   - Z80 read/execute are not perfectly differenciated (opcode 1st byte is X, then it is R)\r\n   - Hooks:\r\n     - VDP register/status\r\n     - PSG/VRAM/dedicated break (per channel/address/tile/whatever).\r\n     - Generally, much more possible things to add.\r\n - Datadump could be redirected to debugger console.\r\n - Small Bug (may not considered as one bug actually): Debugger ON, play, pause, debugger OFF -> machine gets unpaused.\r\n - Scroll thru disassembly\r\n - Completion\r\n   - Better contextual completion, supporting per-command kind of parameter\r\n     (eg: break cl[tab] -> clear)\r\n     - Make the command line parser take additionnal flags, and be able to execute\r\n       commands as well as just returning a list of words depending on the parsing\r\n       context.\r\n - Profiling feature\r\n   - Display line/cycles better\r\n   - User settable timer, global cycle counter.\r\n - Print\r\n   - Find a solution to the problem of not being able to print result that are not 16-bits\r\n - Symbols\r\n   - Automatically select name/addr symbols find in \"SYM\" command\r\n   - Keep track of source symbol, by keeping t_debugger_value all along the chain.\r\n   - Figure out a way to keep symbol references and have them updated on ROM reload.\r\n - SET command\r\n   - Access to non Z80 registers.\r\n   - Indexing.\r\n     eg: \"set RAM[0] = 0\"\r\n - MEMEDIT command\r\n   - Specify address\r\n   - Specify bus (standardize)\r\n - SEARCH command\r\n   - Bytes/ascii search\r\n   - Access to all kind of memory, once we have the proper abstract (see above)\r\n - VAR (?) command\r\n    \" As promised, here's my idea.\r\n      v address var1 [var2 [var3...]]\r\n      When execution reaches \"address\", the contents of var1, var2 etc are reported in the\r\n      message window and execution is not stopped. var1 etc can be a register or an address\r\n      in the Z80 memory map. In other words, it allows one to spy on parameters being passed\r\n      to functions, as well as intermediate variable values inside functions, without having\r\n      to set breakpoints and watch those values manually using memory dumps or the register\r\n      display.\r\n      Letter v is for \"variable\", since I can't think of a better letter to use. \"\r\n    - \"wv\" (watch variables) ?\r\n - Tilemap viewer:\r\n   - Support vertical lock (gauntlet, golvellius...).\r\n   - Proper support for extended modes requires resizing window (tilemap becomes 256*256).\r\n - SOURCE command:\r\n   Load commands from a text file. Useful for storing per-project breakpoints.\r\n - Expression evaluator:\r\n   - Unary operators -, !, ~\r\n   - Proper operator priority. Currently two level: +/- gets low priority and\r\n     all other higher priority. Requires building a proper evaluation tree.\r\n   - Access to data table RAM[0] (this gets more complex...)\r\n - Memory Editor:\r\n   - Memory editor page focus is lost on ROM change.\r\n   - Button to enable/disable exclusive focus.\r\n   - 2/3 byte display/editing\r\n   - Highlight edited digits, add backspace support\r\n   - Dump button (calling datadump)\r\n   - Edit ASCII\r\n   - Lock a writing value\r\n   - Show modified/written values.\r\n     How do I do that? Modified since when? Could be useful when stepping in code.\r\n     - Use debugger hooks + highlight feature to show read/written values.\r\n - Memory find:\r\n   - MEMFIND command.\r\n - Access to machine data in a standardized way (code/library for programmer,\r\n   standardized syntax for end-user functionnalities)\r\n   - 8/16-bits differenciation:\r\n     - WLA DX uses nnnn.b and nnnn.w for ambigous opcodes on other CPUs\r\n       Use a similar system to remove ambiguity!\r\n   - Extract generic code to access memory blocks from memory editor, stick\r\n     them in a generic interface in t_machine. Usable by memory editor, data\r\n     dumper, debugger M command.\r\n   - eg: registers: HL,AF,A, etc. memory: mem[HL]\r\n   - User shortcuts. HL would be in fact cpu.hl ?\r\n   - Z80 access:\r\n    - Register edit\r\n    - CALL command\r\n      - Execute a CALL on the Z80, allow easy quick hack\r\n      - Or more generally, allow inline instruction execution\r\n   - Abstract Marat's core to be able to switch later.\r\n   - Access to the previous state (automatic save state on each user step)\r\n     - Require changing savestate code to work on a memory buffer.\r\n   - User constructed GUI panels showing you info you want.\r\n     Could display registers, any part of memory, tiles, etc.\r\n     Allowing to create panels for custom debugging.\r\n - Input locker\r\n   - Set input bits manually using check boxes, being able to set inputs\r\n     at any point.\r\n - Scripting\r\n    - A breakpoint can trigger a call.\r\n    - Support for debug configuration file/script per ROM/project.\r\n - Call Stack\r\n   - Keep a call stack updated (using a modified Z80 core?)\r\n   - Log wether each memory location was written as 8 or 16 bits?\r\n - Tools:\r\n   - Sprite viewer\r\n     - Select individual sprites, shows infos\r\n   - Sprite ripper\r\n     \" One of the first modified versions of Gens included a sprite ripper. It would\r\n       examine the coordinates of the sprites, and when sprites lined up exactly it\r\n       would export them to a separate image. So long as a regular grid of 8x8 hardw\r\n       are sprites is used to build up arbitrarily-sized character sprites (the\r\n       majority of games), this should work well. \"\r\n   - Cycle counter.\r\n   - SDSC Debug Console.\r\n   - Warn incorrect (non standard) VRAM/port accesses.\r\n   - Warn interrupt if VDP latch is set (98% of the time I guess it\r\n     can lead to a bug).\r\n   - Warn on return of interrupts if Z80 registers are differents from entering (except shadow)\r\n   - PSG access addresses logger/hacker\r\n     Show checkbox for all location accessing to PSG, allows to disable some.\r\n     Could be super useful for VGM hacking/logging.\r\n\r\n-----------------------------\r\n PATCH\r\n-----------------------------\r\n - Be able to reload MEKA.PAT in runtime (helpful for hackers), as a quick\r\n   solution to the lack of features.\r\n - Add info about what's being patched (especially when using * as CRC).\r\n - Add IPS support.\r\n - Add ASM opcodes supports (-> embed an Assembler).\r\n - Start thinking about this feature in the bigger picture as a part of\r\n   the debug/hack/cheat stuff. Avoid implementing 2 or 3 times to same\r\n   stuff in different components.\r\n\r\n-----------------------------\r\n CHEATING\r\n-----------------------------\r\n - Cheat entry database (equivalent to live .pat)\r\n - Action Replay SMS/GG\r\n - Game Genie GG\r\n - Persistant cheat database?\r\n - Cheat masters:\r\n   - MugUK\r\n   - Sweater Fish Deluxe\r\n   - rouken (rouken AT bol.com.br)\r\n\r\n-----------------------------\r\n KEYBOARD MAPPING\r\n-----------------------------\r\n - Generally, hotkeys with ALT/CTRL are not a good idea\r\n   (what does the above statement suggest? I don't remember now.. argh)\r\n\r\n-----------------------------\r\n FILE LOADER / BROWSER\r\n-----------------------------\r\n - Multi roms in single ZIP file support\r\n   - At least, pick the biggest one with correct extension (the 'rom')\r\n   - Warn user ?\r\n - Sort should give low priority to .ext -> \"test.sms\" before \"test (jp).sms\"\r\n - Still a problem with FB directory name load? (Don't think so.)\r\n - Key should work based on focus, to function even with SK-1100 enabled\r\n - Can \"read names\" made faster?\r\n - Different color/icon per system\r\n - Loaded ROM history\r\n - Global computer file database (to run a game from its ID/CRC/whatever)\r\n   Then you can even imagine SMS Power! producing URL/links/datafile read\r\n   by MEKA to run a given game from its museum page entry.\r\n - Mouse wheel handling should not set selection, just scroll.\r\n - Directory change notification:\r\n   - [WIN] There's something, I know.\r\n   - [LINUX] See SIGIO, linux/documentations/dnotify.txt\r\n\r\n-----------------------------\r\n GUI\r\n-----------------------------\r\n - Change resolution / video mode: need to interface in menus.\r\n - Fade: only 32-bits mode. supported\r\n - Font: Move the standalone tilde lower if possible (where does it apply? forgot)\r\n - Background filling is not correct is GUI resolution ratio is not 4:3\r\n - Switch fullscreen font to contains bold black+white\r\n   (currently multiple draw pass are done, which is hell slow)\r\n - Leaks:\r\n   - gui_box_delete() doesn't delete widgets\r\n - Documentation viewer\r\n   - Add generic text viewer applet (that user can use to load his stuff).\r\n   - Fix bouncing with pageup/pagedown\r\n - Move windows bug (press mouse 1, keep 2 pressed, release 1, etc..)\r\n - Online contextual help (using text viewer applet maybe?)\r\n   - Eg: You would press F1 anywhere and it pop some info about the current\r\n     applet or widget focus.\r\n - Rewrite popup menu code\r\n    - Menu moves instead of going off-screen (see non-english languages!)\r\n      - Would be useful to use within windows (as a combo box)\r\n    - Support for more than MAX_ENTRYS entrys\r\n    - Support keyboard\r\n    - Show Hotkeys\r\n    - Multi part menus for like the big theme menu\r\n - Message box: load success/infos message order\r\n\r\n-----------------------------\r\n GUI MENUS\r\n-----------------------------\r\n - Consistant hotkey behavior.\r\n - Menu cleanup:\r\n  - Add volume control.\r\n  - Remove \"screens\"?\r\n  - Messages:\r\n    'Tiles Viewer' -> 'Tile Viewer'\r\n    'Country' -> 'Region'\r\n    'TV Type' -> 'TV Mode'\r\n    'Fullscreen mode -> Game mode\r\n    ?\r\n\r\n-----------------------------\r\n TILE VIEWER\r\n-----------------------------\r\n - Show everything in modes 0->3.\r\n - Mini bg/fg palette selectors in modes 0->3.\r\n - Zoom tile.\r\n\r\n-----------------------------\r\n SC-3000\r\n-----------------------------\r\n - Printer emulation\r\n - Tape drive emulation\r\n   - Find out if encoding used in Music/Lode Runner/C_So! is standard\r\n   - Common, do it. The world (and A.Wheeler) deserve it.\r\n\r\n-----------------------------\r\n SF-7000\r\n-----------------------------\r\n - Verify sprite collision on Gold Miner & Froggy ??\r\n   - This crazy code seems to requires line-per-line collision detection on a TMS9918 mode!\r\n - Floppy disk\r\n   - Correct way of handling disk swapping\r\n   - Writeable disks (how good/bad does it works?), -> and, to file (need a policy or different extensions)\r\n   - Write protection\r\n   - Be able to create empty disk image\r\n   - Disk viewer utility\r\n - Centronics port emulation\r\n - RS-232 port emulation\r\n - Sort out new SF-7000 disks\r\n - Find docs about the FDC\r\n\r\n-----------------------------\r\n COLECOVISION\r\n-----------------------------\r\n - May want to drop ColecoVision? Why adding more weight...\r\n - ROMs:\r\n   - New Roms from MyColeco (gamepack + space invaders)\r\n   - Sort out homebrewn coleco Roms\r\n   - Just drop everything and import a GoodCOL set (or similar).\r\n - Check out Colecovision NMI fix from MESS\r\n - Check FLICKER for Colecovision roms: Antartic Adventure, Sewer Sam, Squish'em Sam\r\n - Problem with Dragon Fire savestate.\r\n - The Christmas demo is buggy because MEKA remove what it think is a footer (the ROM\r\n   is not a 4k multiple and it's exactly +256 bytes, so my code think it is a footer)\r\n - Games:\r\n    - Super Cobra display is off\r\n    - Christmas needs to run in PAL/SECAM mode, without footer removing.\r\n    - Donkey Kong: freeze after level 1\r\n    - Fix Dragon Fire (see Dennis Stith, try Koleko 1.31)\r\n    - Buck Rogers -> 5617\r\n    - Fathom -> 7313\r\n    - Space Panic -> sometimes freeze\r\n - Fix player 2 control\r\n - Add weird controllers emulation (make \"Turbo\" (coleco) works for Opi :)\r\n - Check cabellero bug reports\r\n\r\n-----------------------------\r\n GAME GEAR\r\n-----------------------------\r\n - Option to show entire effective screen\r\n - Option to stretch SMS size back to 160x144 screen. Figure out the pattern.\r\n - LCD persistance simulation\r\n   (Super Monaco GP 2, Space Harrier, Ninja Gaiden)\r\n   > Ninja Gaiden:\r\n   > In 3rd act there are some flickering (windows on skyscraper).\r\n   > In 2nd act, a strange \"flying\" & flickering sprite may appear (gunman).\r\n   > Will there be more...? ;)\r\n - Gear-to-gear emulation.\r\n\r\n-----------------------------\r\n ARCADE\r\n-----------------------------\r\n - Emulate SMS arcade board (Opa Opa, Tri Formation, Solomon no Kagi)\r\n   - The ports are figured out.\r\n   - Need to figure out the dipswitches.\r\n   - Add a proper interface.\r\n - Emulate SG-1000 arcade board (Champion Boxing, Champion Pro Wrestling)\r\n   - Require encryption emulation.\r\n   - Separare OPCODE read and DATA read in Z80 emulator (for encryption).\r\n     That's useful anyway for debugger trapping.\r\n - Interface coin insertion.\r\n\r\n-----------------------------\r\n BIOS\r\n-----------------------------\r\n - Use external BIOS files.\r\n   - Load from a given directory.\r\n   - Implement hack (disablable) to remove cart checks within BIOS.\r\n     This is not \"accurate\" emulation but much better for users.\r\n     As long as it is disablable.\r\n - Implement port 3E properly.\r\n - Support for the different slots. How does the user work with that?\r\n   I certainly don't want to make it \"MesaDX complicated\" for a gamer.\r\n   Automatically select cartridge slot (or cart is ROM < 32 kb), and\r\n   maybe allow a manual setup.\r\n - How would old savestate works once this is properly emulated?\r\n   - Can we assert that games keep value stored in C000?\r\n     - Replace the value?\r\n   - Should maintain legacy emulation?\r\n\\ - Check Super Racing interesting boot code (hmm? it is an obsolete thought?).\r\n - Sort BIOS dumps.\r\n - Allow to boot up other machines (Colecovision/GG) without ROM.\r\n   - Need to be able to select machine.\r\n\r\n-----------------------------\r\n HARDWARE IO\r\n-----------------------------\r\n - Port 3E\r\n   - I/O (especially YM2413 could help Maxim's SMS VGM player)\r\n - Port F2\r\n   - Bit 0 disable PSG/FM mixing?\r\n - Read from 0x7E on SG-1000/SC-3000 return a value based on R register.\r\n - I/O map differs between SMS1/SMS2/etc.\r\n   - Wonder Boy in Monster World relies on that to distinguish them!\r\n - Check GG pirate cards menu dumps and emulate mapper\r\n - Implement horizontal counter latch.\r\n\r\n-----------------------------\r\n MAPPER\r\n-----------------------------\r\n - Move default MAPPER in driver structure (code)\r\n - Mappers emulation based on mask is incorrect if ROM is not power of 2\r\n   and attempt to map a non existing page in a range MEKA think is ok.\r\n - Emulate 3-in-1 mapper (Master Games 1, etc..).\r\n - Emulate 0xFFFC bits to shift starting pages by a certain amount.\r\n - Check out Earthworm Jim / Arena cartridges for an EPROM?\r\n - SG-1000 RAM is only 2 kbyte\r\n - Check out Monaco GP 40k having Safari Hunting included - pirate cartridge?\r\n   - Was figured out elsewhere. See dev forum post.\r\n - Check Flash / Desert Speedtrap cartridge -> the chip is 8kb!\r\n   - Data should not be saved. DB directive?\r\n\r\n-----------------------------\r\n SMS TESTS\r\n-----------------------------\r\n - Write a program that print out at which line/cycle NMI \"trigger\".\r\n   Can the bug I have in Fantastic Dizzy be reproduced on a real SMS with\r\n   some bad luck, that is what I want to know. (Otherwise, seems like a Z80 bug.)\r\n - Write a program to be able to find out at which cycle/h-pos the h-scroll\r\n   is latched. // Didn't Charles figured that out now?\r\n - Write a program that print R - can its 'period' be simulated better?\r\n   - This is nonsense. Just implement a proper Z80 emulator and it'll do it.\r\n - Write a program to find original Rapid Fire speed/period.\r\n - Write a SMS program to figure out exactly which pixel are shown on GG\r\n   screen when is SMS mode (this has been discussed on SMS Power dev).\r\n\r\n-----------------------------\r\n Z80 CPU\r\n-----------------------------\r\n - Register R:\r\n   - Investigate Rastan, register R (bit 7), use for bonus?\r\n   - Differently emulated with different Z80 cores?\r\n - Implement a good Z80 emulator.\r\n   - Common, do it.\r\n - Test with Zexall\r\n   - http://www.mdfsnet.f9.co.uk/Software/Z80/Exerciser/\r\n   - Proper SMS port. See forum.\r\n - Support Z80 overclocking -> increase iperiod for all lines, or only VBL\r\n - Try to implement Dayvee's Z80 emulator\r\n - Undocumented flags (ref: http://www.srcf.ucam.org/~pak21/cssfaq/tech_z80.html#UNDOC)\r\n - Proper iperiod pal/secam + CPU speed pal/secam!! (3.54689)\r\n - OUT (C), 0 variant\r\n   http://www.smspower.org/forums/viewtopic.php?t=9412\r\n\r\n-----------------------------\r\n SPEED\r\n-----------------------------\r\n - Those should be calculated on frame rate:\r\n   - Double-click speed\r\n   - Message speed\r\n   - Key repetition speed\r\n (currently using frame display counter, which is obviously bad)\r\n\r\n-----------------------------\r\n MISC\r\n-----------------------------\r\n - Detect empty overdump (00/FF).\r\n   It used to be ok with MekaCRC but not with CRC32.\r\n - Detect empty half (eg: 256 kb game with another 256 kb full of FF).\r\n   This is often the case on some ROM chip. This would help ROM dumpers.\r\n - Display AUTHOR field from database (and others?).\r\n - Support for other compression format:\r\n   - GZ\r\n   - RAR\r\n - /_SYS_INFOS doesn't show correct OS version since Allegro is not yet installed\r\n - Remove SPACE problem in MEKA.CFG (and other files, maybe)\r\n   - Can use new tools used by MEKA.NAM parser and add quotes to the sentences\r\n - Frame-per-frame (ALT-F12) done correctly (this is coder luxury...)\r\n - Be able to change pcx/, saves/ directories, etc.. with templates\r\n - Implement quizz. :)\r\n   - Hardcode mode: need to answer a question to play.\r\n - Check Richard Bush' ASM Stuff (ooooold)\r\n - Static cartridge loaded (keep track of loaded cart when quitting).\r\n - Auto pause (pause when click on menu, etc..)\r\n - Command line parameter to start in fullscreen.\r\n\r\n-----------------------------\r\n NETWORK\r\n-----------------------------\r\n - Standard 2 player gaae.\r\n - Gear-to-gear with 1 GG on each side.\r\n - Sharing games, multi-games, SMS party project.\r\n   - Need to cleanup a lot of side-effects, globals, determinism issues.\r\n\r\n-----------------------------\r\n SAVESTATES\r\n-----------------------------\r\n - Savestates slots showing with filled/empty boxes.\r\n - Thumbnails?\r\n - Press Fx and select slot. Much easier. Reuse that for blitter!\r\n   - Generally, allow some kind of GUI widgets in fullscreen mode.\r\n - Format: add MEKA version field (text?)\r\n - Separate savestates in directory per system.\r\n - Message save + snail game/BIOS\r\n - Importer:\r\n   - Frozen format (http://www.smspower.org/forum/messages/18383.html)\r\n   - BrSMS format ?\r\n - Savestates manager\r\n   - Scan/move everything. Avoid the plagging \"renaming\" problem.\r\n - Design a whole new, documented, shared, chunked savestates file format\r\n   - This is the way to go.\r\n\r\n-----------------------------\r\n MESSAGES / LOCALIZATION\r\n-----------------------------\r\n - Add code to verify sync/order of message definitions & tables.\r\n - Switching to full multi languages:\r\n   1. Switch to using TTF font.\r\n   2. Cleanup fontsize dependant things / GUI code\r\n   3. Implement non european language support (Japanese!) and add proper fonts.\r\n\r\n-----------------------------\r\n GAMES NOTES\r\n Some may be obsolete.\r\n-----------------------------\r\n - Safari Hunting: original cartridge has $4000-$BFFF unconnected,\r\n   (allowing to use this area as a pseudo-random number generator ?)\r\n   Check out if the game use this area and how.\r\n - Excellent Dizzy: Go-Dizzy-Go! attract mode screws up in MEKA.\r\n - Out Run: PSG noise leftover in FM mode.\r\n - Daffy Duck in Hollywood menus (verify on a real PAL/SECAM system)\r\n - Sangokushi 3: try to finds why demonstration is not the same as on a real system (R?)\r\n - Championship Hockey: reset, glitches ? See on real system.\r\n - Fix formula 1 !! ? (any moer problem?)\r\n - 20-em-1 timing problem (currently patched)\r\n - F-16 Fighting Falcon: keyboard two players mode? See MK3 Page\r\n - Rise of the Robots - raster ok? This game is too ugly for my eyes\r\n - Shining Force 2 bug :( try to play the game from scratch again\r\n - Sonic Blast in European mode\r\n - Why does Psycho Fox run in Japanese when keyboard is enabled ?\r\n   - Well, it's safe to say that my country/D? ports emulation is a joke.\r\n - Hang On / Safari Hunt (cartridge, NOT bios) raster glitches are\r\n   not located at the same place between SMS and Meka (timing?).\r\n - Cosmic Spacehead: verify scroll glitch during demo when switching scenes\r\n\r\n - (\r\n    \"European Prince of Persia has occasional minor graphical glitches\r\n     in 60Hz mode, but is still playable.\r\n     Jungle Book has (from memory) more serious glitches in 60Hz mode.\"\r\n\r\n     buggy Super Monaco Gp 1&2 are buggy when you turn right as far as you can\r\n     go. some times nba jam will lock up and i dont think it is a jp game.\r\n   )\r\n\r\n-----------------------------\r\n SCREEN CAPTURE\r\n-----------------------------\r\n - Advanced capture:\r\n   - Set transparency png_set_tRNS().\r\n   - Separate layers\r\n - Be able to map Screenshot to the pad, for opi and others.\r\n - Keep a way to use windows printscreen\r\n - Document PrintScreen weirdness in docs (NB-what weirdness?)\r\n - Add applet to configure everything (template/counter/automatic capture..)\r\n\r\n-----------------------------\r\n CONFIGURATION FILE\r\n-----------------------------\r\n - Document some things better:\r\n   - Eg: \"start_in_gui\" is not mentionned anywhere!\r\n - Do a big cleaning/renaming/sorting of configuration variables.\r\n   Some includes:\r\n   - Current soundcard should be stored in meka.cfg as an ID string\r\n\r\n-----------------------------\r\n NICE STUFF\r\n-----------------------------\r\n - TV snow noise\r\n - Black & white TV mode\r\n - Screensaver\r\n - Blood layer have priorities over menus\r\n\r\n-----------------------------\r\n DESKTOP\r\n-----------------------------\r\n - Background filename should be case sensitive (especially for Mekanix)\r\n - Add ratio background stretch.\r\n - Unable to load pictures error only on start or theme switch (not when\r\n   switching back to the GUI, everytime).\r\n\r\n-----------------------------\r\n VIRTUAL MACHINE\r\n-----------------------------\r\n - Clean up virtual machine handling.\r\n - Power light should be on on Sega Keyboard picture.\r\n - Find someone to draw nice looking systems.\r\n - Allows to show machine even with theme picture.\r\n\r\n-----------------------------\r\n CONSOLE\r\n-----------------------------\r\n - Error on first video init (init -> GUI|Fullscreen) should show in console.\r\n   Currently, in WIN32, because Meka_State is not MEKA_STATE_INIT anymore,\r\n   they show as a popup. The console was already killed anyway\r\n\r\n-----------------------------\r\n ICONS\r\n-----------------------------\r\n - Sort and add new icons to the executable.\r\n   - All media icons from MEKA (SMS/GG/SG/SC games, etc)\r\n   - Maxim's icon\r\n   - Casiopea's icon\r\n   - Golden Axe Warrior (amibe.ico in my e-mails)\r\n\r\n-----------------------------\r\n SOURCES\r\n-----------------------------\r\n - Sort machine_reset stuff, too many are done ?\r\n - Add pointer to reset for each drivers.\r\n - Improve the whole driver system.\r\n\r\n-----------------------------\r\n SOUND\r\n-----------------------------\r\n - Volume Control\r\n - Disabling sound:\r\n   - Be able to disable sound within the program.\r\n   - Support runtime /nosound switch (does not alter configuration).\r\n   - With sound disabled, is emulation all the same ?\r\n     What about PSG/FM registers, saved into a savestate ?\r\n - WAV logging does not saves FM.\r\n   - Require mixing on our side, or retrieval of mixed buffer.\r\n PSG:\r\n - Different PSG feedback/noise for SG-1000/SC-3000/etc.. (SN76489AN variant)\r\n - Higher PSG Volume\r\n - Enhanced PSG via samples (using Dave's idea) / or generating sinuses / other ways.\r\n FM:\r\n - Static sound in FM. -> kind of crackle. See sound/y's hiss.wav.\r\n - Add YM-2413 channel muting - and others things.\r\n - Be able to disable YM2413HD from compilation\r\n - Add ROMEO card support (yeah).\r\n - Instrument editor is obsolete.\r\n - Maxim tells me:\r\n   > 3. Also, I updated to EMU2413 v0.60 and noticed that it sounds very\r\n   > different, in particular the Phantasy Star title screen music where\r\n   > the drums sound badly \"clipped\" as if played at too high volume.\r\n   > Maybe you can check it out (EMU2413 is inside the MSXPLUG archive on\r\n   > the author's website) and compare to a real system? I'm sure you're\r\n   > interested in having the latest version for Meka :) Otherwise I can\r\n   > send some in_vgm.dlls with the 0.55 and 0.60 cores.\r\n - Support CPU speed change.\r\n Notes:\r\n - AUpdateAudio() in starting init: it is necessary ?\r\n\r\n - Some (old) unsorted feedback:\r\n\r\n   - \"I have detected a error in PSG sound emulation in the game Sonic the\r\n      Hedgehog (Sonic 1). The \"ring\" sound in the scene is 'consecutive' in\r\n      real Master System, but in the MEKA is not.\"\r\n   - Little Mermaid -> missing notes (MIGHT)\r\n   - Games that have fast music: (verify)\r\n     - Cool Spot (title screen, two different tempos)\r\n     - Out Run\r\n     - Sonic 1\r\n     - Sonic Chaos\r\n     - Strider\r\n     - World Grand Prix, Engine noise has extra pitch also\r\n     (maybe the guy was just a PAL freak, but better check)\r\n\r\n   - \"> Also, in Dynamite Dux, a soft beep sound can be heared when the music\r\n      > of the first stage begins.\r\n      I think I hear what you mean. Disable channel 2 and the noise channel\r\n      and you can hear it alone, before any proper notes come in. I also hear\r\n      a lot of crackling because of the vibrato-type effect it uses by changing\r\n      the volume really quickly. If you listen to channel 1 or 3 alone then you\r\n      don't hear it, so it's a Meka problem.\"\r\n      - see Maxim e-mail\r\n      - This is just the standard effect of the main sound bug described above.\r\n\r\n-----------------------------------------------------------------------------\r\n NAMING CONVENTION\r\n-----------------------------------------------------------------------------\r\n - Export/Japan\r\n - Everything in MEKA.CFG\r\n - Everything in MEKA.MSG\r\n - ...\r\n\r\n-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/Themes/README.txt",
    "content": "\r\n MEKA Themes Backgrounds\r\n http://www.smspower.org/meka/themes\r\n\r\n Credits for the images in this directory:\r\n Most are screenshots or composition from other sources.\r\n The credits thus only mention the submitter/composer of the image.\r\n Game, scene and characters pictured are properties of their owner.\r\n \r\n Don't hesitate to submit new Sega 8-bit related themes, or\r\n tweaked existing themes.\r\n\r\nDefault package:\r\n\r\n AlexKidd.png                   Myau of Algol\r\n NinjaGaiden.png                Kurt Roliz\r\n PhantasyStar.png               Myau of Algol\r\n PsychoFox.png                  Barry McLarnon\r\n WonderBoyIII.png               Andrea Ballandino\r\n\r\n"
  },
  {
    "path": "meka/changes.txt",
    "content": "-----------------------------------------------------------------------------\r\n MEKA - ChangeLog\r\n-----------------------------------------------------------------------------\r\n Note: for a more developer/hacker centric ChangeLog, download\r\n source code and refer to HISTORY.TXT file.\r\n-----------------------------------------------------------------------------\r\n\r\n MEKA 0.80 WIP\r\n -------------\r\n  <see history.txt for developer facing changes>\r\n\r\n\r\n MEKA 0.74 WIP xxxxxxxx\r\n ----------------------\r\n  - (Win32) Updated project file to Visual Studio 2008 format + compilation fixes.\r\n  - (Win32) Updated Allegro library to 4.2.3 (using precompiled binary from 'allegro-msvc9-4.2.3').\r\n  - (Win32) Updated LibPNG library to 1.2.8 (precompiled binary package included in repository).\r\n  - (Win32) Including minimal DirectX 7.0 package (precompiled binary package 'dx70_min' included in repository)\r\n     because newer DirectX SDK tends to cause problem with 4.2.x Allegro branches.\r\n  - SC-3000:\r\n    - Fixed the ':' (colon) key not working on Sega Keyboard emulation under certain host keyboard/OS configuration. [Omar]\r\n  - GUI:\r\n    - Added Taiwanese flag (for DB and File Browser). [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n          SMS - 84665648 - Great Soccer (JP) [Hack]             --> Great Soccer (TW)\r\n          SMS - 656d1a3e - Hokuto no Ken [BAD] (CH)             --> Hokuto no Ken (TW) [Hack] (the \"bad\" data is on the original cart, but this version has additional modifications)\r\n          SMS - 69538469 - Monopoly [A]                         --> Monopoly (US)\r\n          SMS - 026d94a4 - Monopoly [B]                         --> Monopoly (EU)\r\n          SMS - 311d2863 - Prince of Persia [SMS-GG] [A]        --> Prince of Persia [SMS-GG] (US)\r\n          SMS - 45f058d6 - Prince of Persia [SMS-GG] [B]        --> Prince of Persia [SMS-GG] (EU)\r\n          SMS - 01686d67 - Suho Cheonsa (KR)                    --> Suho Jeonsa (KR)\r\n          SG1 - 868419b5 - Champion Golf [A]                    --> Champion Golf [cart]\r\n          SG1 - 5a904122 - Champion Golf [B]                    --> Champion Golf [card]\r\n          SG1 - fdc095bc - Doki Doki Penguin Land (HK)          --> Doki Doki Penguin Land (TW)\r\n          SG1 - 60f30138 - Dragon Wang [B]                      --> Dragon Wang [v0]\r\n          SG1 - 7c7d4397 - Dragon Wang (TW)                     --> Dragon Wang [v0] [chinese logo] (TW) (because a second Taiwanese version exists)\r\n          SG1 - 99c3de21 - Dragon Wang [A]                      --> Dragon Wang [v1]\r\n          SG1 - bd24d27b - Flicky                               --> Flicky [v0]\r\n          SG1 - 191ffe0a - GP World [A]                         --> GP World [v1]\r\n          SG1 - 191ffe0a - GP World [B]                         --> GP World [v0]\r\n          SG1 - 6d909857 - Mahjong                              --> Mahjong [small 1983]\r\n          SG1 - 8572d73a - Monaco GP [24k]                      --> Monaco GP [24k] [v0] [40k map]\r\n          SG1 - da2d57f3 - Monaco GP [32k]                      --> Monaco GP [32k] [v1] (provision for newly found [v2] build).\r\n          SG1 - 37fca2eb - Pitfall II ~The Lost Caverns~ [A]    --> Pitfall II ~The Lost Caverns~ [v0] (dumps and versionning finally confirmed)\r\n          SG1 - 3db74761 - Pitfall II ~The Lost Caverns~ [B]    --> Pitfall II ~The Lost Caverns~ [v1]\r\n          SG1 - 160535c5 - Wonder Boy [A]                       --> Wonder Boy [v0]\r\n          OMV - 90160849 - James Bond 007                       --> 007 James Bond\r\n          GG  - f85a8ce8 - 5 in 1 Fun Pak                       --> 5 in One Fun Pak\r\n          GG  - a6bf865e - Beavis and Butt-Head (MTV's)         --> Beavis and Butt-Head (MTV's)\r\n          GG  - 3858f14f - Beavis and Butt-head (MTV's) (US)    --> Beavis and Butt-head (MTV's) (US)\r\n          GG  - 03d28eab - Crayon Shin-chan - Taiketsu! Tankam..--> Crayon Shin-chan - Taiketsu! Kantamu Panic!! (JP) (embarassing typo)\r\n          GG  - 7ec95282 - Madoh Monogatari A [...] Bake~shon   --> Madoh Monogatari A - Doki Doki Vacation (JP)\r\n          GG  - 4e279baa - PGA TOUR Golf 2                      --> PGA TOUR Golf II\r\n          GG  - 786dd67b - Skweek (JP)                          --> Skweek [BAD] (JP)\r\n          GG  - 88618afa - Tails' Sky Patrol (JP)               --> Tails' Skypatrol (JP)\r\n          GG  - e678f264 - Yogi Bear [Proto]                    --> Yogi Bear in Yogi Bears Goldrush [Proto]\r\n    Other smaller changes not recorded, please refer to meka.nam SVN history for exact changes.\r\n\r\n\r\n MEKA 0.73\r\n ---------\r\n  - Updated MEKA license, data are now licensed under the same term as sources.\r\n    The license is now unrestrictive BSD-like. [Omar]\r\n  - Removed \"k\" and associated donation rambling from the documentation.\r\n    Donations are still welcome, at your own discretion.\r\n  - Emulation:\r\n    - Added support for \"no bank switching\" mapper. Used by Korean games such\r\n      as \"FA Tetris\" and \"Flash Point\" which write to $fffe-$ffff range for\r\n      its RAM usage but do not expect bank-switching. [Omar]\r\n    - Added support for Korean 8KB banks mapper. Used by Korean games ported\r\n      from MSX such as \"Penguin Adventure\", \"Street Master\" or \"Won-Si-In\". [Omar]\r\n  - SC-3000:\r\n    - Fixed the ;/+/RAD key not working on Sega Keyboard emulation under\r\n      certain host keyboard/OS configuration. Thanks Jacko. [Omar]\r\n    - Fixed crash in the X86 assembly implementation of the 32KB RAM mapper\r\n      writer when the upper 16 bits were not cleared by the Z80 emulator. [Omar]\r\n  - Debugger:\r\n    - Added \"SYM @addr\" command to search for symbols given an address. [Omar]\r\n    - Added \"RMAP addr\" command to reverse map of a Z80 address and display\r\n      the source of data based on machine state (mapper registers, etc).\r\n      eg:\r\n        RMAP $8001      ; eg: print 'ROM $14001 (Page 5 +0001)'\r\n        RMAP $E001      ; eg: print 'RAM $C001'\r\n      The feature doesn't work 100% in all mappers & bus mirroring cases,\r\n      but should be ok with the standard SMS/GG mapper. [Omar]\r\n    - Duplicate commands are automatically removed from history. [Omar]\r\n    - Increased default height of the debugger. [Omar]\r\n    - Changed watch point per-frame flood limit from 100 to 50. Will expose in\r\n      configuration file if requested. [Omar]\r\n    - Fixed crash when loading symbols with debugger disabled. [Djbass,Omar]\r\n    - Fixed labels showing one instruction early in \"DASM\" command. [Omar]\r\n    - Added breakpoint '!' mark in disassembly window. [Omar]\r\n  - GUI:\r\n    - Fixed Light Phaser and Terebi Oekaki cursor shape when switching from\r\n      32-bits GUI mode to 16-bits game only mode. [Omar]\r\n    - File browser: fixed positionning of BAD and HACK icons, which aren't\r\n      overlays anymore. [Omar]\r\n    - Added Canadian flag (for DB and File Browser). [Omar]\r\n    - Fixed crash when empty gradient range are specified in theme file. [Omar]\r\n    - File browser: country flag now displayed even on BIOS, Prototypes\r\n      or Homebrew images. [Omar]\r\n    - Inputs configuration: right-click on input source selection goes\r\n      backward, in addition to regular left-click to go forward. [Omar]\r\n  - Localization:\r\n    - Updated Dutch localization [Mark van Tilburg]\r\n  - Miscellaenous:\r\n    - Added \"Capture\" menu with screen capture menu access and options. [Maxim]\r\n    - Added \"Capture All\" mode, capturing all emulation frames to disk. [Maxim]\r\n    - Added \"Include GUI\" capture option. Disable to only capture game screen\r\n      when MEKA GUI is enabled. [Maxim]\r\n    - Renamed \"Automatically crop and align screen captures\" option to\r\n      more explicit \"Crop and align screen captures to 8x8 boundaries\".\r\n      Previous name was sounding too \"cool\" and was sometimes activated\r\n      by innocent users who then got their capture all cropped. [Omar]\r\n    - Added \"screenshots_crop_scrolling_column\" option in configuration\r\n      file (default to enabled), to disable cropping the empty left-most\r\n      column in horizontally scrolling games. [Omar]\r\n  - Project:\r\n    - (Win32) Fixed standard libraries used by debug builds (using unusual\r\n      combination led to various problems). Fixed various link warnings.\r\n      Fixed shared directories between DLL and No DLL builds. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n          SMS - d91b340d - Action Fighter (JP)                  --> Action Fighter [v1] (also released in Germany and Italia)\r\n          SMS - 3658f3e0 - Action Fighter                       --> Action Fighetr [v2]\r\n          SMS - f4b3a7bd - Ariel - The Little Mermaid (BR)      --> Ariel - The Little Mermaid (Disney's) (BR)\r\n          SMS - b3768a7a - Bonkers Wax Up! (BR)                 --> Bonkers Wax Up! (Disney's) (BR)\r\n          SMS - 1b10a951 - Bram Stoker's Dracula                --> Dracula (Bram Stoker's)\r\n          SMS - c0e25d62 - California Games II                  --> California Games II [50 Hz]\r\n          SMS - 46340c41 - Cheese Cat-astrophe                  --> Cheese Cat-Astrophe - Starring Speedy Gonzales\r\n          SMS - 89b79e77 - Dodgeball King (KR)                  --> Dallyeora Pigu-Wang (KR)\r\n          SMS - b8b141f9 - Fantasy Zone II                      --> Fantasy Zone II - The Tears of Opa-Opa\r\n          SMS - c722fb42 - Fantasy Zone II (JP)                 --> Fantasy Zone II - Opa-Opa no Namida (JP)\r\n          SMS - 45c50294 - Jogos de Verão II                    --> California Games II [50-60 Hz] (also found in Korea).\r\n          SMS - 5b5f9106 - Nekyuu Kousien (JP)                  --> Nekkyuu Koushien (JP)\r\n          SMS - 0e333b6e - Miracle Warriors - Seal of the Dar.. --> Miracle Warriors - Seal of The Dark Lord (casing on 'The')\r\n          SMS - be57a9a5 - Pacmania                             --> Pac-Mania (the other way, sorry! It seems like the official name of the game)\r\n          SMS - 294e0759 - Paperboy                             --> Paperboy [v0] (scoring bug)\r\n          SMS - 327a0b4c - Paperboy (US)                        --> Paperboy [v1] (also found in Brasil)\r\n          SMS - 97d03541 - Sangokushi 3 (KR)                    --> Samgukji III (KR), Japanese Name \"Sangokushi III\".\r\n          SMS - e1fff1bb - Shinobi (JP)                         --> Shinobi [v0] (also found in Brasil in Game Box Serie Lutas compilation)\r\n          SMS - 0c6fac4e - Shinobi                              --> Shinobi [v1]\r\n          SMS - c93bd0e9 - Slap Shot [B]                        --> Slap Shot [v0]\r\n          SMS - d33b296a - Slap Shot [A]                        --> Slap Shot [v1]\r\n          SMS - 702c3e98 - Slap Shot (US)                       --> Slap Shot [v2] (US)\r\n          SMS - e2fcb6f3 - Super Wonder Boy (JP)                --> Wonder Boy [v0] (also released in Italia)\r\n          SMS - 93ca8152 - T2 - The Arcade Game                 --> T2: The Arcade Game\r\n          SMS - 11ce074c - Taz in Escape From Mars              --> Taz in Escape from Mars\r\n          SMS - ac56104f - Terminator 2 - Judgment Day          --> Terminator 2: Judgment Day\r\n          SMS - bf7b7285 - Tom and Jerry - The Movie            --> Tom and Jerry: The Movie\r\n          SMS - 0c2fc2de - Tom and Jerry - The Movie [Proto]    --> Tom and Jerry: The Movie [Proto]\r\n          SMS - 20f40cae - Vampire                              --> Master of Darkness / Vampire [Proto]\r\n          SMS - 73705c02 - Wonder Boy                           --> Wonder Boy [v1]\r\n          GG  - f85a8ce8 - 5 in 1 Fun Pak                       --> 5-in-1 FunPak\r\n          GG  - 3e549b7a - Aerial Assault                       --> Aerial Assault [v0]\r\n          GG  - ffe4ed47 - Alien Syndrome                       --> Alien Syndrome (JP)\r\n          GG  - 97e3a18c - Ariel - The Little Mermaid           --> Ariel - The Little Mermaid (Disney's)\r\n          GG  - 8d8bfdc4 - Baku Baku Animal (US)                --> Baku Baku (US)\r\n          GG  - 10ac9374 - Baku Baku Animal (EU)                --> Baku Baku (EU)\r\n          GG  - a6bf865e - Beavis and Butt-head                 --> Beavis and Butt-head (MTV's)\r\n          GG  - 325b1797 - Berlin no Kabe - The Berlin Wall (JP)--> Berlin no Kabe - The BerlinWall (JP) (clearly spelled without space)\r\n          GG  - bfceba5f - Bonkers Wax Up!                      --> Bonkers Wax Up! (Disney's)\r\n          GG  - 69ebe5fa - Bram Stoker's Dracula                --> Dracula (Bram Stoker's)\r\n          GG  - 2c758fc8 - Cool Spot                            --> Cool Spot (US)\r\n          GG  - 03d28eab - Crayon Shin Chan - Taiketsu! T.. (JP)--> Crayon Shin-chan - Taiketsu! Tankam Panic!!\r\n          GG  - 4457e7c0 - Donald Duck no Yottsu no Himitsu (JP)--> Donald Duck no Yottsu no Hihou (JP)\r\n          GG  - 19e1cf2b - Dragon Crystal - Tsurani no M.. (JP) --> Dragon Crystal - Tsurani no Meikyuu (JP)\r\n          GG  - 152f0dcc - Drop Zone                            --> Dropzone (Archer MacLean's)\r\n          GG  - 5d3f23a9 - Earthworm Jim                        --> Earthworm Jim (US)\r\n          GG  - 2b60873e - Ecco the Dolphin                     --> Ecco the Dolphin [BAD]\r\n          GG  - d0a93e00 - F1                                   --> Formula One / F1 (alternative names)\r\n          GG  - d69097e8 - Fantasy Zone Gear                    --> Fantasy Zone / Fantasy Zone Gear - Opa Opa Jr. no Bouken\r\n          GG  - 449787e2 - Fatal Fury Special                   --> Fatal Fury Special (US)\r\n          GG  - e123d9b8 - Fray (JP)                            --> Fray ~Shugyou hen~ (JP)\r\n          GG  - 751dad4c - From TV animation - Slam Dunk.. (JP) --> Slam Dunk - Shouri-e no Starting 5 (From TV animation) (JP)\r\n          GG  - 695cc120 - GG Portrait - Pai Chan (JP)          --> GG Portrait - Pai Chen (JP)\r\n          GG  - 4cf97801 - Godzilla - Kaiju Dai-Shingeki (JP)   --> Godzilla - Kaijuu Daishingeki (JP)\r\n          GG  - a93e8b0f - Griffin                              --> Griffin (JP)\r\n          GG  - 398f2358 - Kuni Chan's Game Paradise (JP)       --> Kuni Chan no Game Tengoku (JP)\r\n          GG  - f3774c65 - Kuni Chan's Game Paradise 2 (JP)     --> Kuni Chan no Game Tengoku Part 2 (JP)\r\n          GG  - 42389270 - Hyokkori Hyoutan Jima (JP)           --> Hyokkori Hyoutan Jima - Hyoutan Jima no Daikouka (JP)\r\n          GG  - 9fb5c155 - James Pond II - Codename: Robocod    --> James Pond II - Codename: Robocod (US)\r\n          GG  - 30c09f31 - Jungle Book, The (Walt Disney'..(US) --> Jungle Book, The (Walt Disney's) (US) (US version do not mention 'Classic'. Alternate name have only 'Disney's').\r\n          GG  - 87b8b612 - McDonald's - Donald no Magical World --> Donald no Magical World (Ronald in the Magical World) (JP) (Japanese only release, Western name is unused)\r\n          GG  - 75c71ebf - Madden NFL '95                       --> Madden NFL 95\r\n          GG  - 75e273eb - Madden '96                           --> Madden 96 [BAD]\r\n          GG  - 00c34d94 - Madoh Monogatari I - Mittsu no..(JP) --> Madoh Monogatari I - Mittsu no Madoukyuu (JP)\r\n          GG  - 0a634d79 - Madoh Monogatari III - K.. [v0] (JP) --> Madoh Monogatari III - Kyuukyoku Joou-sama [v0] (JP)\r\n          GG  - 568f4825 - Madoh Monogatari III - K.. [v1] (JP) --> Madoh Monogatari III - Kyuukyoku Joou-sama [v1] (JP)\r\n          GG  - 7ec95282 - Madoh Monogatari A - Dokidoki.. (JP) --> Madoh Monogatari A - Doki Doki Bake~shon (JP)\r\n          GG  - 8f82a6b9 - Magic Knight Ray Earth (JP)          --> Magic Knight Rayearth (JP)\r\n          GG  - 1c2c2b04 - Magic Knight Ray Earth 2 ~mak.. (JP) --> Magic Knight Rayearth 2 ~making of magic knight~\r\n          GG  - 6e1cc23c - Magical Taruruto-kun (JP)            --> Magical Taruruuto-kun (JP)\r\n          GG  - 36ebcd6d - Majors Pro Baseball                  --> Majors Pro Baseball, The\r\n          GG  - 2e4ec17b - Megami Tensei Gaiden Last Bible (JP) --> Megami Tensei Gaiden: Last Bible (JP)\r\n          GG  - 4ec30806 - Megami Tensei Gaiden Last Bibl..(JP) --> Megami Tensei Gaiden: Last Bible Special (JP)\r\n          GG  - 4d5d15fb - Moldorian (JP)                       --> Moldorian ~Hikari to Yami no Shisutaa~ (JP)\r\n          GG  - dbff0461 - Mortal Kombat (JP)                   --> Mortal Kombat - Shinken Kourin Densetsu (JP)\r\n          GG  - 54ab42a4 - Nazo Puyo Aruru no Ru (JP)           --> Nazo Puyo Aruru no Ruu (JP)\r\n          GG  - 4c874466 - Nazo Puyo Aruru no Ru [Editor.. (JP) --> Nazo Puyo Aruru no Ruu [Editor Proto] (JP)\r\n          GG  - 3679be80 - Neko Daisuki! (JP)                   --> Neko Dai Suki! (JP)\r\n          GG  - c3056e15 - Ninku (JP)                           --> Ninkuu (JP)\r\n          GG  - 06247dd2 - Ninku 2 ~Tenkuryu-e no Michi~ (JP)   --> Ninkuu 2 ~Tenkuuryuu-e no Michi~ (JP)\r\n          GG  - 9140f239 - Ninku Gaiden - Hiroyuki Daika.. (JP) --> Ninkuu Gaiden - Hiroyuki Daikatsugeki\r\n          GG  - 19030108 - NBA Action                           --> NBA Action - Starring David Robinson\r\n          GG  - 4680c7aa - NHL All Stars                        --> NHL All-Star Hockey\r\n          GG  - a2f9c7af - Olympic Gold [SMS-GG] [B]            --> Olympic Gold [v0] [SMS-GG]\r\n          GG  - 1d93246e - Olympic Gold [SMS-GG] [A]            --> Olympic Gold [v1] [SMS-GG]\r\n          GG  - d58cb27c - Out Run                              --> Out Run (JP)\r\n          GG  - f037ec00 - Out Run Europa [SMS-GG]              --> Out Run Europa [SMS-GG] (US)\r\n          GG  - a16c5e58 - Pac-Man                              --> Pac-Man (JP)\r\n          GG  - b42d8430 - Pet Club Inu Daisuki! (JP)           --> Pet Club Inu Dai Suki! (JP) (coherent with Neko Dai Suki!)\r\n          GG  - 3ef66810 - Popeye's Beach Volleyball (JP)       --> Popeye Beach Volley Ball (JP)\r\n          GG  - d173a06f - Puzlow Kids / Puyo Puyo              --> Puyo Puyo (Puzle Kids) (JP) (Japanese only release, Western name is unused)\r\n          GG  - 96045f76 - Road Rash                            --> Road Rash (US)\r\n          GG  - 445d7cd2 - Royal Stone ~Hikarishi Toki n.. (JP) --> Royal Stone ~Hirakareshi Toki no Tobira~ (JP)\r\n          GG  - fe7374d2 - Sailor Moon S (JP)                   --> Bishoujo Senshi Sailor Moon S (JP)\r\n          GG  - 2ae8c75f - Shanghai II (JP)                     --> Shanghai II [v0] (JP)\r\n          GG  - 9c5c7f53 - Shikinjou (JP)                       --> Shikinjo (JP) (official transcription)\r\n          GG  - 0f3e3840 - Sokoban World (JP)                   --> Soukoban (JP)\r\n          GG  - d23a2a93 - Sonic Triple Trouble                 --> Sonic The Hedgehog Triple Trouble\r\n          GG  - 80156323 - Star Trek The Next Generation - Th.. --> Star Trek: The Next Generation - The Advanced Holodeck Tutorial\r\n          GG  - 1ebfa5ca - Strider Returns                      --> Strider Returns (Journey from Darkness)\r\n          GG  - 2ea26930 - Surf Ninjas                          --> Surf Ninjas [BAD] (confirmed correct dump)\r\n          GG  - 9479c83a - T2 - The Arcade Game                 --> T2: The Arcade Game\r\n          GG  - cf9c607c - Taisen Mahjong HaoPai (JP)           --> Taisen Mahjong Hao-Pai (JP)\r\n          GG  - 20527530 - Taisen Mahjong HaoPai 2 (JP)         --> Taisen Mahjong Hao-Pai 2 (JP)\r\n          GG  - dd1d2ebf - Tama & Friends - 3chome Koen.. (JP)  --> Tama & Friends - 3 Choume Kouen Tamalympic (JP)\r\n          GG  - f1732ffe - TaleSpin                             --> TaleSpin (Disney's)\r\n          GG  - eebad66b - Taz in Escape From Mars              --> Taz in Escape from Mars\r\n          GG  - 1bd15773 - Terminator 2 - Judgment Day          --> Terminator 2: Judgment Day\r\n          GG  - a1453efa - Tom and Jerry - The Movie (JP)       --> Tom and Jerry: The Movie\r\n          GG  - 5cd33ff2 - Tom and Jerry - The Movie            --> Tom and Jerry: The Movie (US)\r\n          GG  - 7ec64025 - Vampire: Master of Darkness          --> Vampire - Master of Darkness (US)\r\n          GG  - 9977fcb3 - Wonder Boy                           --> Wonder Boy (JP)\r\n          GG  - d9ce3f4c - Yaiba Adventures (JP)                --> Kenyuu Densetsu Yaiba (JP)\r\n          GG  - 88ebbf9e - Yuu Yuu Hakusho (JP)                 --> Yu Yu Hakusho - Horobishi Mono no Gyakushuu (JP)\r\n          GG  - 46ae9159 - Yuu Yuu Hakusho II (JP)              --> Yu Yu Hakusho II - Gekitou! Nanakyou no Tatakai (JP)\r\n          SG  - 37fca2eb - Pitfall II [A]                       --> Pitfall II ~The Lost Caverns~ [A]\r\n          SG  - 3db74761 - Pitfall II [B]                       --> Pitfall II ~The Lost Caverns~ [B]\r\n          SG  - 5a917e06 - Shinnyushain Tooru Kun (Konami no)   --> Shinnyuushain Tooru-Kun (Konami no)\r\n          OMV - 77db4704 - Q*Bert                               --> Q*bert\r\n\r\n\r\n MEKA 0.72\r\n ---------\r\n  - Updated k.\r\n  - Ports:\r\n    - Preliminary MacOSX port. [Proppy]\r\n      Compile and run under a x86-based MacOSX system. Missing sound (due\r\n      to Seal) and debugger (unknown problem to resolve).\r\n      Looking for someone who wish to improve and maintain this port.\r\n  - Video/Blitters:\r\n    - Upgraded everything to hi-color video modes and got rid of old,\r\n      8-bit indexed video modes. This is a major change in MEKA core.\r\n      Some of the benefits are:\r\n      - No more snow and/or color flickering on video card drivers\r\n        which disliked palette changes.\r\n      - Better integration with desktop (usually run faster).\r\n      - Getting possible to use various kind of graphics filters.\r\n      - No more hassle with color limitation for the programmer\r\n        (meaning more features implemented for the end-user).\r\n      - Finally possible to show all Game Gear colors at once,\r\n        and to implement LCD screen persistence (not yet done).\r\n      Some of the features above goes hand to hand with the blitter\r\n      system, which will be improved soon. [Omar]\r\n    - Fixed HQ2X stretched blitter when target output was not 16-bits. [Omar]\r\n    - Stretching works on all blitters. [Omar]\r\n    - Video depth, Vsync, Triple Buffering and Page flipping are now global\r\n      video settings, removed from each specific blitter. Greatly simplify\r\n      configuration and tweaking. [Omar]\r\n    - Triple buffering doesn't interfere with the refresh is not supported\r\n      by the current settings (eg: windowed mode), making it safe and more\r\n      simple to always leave it enabled. [Omar]\r\n    - Changed default fullscreen blitter configuration in the hope of getting\r\n      something more compatible (640x480 by default), as so many people have\r\n      problems with fullscreen modes.\r\n    - Removed obsolete \"scanlines\" blitter, in favor of \"tvmode\". [Omar]\r\n    - Removed \"parallel\" blitter that displayed both odd and even frame\r\n      next to each other. Seems useless now. Could be brought back if some\r\n      four-eyed person request it. [Omar]\r\n  - Sound:\r\n    - Added support for VGM 1.10 header type. [Omar]\r\n  - Emulation:\r\n    - Fixed data corruption/overflow in VDP emulation when seeking and\r\n      writing to an invalid palette address. Thanks Maxim. [Omar]\r\n    - VDP palette write do not mask out current VDP address, so performing\r\n      the (unprobable) set address/access palette/access VRAM sequence will\r\n      keep address in the full 16KB range. [Omar]\r\n    - Fixed VDP line interrupts not properly running in overscan area in\r\n      224 lines mode. Fixes bottom of the screen in Charles Mac Donald's\r\n      BB2K6 demo. [Omar]\r\n    - CPU:\r\n      - Z80: Fixed cases were address arithmetic would not wrap in the\r\n        16-bit address space, effectively crashing the emulator (those cases\r\n        were mostly happening on corrupted data, but it also legit Z80 code,\r\n        and in any case we don't want the emulator to crash). [Omar]\r\n      - Z80: Fixed RETI behavior (same as RETN, copying IFF2 to IFF1).\r\n        Fixes pausing in SMS Robocop 3 during legal screens/introduction,\r\n        probably other infrequent cases. [FluBBa, Omar]\r\n      - Z80: Accepting NMI doesn't copy IFF1 over IFF2, as suggested\r\n        by Sean Young's \"The Undocumented Z80 Documented\". [Omar]\r\n    - ColecoVision:\r\n      - Fixed emulation of pending NMI, pending flag is cleared when\r\n        reading VDP status. Fixes \"Rock 'N Bolt\" among other.\r\n        Thanks to the anonymous poster on SMS Power! forums. [Omar]\r\n      - Note that the compatibility list for ColecoVision titles is\r\n        severly outdated. At some point, James Carter worked on a new,\r\n        more accurate list, but I lost all contact with him.\r\n      - Removed detection of supposed 128-bytes headers and 512-bytes footers\r\n        (from some old soft/copiers?), due to many false detections,\r\n        particularly on homebrew ROM images (the code was introduced in 2001\r\n        when Dig Dug and Pac-Man prototypes were released with such header,\r\n        but ROM images now circulating are without the header). [Omar]\r\n  - GUI:\r\n    - Sorted default themes, removed non Sega 8-bit related themes.\r\n      Now embedding background pictures in regular binary distribution.\r\n      CALL FOR NEW OR IMPROVED THEMES SUBMISSION! Please contribute.\r\n    - KeyPad Enter key now works on input boxes. [Omar]\r\n    - Added shortcut CTRL-F4: closes current window. [Omar]\r\n    - Added shortcut CTRL-TAB: cycles thru windows taking inputs. [Omar]\r\n    - Reworked theme (skin) system from stratch: [Omar]\r\n      - Changed MEKA.THM file format.\r\n      - Using explicit names for variables.\r\n      - Added more variables, making the skin system a little more\r\n        complicated but also more configurable.\r\n      - Using de-facto standard of specifying colors in #RRGGBB format.\r\n      - Rewrote most code since it was all legacy from old MEKA 0.10.\r\n    - Added link to debugger documentation in HELP menu. [Omar]\r\n    - Removed closing fadeout since the current hi-color implementation\r\n      is way inefficient and cannot garantee proper speed. [Omar]\r\n  - Development:\r\n    - Debugger:\r\n      - Fixed various command-line parsing bugs. [Omar]\r\n      - Added line history. Navigate history by pressing Up/Down.\r\n        List or search in history using HISTORY (HI) command. [Omar]\r\n      - Added conditionnal breakpoints. [Omar]\r\n        eg:\r\n          BREAK r C000.. =01,02,03,04   ; break on read of 01020304 in RAM\r\n          BREAK x =C9                   ; break on CPU execution of RET\r\n          BREAK x =0,0                  ; break on CPU execution of NOP NOP\r\n          BREAK w pram 0 =03            ; break on PRAM write of color 0 as red\r\n      - Added display line event breakpoints/watchpoints. [Omar]\r\n        Useful for debugging line interrupts.\r\n        eg:\r\n          BREAK line #13                ; break on display line 13\r\n      - Added \"B nopnop\" shortcut to break on two successives NOP instructions.\r\n        This is basically equivalent to \"B x =0,0\". [Omar]\r\n      - REGS (R) command in debugger now display shadow registers as well. [Omar]\r\n      - Added cursor before current instruction in disassembly. [Omar]\r\n      - Added access to shadow registers in expression evaluator. [Omar]\r\n        eg:\r\n          PRINT AF',BC',DE',HL'\r\n      - Added SET command to modify Z80 registers. [Omar]\r\n        eg:\r\n          SET BC=$1234    ; set BC register to $1234\r\n          SET DE=HL,HL=0  ; set DE=HL, then zero HL\r\n      - Added MEMEDIT command to spawn a new memory editor. [Omar]\r\n      - Added CLOCK command, to display/reset a Z80 cycle counter.\r\n        Very simple but can be helpful to time Z80 routines. [Omar]\r\n      - (Win32) Forward debugging log to Windows debugging stream via\r\n        OutputDebugString(), so running MEKA from Microsoft Visual studio\r\n        will display log in the 'Output' window. [Omar]\r\n    - Memory Editor:\r\n      - Added viewing and editing of VDP registers (VREG). [Omar]\r\n      - Added configuration file directive for resizing window. [Omar]\r\n      - Fixed cursor position when inputing an address on last page. [Omar]\r\n      - Added NES PRAM support. [Omar]\r\n    - Tiles viewer:\r\n      - Added NES palette switching (8 palettes). [Omar]\r\n    - Tilemap viewer:\r\n      - Added tilemap viewer. [Omar]\r\n        Shows tilemap, hovering or clicking a tile shows specific info\r\n        about it, allows filtering BG/FG, disabling tile flipping, display\r\n        of scrolling box, with or without raster effects, manual selection\r\n        of tilemap address, etc.\r\n    - Made '$' default prefix for hexadecimal values in various places. [Omar]\r\n    - Datadump: [Ambil, Omar]\r\n      - Fixed \"palette\" dumping. Blue and green components were inverted.\r\n        Replaced dumping of target host RGB values by actual SMS/GG components.\r\n      - Added sprite pattern base address in \"sprites\" dumping.\r\n    - Cleaned Technical Information Viewer content, renamed a few fields\r\n      to their official names, removed redundant information. It's not\r\n      yet all clean. [Omar]\r\n  - Miscellaenous:\r\n    - Various fixes.\r\n    - Increased max length of directory/filenames. [Musuruan]\r\n    - Added \"Automatically crop and align screen captures\" option.\r\n      This option aligns screen captures on the nearest visible tile,\r\n      helping to simplify the process of creating game maps by pasting\r\n      captures next to each other. [Omar]\r\n      Note: May not work properly on game using scanline based effects.\r\n    - Updated various tidbits in the configuration file. [Omar]\r\n    - (Win32) Removed flickering from initialization message console. [Maxim]\r\n    - (UN*X) Renamed main executable to 'meka' (instead of 'meka.exe').\r\n  - Sources/Project\r\n    - (Win32) Added new targets supporting shared standard libraries. [Omar]\r\n    - (Win32) Updated Allegro library from WIP 4.1.18 to 4.2.0, including\r\n       various fixes/improvements:\r\n         http://www.talula.demon.co.uk/allegro/onlinedocs/en/changes.html\r\n    - (Win32) Now linking to zlib.lib instead of zlibs.lib (name for standard\r\n       static build of ZLIB). [Omar]\r\n    - Removed password encryption from MEKA datafile (became useless). [Omar]\r\n    - Fixed a bunch of warnings on higher warning levels. [Omar]\r\n    - Hacked a lot of old GUI code (box, widgets, menus among others), cleaned\r\n      and renamed various structures, replaced several usage of indexes by\r\n      pointers, added const qualifiers, rewrote parts of various applets,\r\n      got rid of some old obsolete code, etc. Hopefully broke nothing. [Omar]\r\n    - (Win32) Fixed MSVC project to reference LIBPNGDIR.\r\n    - (Win32) Including statically compiled libpng.lib in package. [Omar]\r\n    - (UN*X) No more need to manually edit .ASM files to compile. [Omar]\r\n    - Updated SOURCES.TXT documentation. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n      SMS - 0e21e6cf - Astro Flash (JP)                     --> Astro Flash [Hack] (JP)\r\n      SMS - e5ff50d8 - Back to the Future II                --> Back to the Future Part II\r\n      SMS - 2d48c1d3 - Back to the Future III               --> Back to the Future Part III\r\n      SMS - 953f42e1 - Castle of Illusion                   --> Castle of Illusion - Starring Mickey Mouse\r\n      SMS - b9db4282 - Castle of Illusion (US)              --> Castle of Illusion - Starring Mickey Mouse (US)\r\n      SMS - 59840fd6 - Castle of Illusion [SMS-GG]          --> Castle of Illusion - Starring Mickey Mouse [SMS-GG]\r\n      SMS - 9942b69b - Castle of Illusion [SMS-GG] (JP)     --> Castle of Illusion - Starring Mickey Mouse [SMS-GG] (JP)\r\n      SMS - 42fc3a6e - Deep Duck Trouble                    --> Deep Duck Trouble - Starring Donald Duck\r\n      SMS - 65d7e4e0 - Fantasy Zone                         --> Fantasy Zone [v2]\r\n      SMS - 5d08e823 - Fushigi no Oshiro Pit Pot (JP)       --> Fushigi no Oshiro Pit Pot [Hack] (JP)\r\n      SMS - a4ac35d8 - Galaxy Force [50 / 60 Hz]            --> Galaxy Force\r\n      SMS - 6c827520 - Galaxy Force [60 Hz]                 --> Galaxy Force (US)\r\n      SMS - dabcc054 - Ghost house (JP)                     --> Ghost House [Hack] (JP)\r\n      SMS - c1e699db - Great Baseball [JP] (JP)             --> Great Baseball [JP] [Hack] (JP)\r\n      SMS - 84665648 - Great Soccer (JP)                    --> Great Soccer [Hack] (JP)\r\n      SMS - 695a9a15 - Jungle Book, The                     --> Jungle Book, The (Walt Disney's Classic)\r\n      SMS - 24e97200 - Land of Illusion                     --> Land of Illusion - Starring Mickey Mouse\r\n      SMS - 6350e649 - Legend of Illusion (BR)              --> Legend of Illusion - Starring Mickey Mouse (BR)\r\n      SMS - c352c7eb - Lion King, The                       --> Lion King, The (Disney's)\r\n      SMS - 87b9ecb8 - Satellite 7 (JP)                     --> Satellite 7 [Hack] (JP)\r\n      SMS - bcd91d78 - Seishun Scandal (JP)                 --> Seishun Scandal [Hack] (JP)\r\n      SMS - a71bc542 - Spy vs Spy (JP)                      --> Spy vs Spy [Hack] (JP)\r\n      SMS - 1de2c2d0 - Strategic Defense Initiative (JP)    --> SDI (JP)\r\n      SMS - 95cbf3dd - Super Tennis (JP)                    --> Great Tennis / Super Tennis (JP) (note: this one is tricky. Official game name is \"Great Tennis\" but title screen says \"Super Tennis\").\r\n      SMS - 9dfa67ee - Teddy Boy Blues (JP)                 --> Teddy Boy Blues [Hack] (JP)\r\n      SMS - 60c19645 - Zillion                              --> Zillion [v0]\r\n      SMS - 5718762c - Zillion (US)                         --> Zillion [v1] (US)\r\n      GG  - bb4f23ff - Adventures of Batman and Robin       --> Adventures of Batman & Robin, The\r\n      GG  - 7a41c1dc - Aladdin                              --> Aladdin (Disney's)\r\n      GG  - 770e95e1 - Aladdin (JP)                         --> Aladdin (Disney's) (JP)\r\n      GG  - 4457e7c0 - Deep Duck Trouble / Donald Duck no.. --> Donald Duck no Yottsu no Himitsu (JP) (was Japanese dump)\r\n      GG  - f6af4b6b - Dynamite Headdy                      --> Dynamite Headdy (JP) (note: US/EU version is another dump)\r\n      GG  - 36aaf536 - Evander Holyfield Boxing             --> Evander Holyfield's \"Real Deal\" Boxing\r\n      GG  - 423803a7 - Gambler Jikochuushin Ha (JP)         --> Gyuwanburaa Jikochuushin Ha (JP)\r\n      GG  - 9f64c2bb - Ichidanto-R (JP)                     --> Ichidant~R (Puzzle & Action)\r\n      GG  - 8c048325 - Indiana Jones and the Last Crusade   --> Indiana Jones and the Last Crusade [BAD]\r\n      GG  - 4a98678b - Joe Montana Football                 --> Joe Montana Football (JP)\r\n      GG  - 90100884 - Jungle Book, The                     --> Jungle Book, The (Walt Disney's Classic)\r\n      GG  - 30c09f31 - Jungle Book, The (US)                --> Jungle Book, The (Walt Disney's Classic) (US)\r\n      GG  - 52dbf3e1 - Land of Illusion                     --> Land of Illusion - Starring Mickey Mouse\r\n      GG  - 0117c3df - Land of Illusion (JP)                --> Mickey Mouse no Mahou no Crystal (JP)\r\n      GG  - 0cd9c20b - Lion King, The                       --> Lion King, The (Disney's) (EU)\r\n      GG  - 9808d7b3 - Lion King, The (US)                  --> Lion King, The (Disney's) (US)\r\n      GG  - 00c34d94 - Madou Monogatari I - Mittsu no.. (JP)--> Madoh Monogatari I - Mittsu no Madokyuu (JP)\r\n      GG  - 12eb2287 - Madou Monogatari II - Aruru 16.. (JP)--> Madou Monogatari II - Aruru 16-sai (JP)\r\n      GG  - 0a634d79 - Madou Monogatari III - Kyukyok.. (JP)--> Madou Monogatari III - Kyuukyoku Joo-sama [v0] (JP)\r\n      GG  - 7ec95282 - Madou Monogatari A - Dokidoki-.. (JP)--> Madoh Monogatari A - Dokidoki-Bake Shon\r\n      GG  - cc90c723 - Pocket Jong Sou (JP)                 --> Pocket Jansou (JP)\r\n      GG  - afcc7828 - Psychic World                        --> Psychic World (JP)\r\n      GG  - 445d7cd2 - Royal Stone (JP)                     --> Royal Stone ~Hikarishi Toki no Tobira~ (JP)\r\n      GG  - 95efd52b - Ryu Kyu (JP)                         --> Ryuu Kyuu (JP)\r\n      GG  - 09f9ed60 - Shadam Crusader (JP)                 --> Shadam Crusader ~Harukanaru Oukoku~ (JP)\r\n      GG  - 2ae8c75f - Shanghai 2 (JP)                      --> Shanghai II (JP)\r\n      GG  - 4d1f4699 - Shining Force Gaiden (JP)            --> Shining Force Gaiden ~Ensei Jashin no Kuni e~ (JP)\r\n      GG  - 30374681 - Shining Force Gaiden II (JP)         --> Shining Force Gaiden II ~Jashin no Mezame~ (JP)\r\n      GG  - 6019fe5e - Shining Force Gaiden Final Con.. (JP)--> Shining Force Gaiden ~Final Conflict~ (JP)\r\n      GG  - 742a372b - Spider-Man and the X-Men in Arcade'..--> Spider-Man / X-Men: Arcade's Revenge\r\n      GG  - f1732ffe - Tale Spin                            --> TaleSpin\r\n      GG  - 09151743 - Tanto-R (JP)                         --> Tant~R (Puzzle & Action)\r\n      GG  - 3d8d0dd6 - World Series Baseball [A]            --> World Series Baseball [v0]\r\n      GG  - bb38cfd7 - World Series Baseball [B]            --> World Series Baseball [v1]\r\n      SG1 - 545fc9bb - Ashizawa's Hatchidan Tsumeshogi (JP) --> Serizawa Hachidan no Tsumeshogi (JP)\r\n      SG1 - 5970a12b - Champion Baseball                    --> Champion Baseball [16k]\r\n      SG1 - 6d909857 - Sega Mah-Jong (JP)                   --> Mahjong (Sega) (JP)\r\n      SG1 - e7e0f0e3 - Home Mah-Jong (JP)                   --> Home Mahjong [v1] (JP)\r\n      SG1 - 09196fc5 - N-Sub (1988)                         --> N-Sub [16k] (1988)\r\n      SC3 - 622010e1 - Sega Music Editor                    --> Music\r\n      SC3 - b67ea1c4 - Sega Music Editor                    --> Music [BAD]\r\n      SC3 - 2ec28526 - Sega Music Editor (JP)               --> Music (JP)\r\n      SC3 - ae4f92cf - Uranai Angel Cuty (JP)               --> Uranai Angel Cutie (JP)\r\n\r\n\r\n MEKA 0.71\r\n ---------\r\n  - Now that MEKA is open-source, welcoming other developpers!\r\n    - New contributor: Robert Raper (DjRobX)\r\n    - New contributor: Maxim Stephin (MaxSt)\r\n    Names between brackets refers to the person(s) involved in a change.\r\n  - Blitter/Video:\r\n    - Added triple buffering support on fullscreen blitters. [DjRobX]\r\n      Made triple buffering the default for appliable video modes. It might\r\n      or not work on all configuration. Please report if any problem arise.\r\n    - Added max stretch support on fullscreen blitters. [DjRobX]\r\n      This is currently only available on normal and HQ2X filter.\r\n      Integer/ratio stretch not yet supported, so it is recommended to use\r\n      a resolution multiple of the emulated system screen size.\r\n    - Added support for internally converting the 8-bit video buffer to\r\n      another video depth and blitting that. [DjRobX]\r\n    - Integrated Maxim Stephin's HQ2X graphics filter, and added a dedicated\r\n      blitter. Only 16-bits output is supported as of yet. [MaxSt,DjRobX]\r\n  - GUI:\r\n    - Fixed input box widget missing keys on skipped frames. [Omar]\r\n      This made key inputs very annoying on certain configuration, and\r\n      especially with 3-D glasses auto-frame-skipping enabled.\r\n    - Fixed a problem losing focus while dragging GUI windows with certain kind\r\n      of widgets (happened on tile viewer & memory editor, among other). [Omar]\r\n  - Development:\r\n    - Updated debugger documentation. [Omar]\r\n    - Added symbol loading in NO$GMB format, as generated by the commonly\r\n      used WLA DX linker (-s parameter). [Omar]\r\n    - Added label/symbol viewing in Z80 disassembly window. [Omar]\r\n    - Relative offsets are now resolved in Z80 disassembly window. [Omar]\r\n    - Added expression evaluator. [Omar]\r\n      Supports integer operators +,-,*,/, binary operators &,|,^,\r\n      parenthesis, symbols and CPU registers replacement.\r\n      Yet missing: unary operators -,!,~.\r\n      All commands uses the expression evaluator to get their numeric\r\n      parameters, so you can use it everywhere.\r\n      eg:\r\n        B function    ; break at given 'function' symbol\r\n        M my_data     ; memory dump from 'my_data' symbol\r\n    - Added PRINT (P) command to evaluate and print expressions. [Omar]\r\n      eg:\r\n        P IX,IY       ; print IX and IY registers\r\n        P 1200+34     ; print $1234\r\n        P %00101010   ; print 42\r\n        P HL+(BC*4)   ; print HL+BC*4\r\n        P label       ; print label\r\n    - Added contextual command line completion. [Omar]\r\n      Press TAB to complete current input with matching command/symbols.\r\n      eg:\r\n        b[tab]        ; -> BREAK\r\n        b[tab]la[tab] ; -> BREAK label\r\n    - Added SYMBOLS (SYM) command to list and search for a symbol. [Omar]\r\n    - Changed breakpoint/watchpoint range syntax to '..' to avoid any\r\n      syntaxical ambiguity with substraction (eg: B 1000..2000). [Omar]\r\n    - Added \"B ENABLE/DISABLE ALL\" shortcuts to enable/disable all\r\n      breakpoints at once. [Omar]\r\n    - Added \"B CLEAR DISABLED\" shortcut to clear disabled breakpoints. [Omar]\r\n    - Added \"Reload ROM\" functionnality in the debug menu, for quicker reload.\r\n    - Palette viewer now shows color entry data while hovering colors. [Omar]\r\n    - Fixed display of CPU flags (only bit 0 was properly interpreted,\r\n      because of a typo). Added display of undocumented flags bits 3\r\n      and 5 (partially emulated). [Omar]\r\n    - Made it that debugger log to file is immediately flushed. This allows\r\n      reading the log file in live while the debugger is running. [Omar]\r\n    - Added REGS (R) command to dump Z80 registers to the log console. [Omar]\r\n    - Added animation displaying weither CPU is running or not. [Omar]\r\n    - Fixed behavior of step/step over/continue when executing while being\r\n      located on a breakpoint. [Omar]\r\n    - Fixed behavior of step over an infinite loop. [Omar]\r\n  - Miscellaenous:\r\n    - (Win32) Added a \"setup.bat\" command file to run the interactive setup.\r\n      Seems like few people were aware of the command-line option. [Omar]\r\n    - (Win32) The interactive setup now offers to enable/disable the debugger,\r\n      so you don't have to manually enable it. [Omar]\r\n    - (Win32) Updated Allegro library from WIP 4.1.12 to 4.1.18, which includes\r\n      various fixes/improvements:\r\n        http://www.talula.demon.co.uk/allegro/onlinedocs/en/changes.html\r\n    - (Win32) Fixed crash on early aborting (eg: command line error) due to non\r\n      properly stopping joystick polling thread. [Omar]\r\n    - Fixed loading of corrupted or incorrectly sized ROM images that would\r\n      sometimes made the engine crash. [Omar]\r\n    - Updated various tidbits of documentation. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n      SMS - 60c19645 - Akai Koudan Zillion (JP)             --> Zillion / Akai Koudan Zillion  (note: this ROM was released in both Japan and Europe)\r\n      SMS - a1710f13 - Lucky Dime Caper, The                --> Lucky Dime Caper, The - Starring Donald Duck\r\n      SMS - 5718762c - Zillion                              --> Zillion (US)\r\n      GG  - 7b7717b8 - Big War / Daisenryaku G (JP)         --> Taisen-gata Daisenryaku G (JP)\r\n      GG  - a49e9033 - NBA JAM                              --> NBA JAM (JP)\r\n\r\n  Note that DjRobX's video/blitter changes were integrated but some features\r\n  may not be compatible with all others, and some need improvements. You are\r\n  welcome to experiment different configuration settings in MEKA.BLT but not\r\n  everything may work properly. The preset \"HQ2X\" blitter should works, though.\r\n\r\n  The current blitter system makes it not trivial to do everything we want,\r\n  it is too limited in configuration, and was first made with MS-DOS and low\r\n  end computers in mind. As of next versions, I will work on reoverhauling the\r\n  system, trying to better fits needs of the 21st century (resizing, multiple\r\n  depth, hi-color, windowed modes without borders, non 4:3 ratio screens,\r\n  different refresh rates...) and improve ease of setupping.\r\n  Expect many changes in this area (hopefully). [Omar]\r\n\r\n  - Sources/Project\r\n    - (Linux) Updated Makefile and some sources tidbits for proper compilation.\r\n      [Omar,Belegdol,Proppy]\r\n    - (Linux,DOS) Object directories are now created automatically. [Omar]\r\n    - (Linux,DOS) Removed \"smscheck\" tool building from Makefile. Has nothing\r\n      to do with MEKA. [Omar]\r\n    - (Linux,DOS) Added 'BUILD' switch in Makefile to select between release\r\n      and debug builds.\r\n    - (Win32) Make it that build date/time stamp in build.c is updated when\r\n      rebuilding the solution. Removed buildupd.exe executable from sources. [Omar]\r\n    - (DOS) I'm stopping to maintain the MS-DOS port. A maintener is welcome. [Omar]\r\n\r\n\r\n MEKA 0.70\r\n ---------\r\n  - Released source code.\r\n    Added SOURCES.TXT file with some information for programmers.\r\n  - Registration key is a thing of the past. It never served a real purpose\r\n    other than identifying donators. All donators are publicly listed at:\r\n        http://www.smspower.org/contrib.htm\r\n    Big thanks to all of them for their great and useful support!\r\n    I'll keep sending news/e-mails to donators.\r\n    MEKA is now officially not having a registration procedure anymore, but\r\n    your donations are still greatly welcome and are helping me to cover a\r\n    part of my never-ending Sega 8-bit expenses, including buying cartridges\r\n    for dumping and preservation purpose.\r\n    I updated documentation to reflect this, and changed occurences of the\r\n    \"registration\" word by \"donation\", as it was always meant to be anyway.\r\n  - In SMS mode, fixed color filling when VDP rendering is disabled.\r\n    Previously disabled parts where filled with black, instead of the current\r\n    border color. No commercial game exhibited the problem. Chris Covell's\r\n    port of Aleste 2 from GG to SMS did.\r\n  - Disabling background display now shows a yellow-ish color instead of the\r\n    black/border color, to help sprite ripping. Sorry it's not FF00FF pink,\r\n    but I am currently lacking free palette entries, and anyway, a screen full\r\n    of FF00FF pink would damage your eyes in a matter of seconds. :)\r\n  - Development:\r\n    - Added new full-featured breakpoints and watchpoints!\r\n      - Manage multiple breakpoints/watchpoints. Add/remove/enable/disable.\r\n      - Break and watch on CPU (rwx), IO (rw), VRAM (rw) and PRAM (w) buses.\r\n      - Break and watch on specific access (read/write/execute).\r\n      - Break and watch on single address or whole range.\r\n      - Previous \"B\" command changed to \"S\" (step over).\r\n      - Previous \"B xxxx\" command (one-time breakpoint) is still accessible\r\n        using the \"C\" (continue) command.\r\n    - Added detailed help for each command.\r\n      (eg: \"HELP B\" to get help on breakpoints).\r\n    - Instruction flow disassembly now attempt to display instructions before\r\n      the current one, based on some magical voodoo technique of mine.\r\n      Don't expect it to work in all cases - it is theorically impossible to\r\n      do with variable-sized instructions anyway - but it can be improved.\r\n      This feature helps figuring out what's being executed contextually.\r\n    - The current instruction is now highlighted.\r\n    - ROM edition in the memory viewer was not taken into account without\r\n      a hard reset in region 0x0400-0x3FFF. Fixed.\r\n    - Fixed savestate saving/loading which didn't restore scanline number\r\n      properly, affecting debugging using those features.\r\n    - Tile viewer now display tile starting address.\r\n    - Tile viewer now update information while mouse hovering.\r\n    - Added optional length parameter to \"MEM\" and \"DASM\" commands.\r\n    - Fixed ASCII display of memory in \"MEM\" command.\r\n    - Added \"debugger_console_lines\" and \"debugger_disassembly_lines\"\r\n      variables in configuration file, allowing to change debugger size.\r\n      Combine with a high-resolution MEKA desktop, and you can't be unhappy.\r\n    - Added debugger session logging to file \"debug/debuglog.txt\".\r\n      Can be disabled by clearing \"debugger_log\" in configuration file.\r\n    - Fixed a bug using the memory editor to write to RAM in Coleco Vision mode.\r\n    - Hacked a way so that you can affect controller inputs data while debugging\r\n      (press a direction, it immediately apply on the emulated system state).\r\n\r\n  - When used in the interface, analog peripherals supported by the mouse now\r\n    only perform their action if the mouse has focus on the game window.\r\n    This prevent accidental in-game shooting when using tools or debugging.\r\n    Of course, you should not use the interface if you only intend to play.\r\n  - Fixed /LOG command line parameter (broken recently).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Redumped more games, sorted more versionning/country confusion.\r\n    To avoid certain confusion, all Game Gear games originally running\r\n    in Master System mode were moved back in the Game Gear section.\r\n    This makes the list consistant with actual cartridge releases.\r\n    Some particular renaming includes:\r\n      SMS - 17a40e29 - Alex Kidd in Miracle World (US)      --> Alex Kidd in Miracle World [v0] (US)\r\n      SMS - aed9aac4 - Alex Kidd in Miracle World           --> Alex Kidd in Miracle World [v1] (note: this was released in both US and Europe)\r\n      SMS - 08c9ec91 - Alex Kidd in Miracle World (JP)      --> Alex Kidd no Miracle World (JP)\r\n      SMS - 0df8597f - Basket Ball Nightmare                --> Basketball Nightmare\r\n      SMS - e421e466 - Borgman (JP)                         --> Chouon Senshi Borgman (JP)\r\n      SMS - 11645549 - Solomon no Kagi (JP)                 --> Solomon no Kagi - Oujo Rihita no Namida (JP)\r\n      SG  - 0b4bca74 - Border Line (JP)                     --> Borderline\r\n      SG  - 922c5468 - Souko Ban (JP)                       --> Soukoban (JP)\r\n      SG  - 1ae94122 - Star Jacker [old] (JP)               --> Star Jacker [v0] (JP)\r\n      SG  - 7f25deca - Star Jacker [new] (JP)               --> Star Jacker [v1]\r\n      GG  - fe12a92f - Densetsu no Houguku (JP)             --> Mickey Mouse Densetsu no Oukoku (JP) (terrible typo)\r\n      GG  - 937fd52b - Kaito Saint Tail (JP)                --> Kaitou Saint Tail (JP)\r\n      GG  - dfa805a0 - Hanou no Toukyuuji Dodge Danpei (JP) --> Honoo no Toukyuuji Dodge Danpei (JP)\r\n\r\n\r\n MEKA 0.69b\r\n ----------\r\n  - [DOS/UN*X] Fixed ZIP file support which was accidently disabled\r\n    in version 0.69.\r\n  - Improved auto frame-skipper precision by a minor amount.\r\n    (on another hand, it still manage to skip frames badly).\r\n  - Disabled keys 0 to 9 to set a save state slot directly.\r\n    Those conflicted with some existing and future features.\r\n    Hope that noone will be annoyed!\r\n  - Added ALT-ENTER hotkey to switch between fullscreen and windowed drivers.\r\n    It works in both GUI and Game mode, although the setting is not saved in\r\n    Game mode (due to the way the MEKA.BLT file works now).\r\n  - Added an option to allows pressing opposite directions on the joypad.\r\n    Although standard SG/SMS/GG controllers do not allow that, certain\r\n    type of controllers (or a modified or broken one) may allow it.\r\n    This serve the purpose of demonstrating a bug in \"Wonder Boy in Monster\r\n    Land\", where pressing Left and Right on the same time confuses the game.\r\n    It is also useful in the case some creative genius SMS programmer would\r\n    want to take advantage of that weird feature to do unusual things for a\r\n    soon-to-be released SMS software.\r\n  - Fixed priority of Sega Keyboard (SK-1100) emulation, so that not colliding\r\n    hotkeys are still available while SK-1100 is enabled.\r\n  - Memory Editor now share inputs focus with game. It makes hacking easier.\r\n    Of course you can always pause (F12) or remap controls if needed.\r\n  - Fixed state of debugger window (bug introduced in 0.69).\r\n  - Updated translations:\r\n    - Dutch translation (by Mark van Tilburg).\r\n    - Swedish translation (by Henrik Sankala).\r\n    - Redneck translation (by some redneck in UK).\r\n\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - 31ffd7c3 - Castelo RETim Bum (BR)              --> Castelo RETim-Bum (BR)\r\n      SMS - b137007a - Desert Speedtrap                     --> Desert Speedtrap - Starring Road Runner and Wile E. Coyote\r\n      SMS - 7abc70e9 - Party Games / Family Games (JP)      --> Family Games (Party Games) (JP)\r\n      GG  - 7174b802 - Baku Baku Animal (JP)                --> Baku Baku Animal - Sekai Shiikugakari Senshu-ken (JP)\r\n      GG  - 03d28eab - Crayon Shin Chan (JP)                --> Crayon Shin Chan - Taiketsu! Tankam Panic!! (JP)\r\n      GG  - ec808026 - Desert Speedtrap                     --> Desert Speedtrap - Starring Road Runner and Wile E. Coyote\r\n      GG  - c2e111ac - Desert Speedtrap (US)                --> Desert Speedtrap - Starring Road Runner and Wile E. Coyote (US)\r\n      GG  - a1a19135 - GG League '94 (JP)                   --> Pro Yakyuu GG League '94 (JP)\r\n      GG  - 4cf97801 - Godzilla (JP)                        --> Godzilla - Kaiju Dai-Shingeki (JP)\r\n      GG  - 86c32e5b - NBA Jam TE                           --> NBA JAM Tournament Edition\r\n      GG  - 751dad4c - Slam Dunk (JP)                       --> From TV animation - Slam Dunk - Shouri-e no Starting 5 (JP)\r\n      GG  - dd1d2ebf - Tamalympic (JP)                      --> Tama & Friends - 3chome Koen Tamalympic (JP)\r\n    And an awful typo saying \"Carmen Sandegio\" instead of \"Carmen Sandiego\".\r\n\r\n\r\n MEKA 0.69\r\n ---------\r\n  - Updated k.\r\n  - Updated documentation.\r\n  - Added a Memory Editor, long awaited by programmers, hackers and cheaters!\r\n    It allows reading and writing to Z80 memory map, ROM, RAM, VRAM, Palette\r\n    and Battery Backed RAM. Although it is not yet full-featured, it is\r\n    already very possible to create your own Pro Action Replay codes, and\r\n    perform various real-time hacks.\r\n    Please share your questions and hacks on SMS Power forums:\r\n        http://www.smspower.org/forum\r\n    This tool is the result of joint work with my beloved girlfriend, who\r\n    submitted a first version of it that she developped.\r\n  - Added support for loading and saving pictures in PNG format. PNG is now\r\n    the default format for screenshots, instead of the badly outdated PCX.\r\n    (thanks to libpng).\r\n  - Screenshots are now saved in the \"Screenshots/\" subdirectory.\r\n  - Tweaked some themes, reordered them, removed a few. Themes backgrounds\r\n    are now in PNG format. Please be sure to download the new picture pack at:\r\n        http://www.smspower.org/meka/themes\r\n  - [Windows] Added a message console that shows up on startup and magically\r\n    disappear before you have time to read anything. If any problem occurs,\r\n    the console will actually stay to let you read it.\r\n  - [Windows] Fixed runtime application icon that wasn't showing.\r\n  - [Windows] Removed command line parameters uppercase conversion (eg: when\r\n    ran from Windows explorer). This inconveniently created uppercase output\r\n    filenames for savestates, screen captures, etc. This was MS-DOS legacy.\r\n  - Slighty optimized VRAM accesses emulation.\r\n  - Incremented message buffer size to cope with SMS Chip-8 Interpreter 1.1\r\n    11k embedded comment. There is still buffer overflows in the code and\r\n    I'm not trying to fix most of them now, so this is just a work-around.\r\n  - Various other fixes and code tweaking.\r\n\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - 655fb1f4 - Bank Panic                           --> Bank Panic\r\n      SMS - b4dfb825 - Bank Panic                           --> Bank Panic [BAD]\r\n      SMS - 102d5fea - James Pond 2 - Codename Robocod      --> James Pond II - Codename: Robocod\r\n      SMS - e8ea842c - Marksman Shooting / Trap Shooting    --> Marksman Shooting & Trap Shooting\r\n      SMS - 00bef1d7 - Phantasy Star                        --> Phantasy Star [v3]\r\n      SMS - 07301f83 - Phantasy Star [Saturn]               --> Phantasy Star [Saturn]\r\n      GG  - c01293b0 - Devilish                             --> Devilish (US)\r\n      GG  - 06247dd2 - Ninku 2 (JP)                         --> Ninku 2 ~Tenkuryu-e no Michi~ (JP)\r\n      GG  - 00c34d94 - Madou Monogatari I (JP)              --> Madou Monogatari I - Mittsu no Madokyu (JP)\r\n      GG  - 0a634d79 - Madou Monogatari II (JP)             --> Madou Monogatari II - Aruru 16-sai (JP)\r\n      GG  - 12eb2287 - Madou Monogatari III (JP)            --> Madou Monogatari III - Kyukyoku Joo-sama (JP)\r\n      GG  - 7ec95282 - Madou Monogatari A                   --> Madou Monogatari A - Dokidoki-Bake Shon (JP)\r\n      GG  - c169c344 - X-Men - Gamesmaster's Legacy         --> X-Men - GamesMaster's Legacy\r\n\r\n    Use SMS Checker for your ROM renaming needs!\r\n        http://www.smspower.org/maxim/smschecker\r\n\r\n\r\n MEKA 0.68b\r\n ----------\r\n As an experiment, I have enabled vsync in all default blitters and enabled\r\n it by default in the GUI. Blitters are still a bit complicated to configure\r\n so few people seems to actually tweak them or even enable the \"smooth\"\r\n blitter. Does it works better for you?\r\n I'll be working on synchronisation and blitter improvement (stretching...)\r\n in the future.\r\n\r\n  - Removed the 2-byte tolerance in overdump detection. Overdumps with two\r\n    slighty different half will be added in the database and marked as bad.\r\n  - Emulation:\r\n     - Fixed a major bug in the driver system, which resulted in corrupted\r\n       savestates in F-16 Fighter / F-16 Fighting Falcon (the savestate\r\n       system recognized them as SG-1000 games and so saved only part of RAM).\r\n       Previous ingame states for the game are unrecoverable :(\r\n     - Removed immediate palette update when CRAM is written in a legacy\r\n       video mode (the palette isn't updated on a SMS). It only affected\r\n       F-16 Fighter / F-16 Fighting Falcon, but in a non game-visible way.\r\n     - Tweaked heuristical SMS/GG mapper detection.\r\n     - Fixed SMS/GG scanline counter emulation which was ignoring TV type\r\n       (NTSC or PAL/SECAM) override directive from the database.\r\n       (eg: one game would be forced to PAL/SECAM mode, but scanline counter\r\n        emulation still mimic an NTSC system if it is the user selection).\r\n  - Fixed mouse button mapping in the Input Configuration applet.\r\n  - Fixed file browser showing Japanese names after loading SMS Woody Pop\r\n    or GG Pop Breaker (why those games only? because they both have a default\r\n    country information in the DB, as they only works on Japanese systems).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      GG  - Ganbare Golby! (JP)             --> Ganbare Gorby!\r\n\r\n\r\n MEKA 0.68\r\n ---------\r\n Please report any problems you encounter.\r\n Suggestions are always welcome.\r\n\r\n  - Updated MEKA.NAM database with a new format.\r\n    The new format is more robust, includes CRC32, additionnal flags, and\r\n    allows specifiying multiple countries for a same ROM file.\r\n    In addition, while the MEKA database is being repopulated with entries\r\n    in the new format, a high amount of verifications are being done on a\r\n    case by case basis (redump, verified name based on original game media,\r\n    box and manual, analysis of different versions of a same game, etc...).\r\n    I have already redumped more than a hundred games. This will unsure\r\n    having a near-perfect database after the transition. Old formatted\r\n    entries are kept during the transition period.\r\n  - SMS-mode Game Gear games are now autodetected and forced to run into\r\n    SMS mode even with a .GG extension. This is because those games are\r\n    often spread with a .GG extension, although there is no way in software\r\n    to distinguish between a native GG game and one running in SMS mode,\r\n    since the selection is done via a connected pin in the cartridge itself.\r\n  - Updated file browser:\r\n      - Added dedicated icons to known bad dumps, BIOS images, unofficial\r\n        hacks, homebrew programs (also incorrectly called \"public domain\"),\r\n        prototypes and unofficial translation. A translation is defined as\r\n        a hack whose primary purpose is to alter the language of a game.\r\n        How do you like my icons?\r\n      - Added European, German, Italian, New-Zealand, Portuguese, Spanish,\r\n        Swedish and United-Kingdom flags. All flags are now displayed with\r\n        a border, because some themes may choose a window color matching\r\n        some flags.\r\n      - The \"Load Names\" feature is now faster and does not verbose any\r\n        data to the message box while loading all files.\r\n      - Made file browser window bigger by default.\r\n      - Removed the auto-generated MEKA.VFN file, which was crap anyway.\r\n        Instead, added a new auto-generated MEKA.FDB file, which store\r\n        association between user ROM file names and MEKA DataBase entries.\r\n  - Emulation:\r\n      - Emulated VDP 315-5124 behavior of using register 5 bit 0 and\r\n        register 6 bits 0-1 as masks on sprite x/tile attributes address\r\n        and tile index. No known game relies on this feature, but it is\r\n        good for the sake of accuracy and for developpers to check against\r\n        this particularity in their code (it is often a coding mistake).\r\n        VDP 315-5124 must be selected for that.\r\n  - Updated TECH.TXT with SMS controller pinouts, simple SMS/DB-9 controller\r\n    adapter instructions from Gary Pierce, and GNU/Linux notes.\r\n  - Various other fixes and code tweaking.\r\n\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n      - Naming and database field usage convention has been changed,\r\n        based on the new format.\r\n        - \"Title (The)\" now becomes \"Title, The\".\r\n        - Unless specified by the game title, \"Name: Subtitle\" now\r\n          becomes formatted \"Name - Subtitle\".\r\n        - A few other things related to versionning/country.\r\n      - Replaced all instances of \"Tectoy\" by \"Tec Toy\".\r\n      - Added some missing accents.\r\n      - Added many missing subtitles.\r\n      - Added many new product numbers.\r\n    Some particular renaming includes:\r\n      SMS - Alex Kidd BMX Trial (JP)        --> BMX Trial - Alex Kidd (JP)\r\n      SMS - Ninja Gaiden [B]                --> Ninja Gaiden\r\n      SMS - Ninja Gaiden [A]                --> Ninja Gaiden [Proto]\r\n      SMS - Putt & Putter [B]               --> Putt & Putter\r\n      SMS - Putt & Putter [A]               --> Putt & Putter [Proto]\r\n      SMS - Smash TV                        --> Super Smash T.V.\r\n      SMS - World Games [B]                 --> World Games\r\n      SMS - World Games [A]                 --> World Games [Proto]\r\n      GG  - GG Portrait: Akira (JP)         --> GG Portrait - Yuuki Akira (JP)\r\n      GG  - Halley Wars                     --> Halley Wars (JP)\r\n      GG  - Ninku Gaiden 2 (JP)             --> Ninku 2 (JP)\r\n      GG  - Pet Club Neko Dai Suki (JP)     --> Neko Daisuki! (JP)\r\n      GG  - Pet Club Inu Dai Suki (JP)      --> Pet Club Inu Daisuki! (JP)\r\n      GG  - Putt & Putter                   --> Putt & Putter (JP)\r\n      GG  - Shinkinjoh (JP)                 --> Shikinjou (JP)\r\n      GG  - Tempo JR                        --> Tempo Jr.\r\n      GG  - Winter Olympics                 --> Winter Olympics (JP)\r\n    The list above doesn't include ALL renaming, but only those I felt are\r\n    the most important to be propagated. Many other renaming were done.\r\n\r\n\r\n MEKA 0.67\r\n ---------\r\n  - Updated documentation.\r\n  - Tweaked the auto-frame skipper. Please let me know if you notice any\r\n    improvement or new problem.\r\n  - The analog Paddle Control is now usable using a digital keyboard or\r\n    joystick input, although it is HIGHLY recommended to use a mouse.\r\n    Playing with a keyboard or joystick may be sometimes frustrating and\r\n    does not allows fast movements.\r\n  - Updated debugging mode:\r\n      - Scrapped old, buggy, and unusable MS-DOS only text mode debugger.\r\n      - Added new debugger, well integrated into the GUI and functionnal\r\n        with all versions of MEKA. It is a primitive debugger, but it can\r\n        be helpful and it is definitively better than nothing.\r\n        Supports step-into, step-over, breakpoint, jump, disassembly and\r\n        memory dump. Expression are not evaluated and syntax is primitive.\r\n        Enable with the /DEBUG command line parameter.\r\n      - [Windows] Data dumping facilities are now working.\r\n  - Updated patching system (see MEKA.PAT file):\r\n      - Updated syntax.\r\n      - Support for long awaited RAM patches!\r\n        One of the side effect to that is that you can now apply\r\n        PRO ACTION REPLAY codes easily. This feature is unfortunately\r\n        not backuped by a full-featured interface and cheats database,\r\n        but is helpful and better than nothing - while waiting for\r\n        advanced cheating functionnalites to be added in the future.\r\n      - Support for CRC32 to specify the game to apply patches on,\r\n        as well as using MEKA proprietary checksum format.\r\n      - Putting * in the CRC field will apply a patch to all games.\r\n      - Minor bug fixes.\r\n  - Inputs:\r\n      - [Windows] Fixed joystick sliders support (DirectInput < 8.00\r\n        usually reports the fourth and fifth axis of a joystick as\r\n        being sliders, which is a weird little known behavior).\r\n      - File browser now takes exclusive inputs so the emulated game\r\n        is not affected by keypresses.\r\n  - Fixed file browser \"Load Names\" feature. It was broken in version 0.66,\r\n    and sometimes (not always) went into an infinite loop in earlier version.\r\n  - [Windows] Command line parameters help is now displayed in a message box.\r\n  - Closing a box now automatically focus the next one in focus order.\r\n  - Various other fixes.\r\n  - Updated Dutch translation (by Mark van Tilburg).\r\n\r\n  - Added and modified entries in the checksum and compatibility lists,\r\n    on the road to perfection. Added many missing (J) flags in the Game Gear\r\n    compatibility list. Added a few missing accents.\r\n    Some particular renaming includes:\r\n      SMS - Back to the Future 2            --> Back to the Future II\r\n      SMS - Back to the Future 3            --> Back to the Future III\r\n      SMS - Blade Eagle 3D                  --> Blade Eagle 3-D\r\n      SMS - California Games 2              --> California Games II\r\n      SMS - Chuck Rock 2                    --> Chuck Rock II: Son of Chuck\r\n      SMS - Ecco 2: the Tides of Time       --> Ecco: The Tides of Time\r\n      SMS - Fantazy Zone 2                  --> Fantazy Zone II\r\n      SMS - Fantasy Zone 3: the Maze        --> Fantasy Zone: The Maze\r\n      SMS - Golvellius                      --> Golvellius: Valley of Doom\r\n      SMS - High School Kimengumi           --> High School! Kimengumi\r\n      SMS - Jogos de Verao 2                --> Jogos de Verão II\r\n      SMS - Maze Hunter 3D                  --> Maze Hunter 3-D\r\n      SMS - Missile Defense 3D              --> Missile Defense 3-D\r\n      SMS - Out Run 3D                      --> Out Run 3-D\r\n      SMS - Pac-Mania                       --> Pacmania\r\n      SMS - Poseidon Wars 3D                --> Poseidon Wars 3-D\r\n      SMS - Rambo: First Blood Part 2       --> Rambo: First Blood Part II\r\n      SMS - Secret Commando                 --> Secret Command\r\n      SMS - Space Harrier 3D [Export]       --> Space Harrier 3-D\r\n      SMS - Sport Pad Football              --> Sports Pad Football\r\n      SMS - Sport Pad Soccer                --> Sports Pad Soccer\r\n      SMS - Super Monaco GP 2               --> Super Monaco GP II (Ayrton's Senna)\r\n      SMS - Turma da Mônica em o Resgate    --> Turma da Mônica em: O Resgate\r\n      SMS - Wonder Boy in Monster Land [A]  --> Wonder Boy in Monster Land\r\n      SMS - Wonder Boy in Monster Land [B]  --> Wonder Boy in Monster Land [Hack]\r\n      SMS - Wonder Boy in Monster Land [C]  --> Super Wonder Boy Monster Land / World [Japan]\r\n      SMS - World Cup '92 (Tecmo)           --> World Cup '93 (Tecmo) (Proto)\r\n      SMS - Wimbledon 2                     --> Wimbledon II\r\n      SMS - Winter Olympic '94              --> Winter Olympics\r\n      SMS - Ys: Vanished Omen\t\t\t\t--> Y's: The Vanished Omens\r\n      SMS - Ys: Vanished Omen [Japan]\t\t--> Ys [Japan]\r\n      SMS - Zaxxon 3D [Export]              --> Zaxxon 3-D\r\n      SMS - Zillion 2 [Export]              --> Zillion II: The Tri Formation\r\n      GG  - Chuck Rock 2                    --> Chuck Rock II: Son of Chuck\r\n      GG  - Desert Speedtrap                --> Desert Speedtrap [USA]\r\n      GG  - Ecco 2: the Tides of Time       --> Ecco: The Tides of Time\r\n      GG  - Gun Star Heroes [Japan]\t\t\t--> Gunstar Heroes [Japan]\r\n      GG  - Super Monaco GP 2               --> Super Monaco GP II (Ayrton's Senna)\r\n      SG  - Championship Lode Runner [B]    --> Championship Lode Runner\r\n      SG  - Hang On 2                       --> Hang On II\r\n      SG  - Hyper Sports                    --> Hyper Sports (Konami no)\r\n      SG  - Pitfall 2                       --> Pitfall II\r\n      SG  - Rockn' Bolt                     --> Rock n' Bolt\r\n      SG  - Shinnyushain TooruKun           --> Shinnyushain Tooru Kun (Konami no)\r\n      SG  - Sindbad Mystery [A]             --> Sindbad Mystery\r\n\r\n    Please use SMS Checker for your ROM renaming needs!\r\n    http://www.smspower.org/maxim/smschecker\r\n\r\n\r\n MEKA 0.66\r\n ---------\r\n Blitting & synchronisation are still very bad in many cases. This is my\r\n top priority but I still cannot find a good solution to improve it and\r\n please everyone (slow and fast computers). I can't sleep! :(\r\n Use the \"smooth\" blitter if possible.\r\n\r\n  - Updated default blitters (MEKA.BLT).\r\n  - Video mode is not reinitialized anymore when switching blitters with\r\n    the same resolution/refresh rate. This saves a bit of time.\r\n  - [Windows] Fixed page flipping, for those using it (see MEKA.BLT file).\r\n  - [Windows] Sega 3-D Glasses support is now properly working in MEKAW!\r\n    If you build the simple 3-D Glasses to COM adapter (as described in\r\n    the TECH.TXT file), it is possible to plug original 3-D glasses and\r\n    enjoy 3-D games as they were meant to be played - and additionnally,\r\n    damage your eyes due to intense flickering :)\r\n    Best results are achieved by enabling page flipping or vsync.\r\n  - [DOS] Sega 3-D Glasses support now also works under a Windows 95/98\r\n    command prompt.\r\n  - Increased maximum number of joystick buttons to 32 (instead of 16).\r\n  - Partly fixed incorrect joystick axis reporting. It was a problem for\r\n    many people, and made it impossible or difficult to configure joysticks\r\n    using the interface. One extended joystick axis may be missing now,\r\n    until I can find a solution to this other problem.\r\n  - Tile viewer can now be configured to displayed all 512 tiles, instead\r\n    of the first 448 only. The bottom tiles looks awful with most SMS/GG\r\n    games but some games use this area so it's good to see them.\r\n  - Tile viewer now allows to select all 15 colors to display tiles in\r\n    TMS9918 video modes (used by SG-1000, SC-3000, Coleco Vision, etc.).\r\n  - Loading a ROM now display the full name in the message box.\r\n  - [Windows] Upgraded MSVC compiler from version 5.0 to 7.1 (might bring\r\n    a small improvement on performance). Removed ZLIB.DLL from the\r\n    distribution and statically linked it to the executable.\r\n  - [Windows] Fixed mekaw.cfg saving location. It was saving in a wrong\r\n    place in some cases (depending how you run it).\r\n  - Updated Danish translation (by Mark Klemp).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - Asterix [A]                     --> Asterix [V0]\r\n      SMS - Asterix [B]                     --> Asterix [V1]\r\n      SMS - Chuck Rock 2 [A]                --> Chuck Rock 2 [Europe]\r\n      SMS - Chuck Rock 2 [B] [Brasil]       --> Chuck Rock 2 [Brasil]\r\n      SMS - Golfamania [1990]               --> Golfamania\r\n      SMS - Golfamania [1989]               --> Golfamania (Proto)\r\n      SMS - James Pond 2: Robocod           --> James Pond 2: Codename Robocod\r\n      SMS - Lemmings [A]                    --> Lemmings\r\n      SMS - Lemmings [B]                    --> Lemmings (Proto)\r\n      SMS - Mortal Kombat 2                 --> Mortal Kombat II\r\n      SMS - Pit Fighter [A]                 --> Pit Fighter [Europe]\r\n      SMS - Pit Fighter [B] [Brasil]        --> Pit Fighter [Brasil]\r\n      SMS - Rainbow Island [A]              --> Rainbow Island [Europe]\r\n      SMS - Rainbow Island [B] [Brasil]     --> Rainbow Island [Brasil]\r\n      SMS - Seishyun Scandal [Japan]        --> Seishun Scandal [Japan]\r\n      SMS - Taz-Mania [A]                   --> Taz-Mania\r\n      SMS - Taz-Mania [B]                   --> Taz-Mania (Proto)\r\n      SMS - Tom and Jerry: the Movie [A]    --> Tom and Jerry: The Movie\r\n      SMS - Tom and Jerry: the Movie [B]    --> Tom and Jerry: The Movie (Proto)\r\n      SMS - Ultima IV [A]                   --> Ultima IV\r\n      SMS - Ultima IV [B]                   --> Ultima IV (Proto)\r\n      SMS - Wonder Boy 3: the Dragon's Trap --> Wonder Boy III: The Dragon's Trap (Proto)\r\n      SMS - Woody Pop [Japan]               --> Woody Pop: Shinjinrui no Block Kuzushi [Japan]\r\n      GG  - Lemmings [A]                    --> Lemmings\r\n      GG  - Lemmings [B]                    --> Lemmings (Proto)\r\n      GG  - Monster World 2 [Japan]         --> Monster World II\r\n      GG  - Mortal Kombat 2                 --> Mortal Kombat II\r\n      GG  - Wonder Boy 3: the Dragon's Trap --> Wonder Boy III: The Dragon's Trap (Proto)\r\n    Please use SMS Checker for your ROM renaming needs!\r\n    http://www.smspower.org/maxim/smschecker\r\n\r\n\r\n MEKA 0.65c\r\n ----------\r\n  - Fixed Z80 interruption timing.\r\n    I have tested several \"sensitive\" games and nothing should have been\r\n    broke, but please e-mail me if you notice anything unusual.\r\n    In addition, the fix allowed to remove the need for a custom parameter\r\n    in MEKA.NAM for 5 more games.\r\n  - Fixed MEKA.PAT which added a bug to pausing in Wonder Boy III [SMS].\r\n    The bug was a leftover of one of my working session, and I forgot to\r\n    remove it before releasing the official distribution of version 0.65b.\r\n  - Fixed user inputs during the next frame after loading a savestate.\r\n    Previously, they were reseted on savestate loading, meaning that your\r\n    inputs were ignored on the first 1/60th second after loading. Although\r\n    this is not dramatic in most cases, in a few it made savestates unusable\r\n    because the player would die on loading without being able to react.\r\n    Now you have that missing 1/60th second.\r\n  - Attempted to fix the occasionnal crash on shutdown. I don't know if it\r\n    happens anymore or not.\r\n  - Updated Swedish translation (by Henrik Sankala).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - Double Target [Japan]   --> Double Target Cynthia no Nemuri [Japan]\r\n      SMS - Formula 1               --> F1\r\n      SMS - Machine Gun Joe [Japan] --> Comical Machine Gun Joe [Japan]\r\n      SMS - Pit Pot [Japan]         --> Fushigi no Oshiro Pit Pot [Japan]\r\n      SMS - Sonic the Hedgehog [A]  --> Sonic the Hedgehog [V0]\r\n      SMS - Sonic the Hedgehog [B]  --> Sonic the Hedgehog [V1]\r\n      SMS - Transbot                --> TransBot\r\n      GG  - Columns                 --> Columns [Japan]\r\n      GG  - Formula 1               --> F1\r\n      GG  - Pengo                   --> Pengo [Japan]\r\n      GG  - Jungle Book             --> Jungle Book [USA]\r\n      GG  - Woody Pop               --> Woody Pop [V0]\r\n    Please use SMS Checker for your ROM renaming needs!\r\n    http://www.smspower.org/maxim/smschecker/smschecker.htm\r\n\r\n\r\n MEKA 0.65b\r\n ----------\r\n  - Updated k.\r\n  - Fixed TV Mode which was accidentaly broken in version 0.65 (due to\r\n    recent palette system rewrite). Sorry for the inconvenience. I also\r\n    took the occasion to slighty optimize it.\r\n  - Fixed still screens corruption in Game Gear version of \"Bart vs. the\r\n    Space Mutants\". It was affected by a timing issue introduced in a\r\n    previous version. The fix (using a MEKA.NAM feature) is temporary until\r\n    a better one can be found.\r\n  - [Win] Added a simple first-run setup screen, to select soundcard,\r\n    sample rate and language. Additionally, you can show the setup screen\r\n    on startup by passing the -SETUP command line parameter to MEKA.\r\n  - Added \"cabinet_mode\" setting in MEKA.INP, to invert ESCAPE and F10 keys.\r\n    Arcade/emulation cabinet owners often have ESCAPE mapped to a key they\r\n    want to use to quit. This feature is a quick addition until full key\r\n    redefinition is supported.\r\n  - Added auto-repetition on keys F6/F8 (savestate selection).\r\n  - Added support for mouse wheel in file browser and documentation viewer.\r\n  - Fixed state saving crash that could happen when sound is completely\r\n    disabled and no FM emulator was selected.\r\n  - Started migrating from my own general purpose C library to standard\r\n    C library (LibC) for various functions.  This should provides speed\r\n    improvements in the initialization process.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n  - Various minor changes. Can you stop them all?\r\n\r\n\r\n MEKA 0.65\r\n ---------\r\n  - Rewrote palette system in the attempt of reducing palette changes\r\n    even more. As some people noticed, on some computer, the Windows\r\n    version had terrible slowdown and incorrect colors at some occasion\r\n    and especially in Game Gear games.\r\n    This is due to some DirectX video drivers which force waiting for\r\n    a screen refresh before each palette change. Problem is that some\r\n    drivers does that and some other do not. Palette changes in MEKA\r\n    are now better grouped so that the wait should not affect gameplay\r\n    in most cases.\r\n    Please report if you notice any palette related problem in this version.\r\n    Windows users, note that you can still get color flickering in some\r\n    video modes. But overally, things should be much better.\r\n  - Rewrote hardware sprite collision emulation for video modes 1, 2 and 3\r\n    (used by SG-1000/SC-3000/SF-7000/Coleco Vision software, mainly).\r\n    Sprite collision are now processed line per line, for a very accurate\r\n    result - at the cost of a slighty slower emulation. Although machines\r\n    using those video modes usually can't poll for the current line, some\r\n    software can manually do a similar job, making this precise value useful.\r\n    This fixes \"Froggy\" and \"Gold Miner\" (SF-7000), and maybe more.\r\n    Please report if you notice any collision related problem in this version.\r\n  - Fixed SMS/GG scanline counter to return accurate values.\r\n  - PAL/SECAM modes now have 313 lines instead of 312.\r\n  - Fixed \"Daffy Duck in Hollywood\" (SMS) which in some cases had\r\n    incorrect scrolling on the level score screen.\r\n  - Fixed palette switching in \"F-16 Fighter\" / \"F-16 Fighting Falcon\",\r\n    colors were incorrect during one single frame after the title screen.\r\n    This bug was introduced in a previous release.\r\n  - [Windows] Fixed screen capture (did crash with some DirectX drivers\r\n    in version 0.64c).\r\n  - Added Chinese flag in the file loader and associated the early dump\r\n    of Hokuto no Ken with it.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Fixed a few inconsistent entries.\r\n    Some particular renaming includes:\r\n      Chase H.Q.        --> Taito Chase H.Q.        (official name)\r\n      Story of Mio      --> Hoshi Wo Sagashite...   (official name)\r\n      Hokuto no Ken [B] --> Hokuto no Ken\r\n      Hokuto no Ken [A] --> Hokuto no Ken [China]\r\n  - Updated documentation.\r\n  - [UN*X] Released a quick & dirty GNU/Linux build, codenamed \"MEKANIX\".\r\n    It is not perfect and I do not plan to completely support it, but I hope\r\n    it can be useful to some people (some asked for it).\r\n    Please read MEKANIX.TXT if you want to use it.\r\n\r\n\r\n MEKA 0.64c\r\n ----------\r\n  - Fixed the bug that would sometimes shut down sound when resetting\r\n    or loading a savestate in full-screen mode.\r\n  - Fixed the bug that would not save battery backed memory when switching\r\n    the virtual machine Off (thanks Ian Hodgkinson for the precise report!).\r\n  - Fixed Light Phaser border limit when left column is blanked. In some\r\n    cases, the limit was enabled where it should not have.\r\n  - Light Phaser is now usable inside of the GUI, although this is obviously\r\n    not recommended since you can move the game window accidentally.\r\n  - Redumped and verified plenty more cartridges. Added and modified entries\r\n    to the checksum and compatibility lists, including new alternate dumps.\r\n    Some particular renaming includes:\r\n      James Bond 007: The Duel [B] --> James Bond 007: The Duel\r\n      James Bond 007: The Duel [A] --> James Bond 007: The Duel [Brasil]\r\n      Paperboy [B]                 --> Paperboy\r\n      Paperboy [A]                 --> Paperboy [USA]\r\n    Also modified compatibility list to be coherent with checksum list\r\n    regarding alternate version naming.\r\n  - MEKA now switch back to interface if fullscreen video mode cannot be set,\r\n    instead of quitting.\r\n  - Virtual machine picture positionning in the GUI now takes account of the\r\n    resolution (in GUI another resolution than default 640x480 is used).\r\n  - Updated history section of the documentation.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n  - [Windows] Fixed some of the screen corruptions when another application\r\n    is getting the focus or writing to the screen (untested).\r\n  - Added SG-1000 games to the multiplayer games list file (MULTI.TXT).\r\n  - Updated Danish translation (by Marc Klemp).\r\n  - Added CPU state dumping feature in debug mode.\r\n\r\n\r\n MEKA 0.64b\r\n ----------\r\n  - Added patches to be able to run SMS BIOS images (Alex Kidd in Miracle\r\n    World, Hang On / Safari Hunt, Sonic the Hedgehog...) as standard games.\r\n  - Fixed an amazingly stupid problem that's been around since years, which\r\n    was that Game Gear colors were considered as 9-bits instead of 12-bits.\r\n    Colors are now more precise, and you can notice a clear difference by\r\n    looking at the ground in FIFA International Soccer.\r\n    Thanks goes to Carleton Handley (the FIFA programmer on Game Gear) for\r\n    clearly pointing that out to me.\r\n  - Fixed VDP IE1 bit controls on Z80 IRQ Line.\r\n  - Fixed top of the screen in video mode 3, and optimized its refresh.\r\n    (used by Cabbage Patch Kids Picture Show and Smurf Paint & Play Workshop)\r\n  - Added Danish translation (by Marc Klemp).\r\n  - Patches write commands (in MEKA.PAT) now support multiple bytes in\r\n    a single line.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n  - Added \"Skydrop\" theme by Peter Deas (need to uncomment it in MEKA.THM).\r\n  - [Windows] Removed some unused bits in Allegro library and statically\r\n    linked it within the executable, reducing the ZIP file by 150 Kb!\r\n\r\n\r\n MEKA 0.64\r\n ---------\r\n Important changes were applied to the sound engine. As always, please\r\n contact me if notice something unusual, if you have any comment or doubt.\r\n\r\n PSG fixes that were applied in version 0.63 are apparently causing a bug\r\n to Out Run (SMS) running in FM mode. I searched but was unable to fix it\r\n as of yet. :(\r\n\r\n  - Cleaned and modified various part of the sound engine.\r\n    Please report if you notice anything unusual.\r\n  - [Windows] Disabled access to hardware YM-2413 emulation using OPL\r\n    under Windows 2000 and XP, avoiding crashes in certain cases... Well,\r\n    this time it should works :-)\r\n  - [Windows] FM Sound through OPL is now muted when switching to other\r\n    applications. PSG can not muted yet due to a technical constraint.\r\n  - Fixed muting of OPL on pause and quit (previously you were sometimes\r\n    able to hear very low hanging notes with a very high volume).\r\n  - Implemented software YM-2413 emulator by Mitsutaka Okazaki.\r\n    Although hardware YM-2413 emulation using OPL sounds cooler, this\r\n    emulator seems more faithful to the original chipset. It also works\r\n    on all systems, including Windows 2000 and XP. The downside is that\r\n    doing software synthesis takes a lot of time, and thus a fast computer\r\n    is recommended (at least 600 Mhz) to play MEKA with software YM-2413\r\n    emulation.\r\n  - Implemented a new software PSG emulator by Maxim (with modifications).\r\n    PSG emulation is pretty straightforward, but this emulator takes\r\n    account of several Maxim finds, such as the real sequence of pseudo\r\n    random numbers, as generated by the noise channel.\r\n  - Added refresh rate settings to GUI and Blitters. An advanced user\r\n    can now setup a video mode at 60 Hz with vsync enabled and auto frame\r\n    skipping disabled, for a smooth video refresh.\r\n  - Fixed PSG output that was previously too low and unsigned.\r\n  - [Windows] Attempted to fix some crashes subsequent to freeing a ROM.\r\n  - Added entries to the checksum and compatibility lists.\r\n  - Updated documentation.\r\n\r\n\r\n MEKA 0.63b\r\n ----------\r\n  - [Windows] Disabled access to hardware YM-2413 emulation using OPL\r\n    under Windows 2000 and XP, avoiding crashes in certain cases.\r\n  - Removed rare PSG debugging messages that were accidentally left.\r\n  - Fixed timing of the {LD,CP,IN,OT}[ID]R transfer/comparaison Z80 opcodes,\r\n    which were made too slow by 8 cycles in version 0.63.\r\n    \"The Castle\" (SG-1000) was affected.\r\n  - Fixed Sega Keyboard mapping for the \"Yen\" key on Japanese keyboard\r\n    (untested). Note that the mapping for certain specials keys seems not\r\n    to be right yet using the Windows version.\r\n  - Performed some minor calling optimizations.\r\n  - Updated Dutch, Deutsch, Italian, Spanish and Swedish translations\r\n    with missing messages. (Thanks to their respective mainteners!)\r\n\r\n\r\n MEKA 0.63\r\n ---------\r\n  - Implemented a cyclic color allocation algorythm, reducing palette\r\n    changes even more in some games. Users with videocard/drivers having\r\n    problems changing palette can expect less slowdown in Game Gear games.\r\n  - Tested every single Master System games, and wrote a multiplayer games\r\n    list out of them. It is included in the emulator (MULTI.TXT).\r\n  - Added 21 missing undocumented Z80 opcodes in the ED instruction set,\r\n    including the wonderful OUT (A), 0.\r\n  - Fixed PSG emulation. The holding note after text boxes shows in\r\n    \"Alex Kidd in Miracle World\" is no more, and noise channel writes were\r\n    fixed (as used by CodeMasters games: Micro Machines drums now sounds\r\n    correctly, etc...). Thanks to the great Maxim for his informations!\r\n  - Fixed Light Phaser shooting position for when left column blanking is\r\n    enabled (a bug leaked in since a few version).\r\n  - Fixed 64-bytes ROM footer detection.\r\n  - Fixed a bug affecting Hardware Reset and ROM reloading on SG-1000/SC-3000\r\n    and Colecovision emulation. As far as I know, only \"Pac-Man\" (Coleco)\r\n    was affected after an Hardware Reset, but other ROMs could as well.\r\n    Thanks to James Carter for the bug report.\r\n  - Fixed a two-years-old bug that may lead MEKA to crash when loading\r\n    a savestate that was previously used under the debugger.\r\n  - Fixed Sega Keyboard mapping for the unusual \"Pi\" / \"Ro\" key, so\r\n    Japanese users can use it at its standard mapping location.\r\n    Thanks to Yujiro for the bug report.\r\n  - FPS Counter is now enabled/disabled by pressing Alt+F, instead of\r\n    keeping F pressed.\r\n  - [Windows] Fixed time display.\r\n  - Updated to newer GCC version, hopefully little improving performances.\r\n  - Added and modified entries to the checksum and compatibility lists.\r\n    Some interesting ones I could rename after redumping:\r\n      Alex Kidd in Miracle World [A] --> Alex Kidd in Miracle World [Export]\r\n      Alex Kidd in Miracle World [B] --> Alex Kidd in Miracle World [USA]\r\n\r\n\r\n MEKA 0.62c\r\n ----------\r\n  - Various fixes.\r\n  - Added \"compatibility list\" and \"changes list\" items in the help menu,\r\n    allowing you to open them with the internal text viewer.\r\n  - Released Windows version.\r\n\r\n\r\n MEKA 0.62b\r\n ----------\r\n  - Sorry for the huge delay in such a minor update. I've tweaked the Z80\r\n    core a bit again to fix a little bug that I introduced myself and which\r\n    puzzled me for a while. I took the occasion also to upgrade to Marat's\r\n    latest debugger (now showing inline interrupt informations).\r\n  - Battery backed RAM is now scanned so unnecessary pages are not saved\r\n    in the .SAV file (this was previously already done, but only inside\r\n    of save states).\r\n  - Added new entries to the checksum and compatibility lists.\r\n  - Updated Spanish localisation.\r\n\r\n\r\n MEKA 0.62\r\n ---------\r\n Compatibility notes:\r\n  - Sonic Blast [GG] minor glitches on title screen in non Japanese mode\r\n    has been confirmed to appear on a real Game Gear, so the game is now\r\n    marked as perfectly working.\r\n  - Thanks to the new 93c46 EEPROM emulator, Game Gear perfect compatibility\r\n    has now increased to 98.09% (counting like FreezeSMS does, that gives us\r\n    a whooping 150.00% :)\r\n  - Statistics: as far as I know, out of the 7 Game Gear games marked as\r\n    NON-WORKING, 5 games requires a simulation of LCD blurry persistance to\r\n    show up without flickering, 1 may be severly broken (not possible to\r\n    complete the game), and 1 is minorly broken.\r\n\r\n As always, please report if you find out anything you feel as not emulated\r\n PERFECTLY: even a single suspicious pixel, etc.. Thank you!\r\n\r\n  - Rewrote 93c46 EEPROM emulation from stratch, it now works and saves\r\n    data properly. This fixes the following Game Gear games:\r\n      - Majors Pro Baseball\r\n      - Nomo's World Series Baseball (J)\r\n      - Pro Yakyuu GG League (J)\r\n      - World Series Baseball [A]\r\n      - World Series Baseball [B]\r\n      - World Series Baseball 95\r\n  - Emulated onboard 64 kb RAM chip of Ernie Els Golf (GG).\r\n  - For the sake of accuracy, started to implement emulation of the four\r\n    slighty different VDP chipsets used in Master System 1/2, Game Gear and\r\n    Megadrive (compatibility mode). They all have subtle differences, causing\r\n    some games not to work perfectly on all of them.\r\n  - Fixed glitches in Ys (Japanese version), using 315-5124 VDP emulation.\r\n  - Fixed bugs in Z80 emulation, letting the Game Over screen for Rambo III\r\n    to appears normally - and this required many many hours of work! (thanks\r\n    to Jonas Persson for reporting the bug). Also changed behavior of EI\r\n    instruction, fixing Double Dragon for Game Gear (again).\r\n  - Fixed VDP refresh disable emulation for Game Gear.\r\n  - Fixed YM-2413 state restoring when loading a save with FM playing.\r\n  - Now store YM-2413 state initialization in VGM files.\r\n  - If available, store Japanese game name (in romanji form) in VGM files.\r\n  - Fixed shifted instruction offset in debugger.\r\n  - Updated TECH.TXT with instructions about how to build a DB-9 adapter\r\n    to connect SMS Joypads on your PC.\r\n  - Added full French (by Overture 1928) and Swedish (by Henrik Sankala)\r\n    localisations. Complete Italian localisation (by Andra Ballandino).\r\n  - Fixed minor display bug in the Inputs configuration tool.\r\n\r\n\r\n MEKA 0.61\r\n ---------\r\n This version may or not have minor glitches on certain games (like, a single\r\n pixel or a single blinking row at the top or the bottom of the screen).\r\n Please DO report those glitches if you notice any. Thanks!\r\n\r\n  - Moved 104 messages to MEKA.MSG, allowing for full localization of\r\n    the menus. 99% of MEKA is now localizable. Updated the following\r\n    languages: English, German, Redneck, Dutch, Portuguese and Spanish.\r\n  - Improved Z80 core (timing and interrupt emulation bug).\r\n  - Fixed Rise of the Robots (GG), MEKA being the first emulator to play\r\n    it without glitches (and even without, it sucks! :)\r\n  - Fixed most or all (?) glitches in Formula 1 (SMS) two-players mode\r\n    (maybe not the right way yet).\r\n  - Fixed Double Dragon (GG) which was not working since an update of\r\n    the Z80 core (from fMSX) several version ago.\r\n  - Country changes now immediately takes effects (no need to reset).\r\n  - Tweaking interrupt emulation for SG-1000/SC-3000/SF-7000 and Coleco\r\n    Vision drivers. Those changes should not affect anything.\r\n  - Fixed 'Parallel' video blitter, odd frames were not updated when\r\n    using the blitter with software 3-D Glasses mode enabled.\r\n  - Fixed crash of SF-7000 driver when loading a corrupted floppy disk.\r\n  - Fixed YM-2413 logging in VGM files (Register & Value were reversed!)\r\n  - Updated SDSC Header support for version 1.01 (adding Author field).\r\n  - Added Golden Axe theme by Death Adder. (uncomment to use in GUI)\r\n  - Updated to Allegro WIP 3.9.39 and reapplied all custom patchs.\r\n    Changed SideWinder autodetection process a bit. Hope it works!\r\n  - Reduced executable.\r\n\r\n\r\n MEKA 0.60\r\n ---------\r\n  - Improving timing in Z80 core.\r\n  - Fixed voices that weren't ok (Alex Kidd: the Lost Stars..).\r\n    Voices in many many games were tested, finally marked them as 'Ok' in\r\n    the compatibility list.\r\n  - Due to timing improvments, now Space Harrier [50 Hz version] has correct\r\n    glitches (like on a real system) when running in NTSC mode. It is now\r\n    configured to automatically use PAL/SECAM by default.\r\n  - Removed the need of specific IPeriod setting for some Codemasters\r\n    games, meaning that they will now run even if you delete MEKA.NAM.\r\n  - Added sample accurate VGM logging, allowing to log voices. The option\r\n    was previously grayed, it is activated now that all voices are Ok.\r\n  - Updated to VGM version 1.01, to include original TV type information\r\n    (NTSC or PAL/SECAM) in the file, allowing to play at a different rate.\r\n  - Fixed minor sprite masking bug affecting scrolling games in certain\r\n    conditions. Evander Holyfield Boxing (Game Gear) was affected.\r\n  - Added support for Coleco Vision header/footer in order to load the\r\n    newly released \"Pac Man\" and \"Dig Dug\" ROMs from CGE 2001.\r\n  - Fixed a minor bug when loading an in-game savestate from the BIOS.\r\n  - Fixed file loader sorting so that if present, \"..\" is always on top.\r\n  - Added/fixed entrys to the checksum and compatibility lists.\r\n  - Added two Sonic themes by H Hog. (uncomment to use in GUI)\r\n\r\n\r\n MEKA 0.59b\r\n ----------\r\n  - Fixed vertical scanline counter emulation.\r\n  - Fixed a minor hardware collision bug introduced in version 0.59.\r\n  - Fixed usage of '%' in ROM comment field.\r\n  - Changed message logging (with /LOG) to avoid cutting text in the file\r\n    when it doesn't fit on the GUI message box.\r\n\r\n\r\n MEKA 0.59\r\n ---------\r\n  - Various changes to the sound engine:\r\n     - Fixed PSG Periodic Noise emulation (bass in some Marble Madness tunes,\r\n       Daffy Duck in Hollywood, and few other games). Thanks Ziria and Maxim!\r\n     - Added PAL/SECAM machines accurate base clock for PSG wave generation\r\n       (pitch is around 1% off from NTSC machines).\r\n     - Added VGM logging. VGM (for Video Game Music) is a new file format\r\n       recently developed on S8-Dev with collaboration of Dave, Maxim and\r\n       some other people. Maxim has wrote a WinAMP plugin already.\r\n       Check out the newly created Music Section on SMS Power at\r\n       http://www.smspower.org/music !\r\n     - Added PSG registers to the technical information window.\r\n  - Fixed a very weird bug introduced in version 0.58, where a certain sprite\r\n    configuration and positionning could screws up the whole emulator! This\r\n    caused problems in Terminator 2: The Judgment Day and Ghouls'n Ghosts.\r\n  - Added Korean mapper (9) emulation, as used by Dodgeball King.\r\n  - Added Italian messages translations (by Andrea Ballandino).\r\n  - Added German messages translations (by Tilman Hesse).\r\n  - Fixed some PortuguE messages.\r\n  - Fixed/added accentued characters in some Brazilian game names.\r\n  - Added new \"Mario Must Die\" theme, with a nice handdrawn picture :-)\r\n  - Added new entrys to the checksum and compatibility lists.\r\n  - Fixed and improved various minor things.\r\n\r\n\r\n MEKA 0.58c\r\n ----------\r\n  - Fixed the missing soundcard selection menu in some cases.\r\n  - Added printing of SDSC Header informations when found. The SDSC Header\r\n    has been defined and created by the SMS Power developement team (based\r\n    on Eric Quinn's idea) for homebrewn programs.\r\n  - Drawn Latin-Extended characters (Unicode 0080-00FF) in the big font.\r\n    Accents are now usable everywhere in MEKA. Be sure to use accents from\r\n    the Latin-Extended table (usually used by Windows programs, not DOS ones).\r\n  - Added Spanish messages translations (by Antonio J. Bazalo).\r\n  - Added PortuguE messages translations (by Rodrigo C. Rubio).\r\n  - Added \"WIP\" (Work In Progress) parameter in language definition, to\r\n    disable warnings and informations when the language is uncomplete.\r\n  - Squashed one very minor flag bug in the browser when a ROM had an\r\n    number after a space, at the end of its filename.\r\n\r\n\r\n MEKA 0.58b\r\n ----------\r\n  - Fixed various minor bugs.\r\n  - Fixed two scrolling emulation bugs in video mode 5. They did not\r\n    affect any game, but for the sake of accuracy, better fixing them!\r\n  - Added Dutch messages translations (by Mark van Tilburg) and Redneck\r\n    messages translations (by Maxim, using Dialectizer). Fry mah hide!\r\n  - Added /LOAD command line parameter, to start directly with a savestate\r\n    loaded (so you can make yourself batchfile loading a certain state.)\r\n  - Added several new entrys to the checksum and compatibility lists, and\r\n    fixed some existing ones. Added an USA flag and set the flag to all\r\n    SMS games only released in USA (Alf, King's Quest, Montezuma's Revenge).\r\n  - Added one new happy theme from the french movie \"Am‚lie Poulain\".\r\n\r\n\r\n MEKA 0.58\r\n ---------\r\n Again, please report if you notice any bug/glitche with any game, that is\r\n not mentionned in the compatibility list. The VDP fix applied in this\r\n version is also a massive compatibility test, and I would like to know\r\n if it has any unexpected behavior on other games. So play, play, play! :)\r\n\r\n  - Added PSG sound logging to WAV files, accessible from the Sound menu.\r\n  - Rewrote messaging system, added localization support.\r\n    Moved all messages to an external file, MEKA.MSG. You can now change\r\n    80% of the texts used in MEKA, and translate it to the language of your\r\n    choice. I am however NOT YET sure about how accents will work, since it\r\n    depends on the font used.\r\n    This feature required a pass on all existing code and so took plenty\r\n    of time to do (10+ hours), I might have screwed a few messages during\r\n    the change, so be sure to send me an e-mail if you notice anything\r\n    unusual.\r\n  - Implemented a VDP quirk found in Master System 2 but not Master System 1\r\n    or Game Gear, discovered by Charles Mac Donald (thanks Charles!). This\r\n    one fixes Cosmic Spacehead *BUT* might screws up few other games. I did\r\n    a bit of testing but couldn't do them all again, so please report if you\r\n    notice anything unusual with another game.\r\n  - Improved hardware sprite collision accuracy, fixed a bug in some\r\n    cases where it was previously framerate dependant, and rewrote the\r\n    whole code in assembly.\r\n  - Changed initializations messages and some other messages.\r\n  - Fixed an incorrect numbers of TV lines in PAL/SECAM TV emulation (due\r\n    to a typo - thanks goes to cgfm2 for pointing me this stupid error!),\r\n    allowing removal of a few custom MEKA.NAM parameters (Daffy Duck in\r\n    Hollywood..).\r\n  - Fixed the annoying bug that caused crashes on startup under DOS when\r\n    sound was enabled.\r\n  - Fixed a minor bug in Codemaster mapper emulation, that affected the\r\n    checksum check of 'Drop Zone' (although the game worked).\r\n  - Fixed crash when using a patch defined in MEKA.PAT that write outside\r\n    of any existing data.\r\n  - Added (very) quick and (very) dirty frame-per-frame advance by pressing\r\n    ALT-F12. In fact, it will unpause the game then pause it back next frame.\r\n  - Updated Colecovision compatibility list and added some product IDs,\r\n    thanks to Tincho DJ.\r\n    The current state with Colecovision games is: a mess :(\r\n    Someone will lots of Colecovision knowledge would be very helpful\r\n    to help sorting out all bad dumps, testing games and redumping others.\r\n\r\n\r\n MEKA 0.57b\r\n ----------\r\n\r\n Lots of fixes, for a total of twenty working hours.\r\n Please also note in documentation that *I HAVE MOVED HOUSE*, that is\r\n in case you planned to send something.\r\n\r\n  - Various minor fixes and improvements.\r\n  - Fixed startup delay (and sometimes crash) when autodetecting Sidewinders.\r\n  - Fixed and improved the new dynamic palette handler, avoiding palettes\r\n    overflow on some Game Gear games such as Sonic & Tails 2 / Triple Trouble,\r\n    Sonic 1 or Deep Duck Trouble. The fourth level of Sonic 1 is however\r\n    not yet perfect when both air and water are shown on screen.\r\n    Thanks to ICEknight for pointing the bug out.\r\n  - Made various clean and corrections to the main sound engine structure.\r\n    It should not have broken anything, but please report if you notice\r\n    something unusual. Noticable changes are that:\r\n     - MEKA refuse to start if sound initialization has failed.\r\n     - Sound is now muted while certain long operations are being processed.\r\n     - Sound card type is not lost if you only disable sound.\r\n     - An incorrect BLASTER environnement variable is now reported.\r\n  - Added an algorithm to automatically detect certain mappers and select\r\n    them when the ROM is unknown.\r\n  - Fixed vertical scrolling emulation in certain special cases.\r\n  - Fixed zoomed sprites in SMS/GG video mode. They were accidentally\r\n    screwed up by a typo (!) in previous version, and affected Virtua\r\n    Fighter Mini.\r\n  - Fixed a bug with checksum handling. In some cases, ROMs with only a\r\n    few different bytes were previously not recognized as different.\r\n  - Fixed usage of the ';' key in the input system (now usable), previously\r\n    the character was considered as beginning a comment in MEKA.INP.\r\n  - Fullscreen messages are now correctly displayed when the current emulated\r\n    system uses a resolution higher than your fullscreen resolution.\r\n  - Fixed debugger breakpoint when loading a save state.\r\n  - Added some new entrys to the checksum and compatibility lists,\r\n    and fixed few existing ones. Added a french flag, currently used\r\n    for games translated in french.\r\n\r\n\r\n MEKA 0.57\r\n ---------\r\n Note: I made lots of little sources changes in this version. Things have\r\n been tested, but in case you notice anything unusual, please contact me.\r\n\r\n  - Rewrote dynamic palette handler, minimizing actual hardware palette\r\n    changes, reducing snow and generally reducing flickering when games\r\n    were abusing of palette changes (like the \"Happy Birthday\" demo, or\r\n    some Game Gear games). Due to that change, Palette and Tile viewers\r\n    are now slighty slower than before, but since they are not used for\r\n    playing, it is fine.\r\n  - Rewrote hardware sprites collision emulation a more accurate way,\r\n    fixing Cheese Catastrophe (SMS) bonus catching. There was an easy\r\n    way to get it to work, but technically speaking, it was not the\r\n    right one. Instead I emulated the feature a better way so that\r\n    theorically, any tricky uses of it should be working. Speed might\r\n    have dropped of about 1 FPS on slow computers.\r\n    (Thanks to nop.nop for the bug report.)\r\n  - Added data dumping facilities for developers and hackers.\r\n    You can now dump the following to a file:\r\n      - RAM (raw or text hex/ascii)\r\n      - VRAM (raw or text hex/ascii)\r\n      - Palette (raw or text colors definitions)\r\n      - Sprites (raw or text sprites definition)\r\n      - VDP Regs (raw or text binary/hex)\r\n      - OnBoard Memory (raw or text hew/ascii)\r\n    Those functionnalities are available by starting MEKA with /DEBUG.\r\n  - Added Sega Keyboard (SK-1100) hardware detection emulation. You can\r\n    know use the emulated keyboard to play SG-1000 (and early SMS) games\r\n    supporting it.\r\n  - Added a 'none' value for joypad driver, to disable any kind of\r\n    detection (as it may be slow on some computers). See MEKA.INP.\r\n  - Battery backed RAM optional pages are now not saved when their\r\n    content is null.\r\n  - Optimized the technical information viewer that was previously\r\n    too slow. Also made cosmetic changes to the informations shown.\r\n  - Fixed error message that said MEKA was unable to write SaveRAM\r\n    to write, while it did correctly.\r\n  - Fixed savestate loading bug in some very specific cases when using\r\n    a custom mapper.\r\n  - Fixed sprite drawing in overscan video mode.\r\n  - The selected tile in the tile viewer is now refreshed if modified.\r\n  - Fixed PSG volume bug, where volumes 14 and 15 were actually the same.\r\n    (thanks to Martin Konrad for noticing it)\r\n  - Changed the 'palette_bright' option to a 'palette' option that can\r\n    be either 'muted' or 'bright', the later being now the default, since\r\n    many people suggested that it was better than the old default one.\r\n    Also added a switch in the GUI options box to change it dynamically.\r\n  - VSync is now automatically avoided if a speed faster than 70 hz is\r\n    being used. So you can use a blitter with VSync enabled and still\r\n    profit of accelerations if you want them sometimes (skip intros, etc..).\r\n  - Partially rewrote popup menu code. Also hacked a bit to fixed the bug\r\n    when more than 32 themes were enabled on the same time.\r\n  - Added the usual amount of new themes and new database entries.\r\n  - Added some new comments to the configuration file.\r\n  - Converted all ASM code to NASM format, for better portability.\r\n  - Ported MEKA to Windows. Cool.\r\n\r\n\r\n MEKA 0.56\r\n ---------\r\n  - Added Sega Super Control Station emulation, codename SF-7000.\r\n    The SF-7000 is a rare addon for the Sega Computer 3000, providing it\r\n    with a 3\" Floppy Disk Drive, 64 kbytes of RAM, a parallel printer port\r\n    and a RS-232C port. The later two are only partially emulated as anyway\r\n    there is no way to use the emulated connection (ex: for printing) yet.\r\n    Many thanks goes to Marc Le Douarain for his help and dumps of his old\r\n    disks, and Ulrich Cordes for the FDC-765 emulation (see documentation).\r\n\r\n    I added in the documentation a paragraph about how to use SC-3000 and\r\n    SF-7000 Basic software, as it is needed to load programs for the later.\r\n    Also, I am still looking for a real SF-7000 and any softwares!\r\n\r\n  - Added sprite flickering emulation in video mode 5 (SMS/GG), and\r\n    interfaced so you can now enable it if you feel like playing shooters\r\n    with invisible bullets. It is available in the VIDEO->FLICKERING menu.\r\n  - MEKA is now ignoring those rarely present 64 bytes footers.\r\n  - Fixed Ninja Gaiden (GG version) hand on intermission animation.\r\n  - Fixed PAUSE button which was broken in version 0.55b.\r\n  - Fixed blinking sides when a program was using text mode (Sega Basic, ..)\r\n    with a border color different than black.\r\n  - Fixed Sega Keyboard letters color.\r\n  - Fixed /LOG command line option which was ignoring the given filename.\r\n  - Added and fixed entrys in the compatibility and checksum lists.\r\n  - Various minor changes - changed messages, fixed typos..\r\n\r\n\r\n MEKA 0.55b\r\n ----------\r\n  - Added configurable mouse speed values in the MEKA.INP file.\r\n  - Fixed mouse under Windows NT / Windows 2000.\r\n\r\n\r\n MEKA 0.55\r\n ---------\r\n  - Added builtin documentation, accessible from the \"HELP\" menu.\r\n  - Entirely revamped the input system. I originally fixed Paddle Control\r\n    emulation then noticed the problem I was having with Super Racing was\r\n    due to a bug in the original game. I did not feel like adding a cheap\r\n    hack and beside it was time to clean it up, I just needed a reason :)\r\n    Inputs related changes you will notice are:\r\n\r\n      - Added configuration tool, showing small pictures of peripherals\r\n        being used (hope you like the pictures, as I spent a long time\r\n        drawing them). This tool allows you to see currently available inputs\r\n        sources, enable/disable them, and change their key/buttons mapping.\r\n        No more dealing with obscure scancodes numbers (finally).\r\n        To keep going with the MEKA tradition, every configuration bit is\r\n        stored in a human-readable and manually editable file: MEKA.INP.\r\n        You can access most of the functionnalities from under the interface\r\n        but experienced users might want to check this file out. The new\r\n        input system is high-level oriented and allows you to do many nice\r\n        things like playing with two pads on the same time or mapping pause\r\n        to a mouse button. Whatever you feel.\r\n      - Any joypad/joystick corresponding to the driver selected in MEKA.INP\r\n        should be automatically enabled on starting, and available for use.\r\n      - Renamed left occurences of peripherals that were incorrectly named\r\n        (Paddle Controller -> Paddle Control, Light Gun -> Light Phaser)\r\n      - Improved Paddle Control emulation so that they will work in Japanese\r\n        mode, and allowing Super Racing to detect a paddle when plugged on,\r\n        instead of the regular joypad.\r\n      - Fixed a precision bug in Paddle Control 2 emulation.\r\n      - Added support for a second Sport Pad / Trackball.\r\n      - Added digital input source emulation with the mouse, so basically\r\n        you can play any joypad game with a mouse now. Expect being really\r\n        frustrated with most games, but it is actually very cool for shooters\r\n        and games where you do not have to do 'long' movements. Try R-Type.\r\n\r\n  - Added 3-D Glasses emulation, with both software and hardware modes:\r\n      - Software mode let you play 3-D games by showing only\r\n        images of a choosen side (left or right).\r\n      - Hardware mode supports REAL Sega 3-D Glasses connected on\r\n        your PC through the communication port! See TECH.TXT for more\r\n        informations about how to build a Sega 3-D Glasses adapter\r\n        and enjoy a new dimension of videogaming :-)\r\n        Warning: 3-D Glasses support through the COM port is still not\r\n        in perfect stage, meaning that you may experience flickering.\r\n        A blitter with VSync enabled is *strongly* recommended.\r\n        Also stop playing every 30 minutes eyes you'll become blind :)\r\n\r\n  - Tweaked VDP code for potentially more accurate side effect emulation.\r\n  - Fixed sprite collisions in certain cases. The following Colecovision\r\n    games are now perfectly playable:\r\n      - Carnival (Bonus Level is ok)\r\n      - Jumpman Junior (Ladders on level 3 are ok).\r\n      - Pitfall 2 (No false hit on the third screen).\r\n      - Venture.\r\n    Thanks goes to the one who sent me a long e-mail about collision\r\n    detection some months ago, but which I unfortunately lost and was\r\n    then unable to answer. E-mail me if you are still around :)\r\n  - Fixed hard pausing. You can now safely take screenshots after pausing\r\n    with a message shown on the screen, as it will not be shown in the shot.\r\n  - Fixed loading of very small ROMs, which affected Tic Tac Toe on\r\n    Colecovision, and maybe your very own demos programs.\r\n  - Implemented Antiriad's hack to Allegro - used in Raine - to permit\r\n    usage of Sidewinders while their driver is loaded (not tested). Thanks!\r\n  - Fixed the Eagle blitter which was not centered and showed garbage\r\n    in some machines. Also fixed the default Eagle blitter configuration\r\n    which limited speed to 30 FPS even on a very fast system. What a loss!\r\n    By the way, Eagle does in fact looks nice with a few games. Try R-Type.\r\n  - Slighty optimized memory accesses and tile refresh.\r\n  - Changed the key to save screenshots from F12 to PrintScreen. If you\r\n    are using Windows, be sure to configure the properties of your DOS box\r\n    to enable the use of the PrintScreen key if you want to make screenshots.\r\n  - Added F12 shortcut to hard pause emulation.\r\n  - Added access to enabling/disable GUI Vertical Sync in the options box.\r\n  - Fixed a bug that prevented Battery Backed RAM or EEPROM to be saved when\r\n    freeing ROM.\r\n  - Added a technical document (TECH.TXT) with basis informations about\r\n    the systems, as well as the schematic for the 3-D Glasses adapter.\r\n  - Reduced default FM writing delay, that should speed up the two games\r\n    over-abusing of FM writes. Try R-Type title screen.\r\n  - Added various name and checksum entries, and corrected many existing ones.\r\n    Should have noted out all Game Gear games running in Master System mode,\r\n    fixed some Colecovision names and date, and generally improved accuracy.\r\n    Thanks goes to Maxim and Luke2 for their precious help! :)\r\n  - Added Korean flag in the file loader and associated Super Tetris with it.\r\n    There are still several Korean games to dump, however.\r\n  - Fixed leap year calculation (for display of dates).\r\n  - Fixed a crashing bug when passing too many parameters on command line.\r\n  - Added the usual bunch of new GUI themes, and more pictures are available\r\n    from the homepage.\r\n  - Plenty of minor fixes here and here.\r\n\r\n\r\n MEKA 0.54b\r\n ----------\r\n  - Made some very minor fixes.\r\n  - Added two new themes (Deep Purple and Deep Brown).\r\n\r\n\r\n MEKA 0.54\r\n ---------\r\n  - Updated to the documentation, improved many parts and added new things.\r\n    Please read it!\r\n  - Fixed invalid vertical sprite wrapping in video mode 2 (bug introduced\r\n    in version 0.51, slighty affecting The Castle and maybe other games).\r\n  - Added PSG wave synthesis sound rate setting in the configuration file.\r\n    Rate is no more fixed to a weird value like in all previous versions,\r\n    avoiding the clicks and noise with certains soundcards. You can also\r\n    change the rate to the default values of 11025, 22050 and 44100 Hz from\r\n    the GUI pop-up menus.\r\n  - Added separate PSG channel enabling/disabling. Mainly useful for\r\n    musicians who want to listen to different channels separately, but\r\n    it is also very fun to disable some channels and play games with\r\n    somewhat new musics :)\r\n  - Fixed FM bug when hard pausing and unpausing in some games.\r\n  - Addams Family, Operation Wolf and Sonic Blast now automatically run in\r\n    PAL/Secam mode when NTSC is selected, due to the games having bugs in\r\n    NTSC mode.\r\n  - Fixed the badly positionned line of Hang On in Hang On / Safari Hunt.\r\n  - If brutally forced to close (like when switching to a blitter using an\r\n    invalid resolution), MEKA now switch back to its starting directory.\r\n  - Added screenshot filename template to the configuration file. You can\r\n    now configure weither you want padding, short or long filenames, etc..\r\n    Also changed screenshot numbering starting value from 0 to 1.\r\n  - Added \"integer stretched\" display of the themes background pictures\r\n    (see MEKA.THM).\r\n  - Added new themes, some of them using nice background pictures you are\r\n    invited to download at http://www.smspower.org/meka/themes.\r\n\r\n\r\n MEKA 0.53c\r\n ----------\r\n Game Gear compatibility rate is now of 95.80%. It is the only unperfect\r\n system and that's mainly due to the lack of LCD screen persistence of\r\n vision emulation.\r\n\r\n  - Kishin Douji Zenki very minor graphic bug was a bug in the game itself,\r\n    not in MEKA. Thanks goes to Adol brothers for their help on this one.\r\n  - Added a patch to fix a bug in Walter Payton Football (in the game itself)\r\n    preventing it to works on machines with a FM Chipset.\r\n  - Fixed Wanted patch, I had accidentally commented a line out.\r\n  - Fixed California Games 2 minor graphic bug when selecting the top left\r\n    entry of the menu (screwed in version 0.52). Thanks Pieter!\r\n  - Added new entries to checksum and compatibility list.\r\n\r\n\r\n MEKA 0.53b\r\n ----------\r\n I finally figured out what was the problem of the major slow down in\r\n some video modes when page flipping was enabled. Actually using page\r\n flipping need to force vertical synchronisation in most video modes, so\r\n enabling them both will make the program synchronise twice per frame to\r\n the vertical refresh, causing speed to be limited to about 30/35 FPS.\r\n The default blitter definition files now have Page Flipping modes enabled\r\n by mode, replacing the obsolote VSync modes.\r\n\r\n  - Fixed a bug preventing files to appear in the file browser under DOS.\r\n  - Added all known Colecovision dumps to the checksum/names list.\r\n    Names are based on Cowering's GoodColeco utility.\r\n  - Game name is now dynamically updated under the GUI is a country change\r\n    affect the current name.\r\n  - Fixed \"Rise of the Robots\" by forcing NTSC mode when it is not enabled.\r\n  - Added a patch to fix a bug in Wanted (in the game itself) preventing it\r\n    to works on machines with a FM Chipset.\r\n  - Fixed a bug sometimes happening where disabling background layer\r\n    display wouldn't work.\r\n  - Added 5 new themes (commented by default).\r\n\r\n\r\n MEKA 0.53\r\n ---------\r\n Master System compatibility rate has now reached the perfect 100.00%\r\n assuming out of the 373 tested ROMs none was broken in a recent version.\r\n Something major have changed in this version and which might screw just\r\n about any game. So if you find anything unusual that might be a bug,\r\n please report it to me. As soon as possible I'll spend a week trying\r\n all games again.\r\n\r\n Enabling page flipping is known to cut down the speed by a factor of two.\r\n This is obviously a bug as page flipping should not affect performances\r\n so at the moment I suggest avoiding it and enabling VSync instead.\r\n\r\n As a side news, I have ported MEKA to FreeBSD/NetBSD. It probably compiles\r\n under Linux also, and whenever I can get my hands on a computer running\r\n Windows applications at a correct speed, a Windows port will be worked on.\r\n\r\n  - Fixed temporary sound bug when loading savestates in certains cases.\r\n  - Added TV Type switch to change between NTSC and PAL/SECAM.\r\n  - Improved tile viewer so that a click on a tile shows its number and\r\n    the tile itself. Might be useful for developers and ROM hackers.\r\n  - Improved file browser: added a \"Reload Directory\" button and a\r\n    \"Load Names\" button to load full game names for all files.\r\n  - Fixed Y's (SMS/J).\r\n  - Added full TV Oekaki Graphic Board and Pen emulation, using mouse.\r\n    Button 1 simulate a pen press and button 2 simulates the pen being away\r\n    of the graphic board - when it is away you can use standard inputs. Now\r\n    you will be able to draw with the emulator ^_^\r\n    Thanks to Toshi for sending out the Graphic Board.\r\n  - Fixed GP Rider (GG) road corruption.\r\n  - Fixed NBA Action (GG) abnormal flickering.\r\n  - Fixed NBA Jam TE (GG, previously unknown bug) and Surfs Ninja (GG).\r\n  - Fixed reset key in Sega Keyboard emulation.\r\n  - Fixed Gear Game communication port emulation somewhat broken in\r\n    previous version and which affected Pac Attack.\r\n  - Fixed secret games left side of the screen bug in fullscreen mode.\r\n  - Improved auto frame skipper synchronization to the choosen speed.\r\n  - Compiled with the newest patched Seal Audio Library, improving overall\r\n    sound quality (16-bit mode was somewhat useless in previous versions),\r\n    and ALLOWING SOUND TO WORK ON SOUND BLASTER 128 SOUND CARDS, finally.\r\n    A big thanks goes to whoever patched Seal for that.\r\n    (I guess it is someone to the MAME team, but I am not sure.)\r\n  - File browser now go in the root of drive if current directory is invalid.\r\n  - Removed a broken line in the MEKA.NAM file causing Back to the Future 3\r\n    to show a black screen.\r\n  - Added even more new entries in the compatibility and checksum lists.\r\n  - Lot of sources changes and improvments.\r\n\r\n\r\n MEKA 0.52\r\n ---------\r\n Compatibility rates as of version 0.52:\r\n\r\n  Master System: 99.72%\r\n    (not perfect because of the Japanese version of Ys).\r\n  Sega Game 1000: 100.00%\r\n  Sega Computer 3000: 100.00%\r\n    (excluding emulation of optional peripherals such as the Sega Printer)\r\n  Game Gear: 95.03%\r\n    (excluding gear-to-gear emulation used by certains two players games)\r\n\r\n  - Fixed the minor glitches in:\r\n   - Back to the Future 2\r\n     (black section flickering between the road and status bar)\r\n   - Gangster Town\r\n     (little line of skyblue pixels on the top of the car in the first scene)\r\n   - Operation Wolf\r\n     (minor graphic glitches on the top of the bottom bar when shooting)\r\n\r\n Tested Wonderboy in Monsterworld on a real system and confirmed the minor\r\n glitch when the menu is vertically scrolling is a bug in the game itself.\r\n\r\n Did some research about Ys (J/FM), with help from Toshi.\r\n It is not considered anymore as a bad dump. The bug happening in MEKA also\r\n happens when using a real Game Gear or a Megadrive with an adapter.\r\n However the game show a perfect status bar on a Japanese Master System,\r\n so the bad behavior is considered as a bug of MEKA, even if in the first\r\n place it is due to a bug in the game code taking advantage of an odd\r\n behavior of the Japanese Master System.\r\n\r\n Also:\r\n  - Improved run-time TMS9918 video mode detection.\r\n  - Fixed Hyper Pro Yakyuu 92 (GG).\r\n  - Reduced flickers in NBA Action (GG).\r\n  - Fixed freezing until a key is pressed when loading the Japanese BIOS.\r\n  - Fixed yet another silly bug introduced in previous version and screwing\r\n    some SC-3000 software such as the Sega Basic.\r\n  - Added new entries to compatibility and checksum lists. Also redone\r\n    SC-3000 list with names corrections for Japanese educational softwares.\r\n  - Fixed potential VDP bug - wasn't affecting any games, but could have.\r\n  - Implemented MAME Z80 CPU Core but did not enabled it in the public\r\n    version as it doesnt bring anything better than Marat's core: they\r\n    are on par, but MAME license is quite limiting.\r\n  - Improved documentation inside of the MEKA.BLT file.\r\n  - Fixed a bunch of minor bugs. Fixed handing of ROM smaller than eight\r\n    kilobytes. Fixed empty entry creation in the VFN database. Fixed a bug\r\n    in windows repositionning when changing resolution.\r\n  - Reduced executable size.\r\n\r\n And also:\r\n  - Added background picture caching for a faster switch to the GUI when\r\n    a big image is used on background.\r\n  - Added a bunch of new themes into the distribution package.\r\n    Background pictures for some of the themes are available on a new\r\n    site at http://www.emucamp.com/meka/themes\r\n  - As of now the PICS/ directory should be considered as the one everyone\r\n    have to use to share themes easily. You can still have your own themes\r\n    pictures stored anyway, anyway.\r\n\r\n\r\n MEKA 0.51 - OverClocked Edition\r\n -------------------------------\r\n SG-1000 perfect compatibility rate is now of 100%\r\n\r\n  - Added the possibility of adding a custom background picture in themes.\r\n    Keyword to be used in MEKA.THM is \"background_pic\". Pictures need to\r\n    be in PCX format and a maximum of 128 colors will be used. You can\r\n    zoom, tile or center the picture using the appropriate keywords.\r\n  - Added desktop saving. Active windows and their position are now saved\r\n    and restored back when loading MEKA.\r\n  - Rewrote sprite engine for video modes 1/2/3, fixing the minor bug in\r\n    Pitfall 2 (SG-1000) and Rockn'Bolt (SG-1000). Probably also fixed some\r\n    Colecovision games. Added optional flickering emulation.\r\n\r\n\r\n MEKA 0.50\r\n ---------\r\n Master System perfect compatibility rate is now of 98.90%\r\n Games still causing problems are:\r\n   Back to the Future 2\r\n     (black section flickering between the road and status bar)\r\n   Gangster Town\r\n     (little line of skyblue pixels on the top of the car in the first scene)\r\n   Operation Wolf\r\n     (minor graphic glitches on the top of the bottom bar when shooting)\r\n   Wonderboy in Monsterworld\r\n     (minor glitche on the menu vertical scrolling line when pressing pause)\r\n Found out that the bug in Aerial Assault was happening on a real system.\r\n So it's not considered as a bug anymore.\r\n\r\n Next step will be to improve Game Gear perfect compatibility rate (94% now).\r\n\r\n First, reparing bugs introduced in MEKA 0.40:\r\n  - Fixed accidentally left bug in SG-1000 interrupt emulation, fixing\r\n    Championship Lode Runner and probably other games.\r\n  - Fixed accidentally left minor scrolling bug in a few games (Castle of\r\n    Illusion to name one. I forgot about the others).\r\n\r\n New stuff being:\r\n  - Rewrote Light Phaser emulation. The following games are now playable:\r\n      - Laser Ghost (Light Phaser is optional)\r\n      - Missile Defense 3D\r\n      - Operation Wolf\r\n      - Shooting Gallery\r\n      - Wanted\r\n  - Improved various bit of emulation to fix the following games:\r\n      - Robocop 3 (SMS): does not crash anymore when pausing.\r\n      - Back to the Future 3 (SMS): have minor title screen bug fixed.\r\n      - Sonic Drift 2 (GG): bottom of screen is correct now.\r\n      - Out Run (GG): music now plays.\r\n  - Added Game Gear vertical scrolling lock emulation (fixing Fray).\r\n  - Added wide effective area emulation (2 Star Trek games on Game Gear).\r\n  - Implemented better systems hardware differences to allow detection.\r\n    Renaming Pit Pot (SMS) to the .SG extension and running it will\r\n    now show a custom error screen! Thanks goes to Yujiro to the notice.\r\n  - Slighty optimized Master System and Game Gear screen refresh.\r\n  - Rewrote blitters handling system:\r\n      - Added blitters definition file (MEKA.BLT) where you can configure\r\n        fullscreen video modes drivers, resolution and effects, and create\r\n        your own video modes this way.\r\n      - Added \"TV Mode\" blitter that simulate accurates TV scanlines.\r\n      - Added \"Double\" blitter. Nice uses of it are:\r\n          - Doubling screen with 512x384 mode (getting true Fullscreen).\r\n          - Doubling screen in a tweaked mode (Game Gear with big pixels).\r\n            If you find any suitable mode for Game Gear other than the ones\r\n            listed in the MEKA.BLT file, please tell me about it.\r\n      - Added \"Page Flipping\" option to blitter (reducing flickers)\r\n      - Included \"Perfect\" blitter definition with all best features enabled\r\n        (512x384 resolution, TV Mode, Doubled Fullscreen, Page Flipping and\r\n        Vertical Synchronisation) for people with *very* fast computer.\r\n      - Removed hotkeys to enable/disable the Scanlines, Eagle and Parallel\r\n        effects. They are now part of blitters configuration. The current\r\n        blitter can be changed by pressing F1.\r\n  - Rewrote frameskip handling system and added speed throttling.\r\n      - F2 key now switch between standard and automatic frameskipping.\r\n      - F3 decrease speed in automatic mode, else decrease frameskip.\r\n      - F4 increase speed in automatic mode, else increase frameskip.\r\n  - Added icons package from various contributors (see ICONS.ZIP).\r\n  - Added Massage savegame converter. Rename a .MSD file in the MEKA\r\n    naming convention and it will be automatically converted when loading.\r\n    You might in some cases experience sound or various other problems\r\n    with certain games. The usual solution is to pause and unpause the\r\n    game, else try to change screen/level.\r\n  - Slighty improved voice emulation.\r\n  - Rewrote drivers handling system. It is easier to maintain internally now.\r\n  - Color related stuff:\r\n      - Fixed potentiel palette problems with some video card/mode couples.\r\n      - Revamped whole palette update handling (reducing snow).\r\n      - Palette viewer now show no more than the correct number of colors\r\n        in SG-1000/SC-3000/Coleco mode.\r\n  - Fixed configuration file problem when using PSX and N64 joypads.\r\n  - Added new games and product numbers to compatibility and checksum lists.\r\n  - Added mouse button 2 shortcut to switch between the two Light Phasers.\r\n  - Added some new GUI themes - uncomment in MEKA.THM file to use them.\r\n  - Fixed file browser bug when overwriting recognized ROMs with unknown\r\n    ones would keep the old, recognized name showing.\r\n  - Fullscreen captures now ignore status message and filters/effects.\r\n  - Made some structural optimisations, increasing speed of a few percents.\r\n  - Fixed bug virtual longfile name self created list saving.\r\n  - Fixed a screenshot naming bug with short ROM names.\r\n  - Fixed rare crashing bug with the blood cursor GUI effect.\r\n  - Sega Basic Level 3 Version 1.1 Japanese now works with a patch.\r\n  - Reduced savegame size for SG-1000 and Colecovision systems.\r\n  - Compiled with latest Allegro library, adding support for the following\r\n    joysticks/pads drivers:\r\n      - DB9 pads through parallel ports (allow to plug real SMS pads!)\r\n      - PC Engine pads through parallel ports\r\n      - Saturn pads with IF-SEGA interface cards for PC.\r\n\r\n Now Phantasy Star runs at 49 frame per seconds on my computer !\r\n\r\n\r\n MEKA 0.40\r\n ---------\r\n Master System perfect compatibility rate is now of 97.78%\r\n Games still causing problems are:\r\n   Aerial Assault (minor scrolling glitch on the beginning of a level)\r\n   Back to the Future 3 (minor bug on title screen)\r\n   Missile Defense 3D (buggy lightgun emulation)\r\n   Operation Wolf (buggy lightgun emulation)\r\n   Robocop 3 (pausing crashes the game)\r\n   Shooting Gallery (buggy lightgun emulation)\r\n   Wanted (buggy lightgun emulation)\r\n   Wonderboy in Monsterworld (glitches when pressing pause)\r\n\r\n Game Gear perfect compatibility rate is 94.55%\r\n 17 games are still causing problems, including 5 which requires simulation\r\n of LCD screen visual persistance to produces transparency effect, 3 using\r\n an internal EEPROM to save custom teams, 2 having bad scrolling positions,\r\n and the 7 others:\r\n   GP Rider (road distort itself after a moment)\r\n   Kishin Douji Zenki (one line of clouds is not scrolling in fighting level)\r\n   NBA Action (sprites flickering, might be the real game behavior)\r\n   Out Run (no music for some reasons)\r\n   RBI Baseball '94 (sprites not visible in top view, might be a bad dump)\r\n   Sonic Blast / G-Sonic (micro title bug in US/Euro mode)\r\n   Sonic Drift 2 (bottom line has a bad scrolling offset)\r\n\r\n Sega Game 1000 perfect compatibility rate is 97.40%\r\n Games still causing problems are:\r\n   Pitfall 2 (minor glitch at the top when dying)\r\n   Rockn' Bolt (sprite priorities bug on lift when starting)\r\n\r\n  - Improved emulation on various point, fixing:\r\n      - Altered Beast (SMS): title screen effect is now ok\r\n      - Cool Spot (SMS): no more minor flickering\r\n      - Evander Holyfield Boxing (GG): no more blue screen every odd frame\r\n      - Global Gladiator (SMS): no more minor flickering\r\n      - Gun Star Heroes (GG): no more glitches here and here\r\n      - Hang On / Safari Hunt (SMS): fixed a bug preventing to start sometimes\r\n      - Heavy Weight Champ (SMS): music play on introduction\r\n      - Hurricanes (GG): no more blue screen every odd frame\r\n      - Impossible Mission (SMS): room are showing properly when entering\r\n      - NBA Jam (GG): playfield is ok\r\n      - PGA Tour Golf (SMS): playfield is ok before game start\r\n      - Legend of Illusion (SMS): does not hang anymore at the sunken ship stage\r\n      - Out Run (GG): no more flickering\r\n      - Orguss (SG-1000): no hang when exploding with the small robot\r\n      - Safari Hunting (SG-1000): no hang when entering in the game area\r\n      - Safari Race (SG-1000): better response of button on title screen\r\n      - Shining Force 1 (GG): fixed random crashes\r\n      - Shining Force 2 (GG): fixed random crashes\r\n      - Shining Force 3 (GG): fixed random crashes\r\n      - Speedball 2 (SMS): no more flickering\r\n      - Sonic Drift (GG): now works perfectly\r\n      - Sonic Drift 2 (GG): now works almost perfectly, minor bug on bottom\r\n      - Terminator 2: Judgement Day (GG): no more blackout every odd frame\r\n      - WWF Steel Cage Challenge (SMS): no more moving bug on barriers\r\n      - Xenon 2 (SMS): no more flickering\r\n  - Custom IPeriod values for Aerial Assault (SMS), Barcelona 92 (SMS),\r\n    Gokuaku Doumei Dump Matsumoto (SMS) and Pro Wrestling (SMS) are not\r\n    needed anymore due to improved emulation, and were removed. The only\r\n    game left needing a custom IPeriod value is \"Shadow of Beast\" which\r\n    sometimes crash on title screen with the default value.\r\n  - Improved voice emulation, many games sound correct now (not all).\r\n  - Updated to Allegro WIP in prevision to future improvments. In the\r\n    meanwhile, the new version provides drivers for Gravis Grip, PSX and\r\n    Nintendo 64 joypads, as well as better Sidewinder support (untested).\r\n  - Rewrote hardware sprite collision emulation. Might break some games,\r\n    please report if you discover anything unusual!\r\n  - Improved Master System Sportpad controller emulation.\r\n    Games are easier to play now, even if it is not perfect.\r\n  - Improved default mapper emulation.\r\n  - Added (buggy) EEPROM model 93c46 emulation. This chipset is used by\r\n    three Game Gear baseball games to save custom teams and game progress.\r\n    Pretty though one to emulate, but that's the only way to reach perfect\r\n    emulation ^_^\r\n  - Added Rapid Fire emulation.\r\n  - Improved video mode 2 emulation, fixing Cosmo Fighter 2 (Coleco).\r\n  - Added video mode 3 emulation, used by two painting programs for the\r\n    Colecovision, and very probably by many SC-3000 programs.\r\n  - Definitively removed the snow effect that pissed everyone :-(\r\n    I would have stopped on the 28 of December, anyway.\r\n    Instead, added the \"special=snow\" parameter in the theme file, to\r\n    create your own themes using that effect.\r\n  - Added Christmas and Sunrise GUI themes.\r\n  - Compatibility and checksum lists changes:\r\n     - Added a bunch of new names.\r\n     - Added new Game Gear Japanese games (thanks to Casiopea).\r\n     - Differencied names for alternate versions (thanks to Luke).\r\n     - Added product numbers for about 150 Japanese Game Gear games.\r\n  - Added IPERIOD_SG1000_SC3000 setting in the configuration file.\r\n  - Added a patch to fix the bug in Sport Pad Soccer which make it hang on\r\n    systems without the FM chipset.\r\n  - Fixed bad screen size bug in certain cases after freeing ROM.\r\n  - Added improved filter for old configuration file. As the keyboard\r\n    keycodes have changed in this version they cannot be imported.\r\n  - Added /LOG command line parameters to log all messages to a file.\r\n  - Rewrote message applet from scratch. It does not slow down anymore\r\n    when the number of messages per second is too important (+1000).\r\n  [sources changes]\r\n  - Revamped mapper handling.\r\n  - Revamped backed memory handling.\r\n\r\n\r\n MEKA 0.32c\r\n ----------\r\n  (minor update - version number still the same in the executable)\r\n  - Fixed a stupid little damned bug causing the program to crash under DOS.\r\n  - Added IPERIOD_COLECO setting in the configuration file.\r\n    Do not touch unless you know what it means!\r\n\r\n\r\n MEKA 0.32b\r\n ----------\r\n  (minor update - version number still the same in the executable)\r\n  - Fixed slodown bug when loading a non Coleco ROM after a Coleco ROM.\r\n  - Fixed a bug preventing from switching the machine Off in certain cases.\r\n  - Fixed a minor file browser bug (selection was lost when using mouse).\r\n  - Added some new checksums for various hacks.\r\n  - Added a new GUI theme.\r\n\r\n\r\n MEKA 0.32\r\n ---------\r\n  - Fixed the following games:\r\n      - Andre Agassi Tennis [SMS, GG]\r\n      - Greendog [GG] (Sega logo now shake, it did not before)\r\n      - Panzer Dragoon Mini [GG]\r\n      - Pit Fighter [SMS]\r\n  - Improved emulation in the following games:\r\n      - PGA Tour Golf [SMS] (level presentation now scroll - buggy)\r\n      - Sonic Spinball [SMS, GG] (lake in introduction now scroll - buggy)\r\n  - Fixed a VDP bug introduced in 0.31 that affected Rescue Mission (and\r\n    probably many other games, too).\r\n  - Added .BIN extension in the file browser (for some Colecovision ROMs).\r\n  - Fixed incorrect palette of Colecovision picture after freeing ROM.\r\n  - Updated Colecovision compatibility list, Added a new GUI theme,\r\n    Added checksum and names for a bunch of SMS hacks.\r\n  - Improved debugger (still not for public consumption).\r\n\r\n\r\n MEKA 0.31\r\n ---------\r\n (YM-2413 emulation is disabled by default because of many people who\r\n  do not know about the existence of that chipset and complain about the\r\n  musics and sound effects not being the same as they used to hear. Now\r\n  that you know about it, feel free to enable YM-2413 emulation yourself).\r\n\r\n  - Updated various chapters of the documentation. Please read it!\r\n  - Added ZIP files support. Also improved file handling in general.\r\n    Warning: loading ZIP files which do not contains valid ROM images may\r\n    crash the program when it comes to emulating a non Z80-code file.\r\n  - Made some minor optimizations of screen refresh.\r\n  - Fixed a bug that caused games not to run before being reseted\r\n    when in Japanese mode with the BIOS enabled.\r\n  - Fixed a bug which cause the START button to be randomly pressed just\r\n    after loading a Game Gear savegame.\r\n  - Added a patch to fix the bug in American Pro Football that make it\r\n    hang on systems with the FM chipset.\r\n  - Fixed too early palette setting when loading a SG-1000/SC-3000/Coleco\r\n    game from the command line.\r\n  - Added support for sprites both doubled and zoomed.\r\n  - Added options box with various flags modifiable directly under the GUI:\r\n     - Enable/disable startup BIOS logo.\r\n     - Keep file browser open after loading game.\r\n     - Switch to fullscreen mode after loading game (new option).\r\n     - Enable/disable virtual long file names (new option).\r\n     - Enable/disable messages in fullscreen mode.\r\n  - Slighty improved dynamic palette system, fixing Moldorian and other\r\n    games, until a better fix could be applied.\r\n  - Added an option to show games product numbers.\r\n  - Game comments are now displayed under the GUI, and a warning is given\r\n    on known bad dumps. Any cool informations and comments that could be\r\n    included in the default distribution are welcome.\r\n  - Updated Colecovision support (finally):\r\n     - Improved keypad emulation. Mapped # and * keys on the keyboard.\r\n       Their corresponding keys are minus and equals, next to the 0.\r\n     - Fixed garbage sound on the beginning of some games.\r\n     - Improved interrupt emulation.\r\n     - Fixed joypad emulation in some cases.\r\n     - Added Colecovision picture in the graphical user interface.\r\n  - Reorganized and cleaned various parts of the sources. Improved\r\n    widgets and configuration file handling (no visible changes).\r\n  - Updated compatibility and checksum lists with new entries. Added and\r\n    fixed even more Japanese names. Added flags here and here.\r\n\r\n\r\n MEKA 0.30\r\n ---------\r\n  - Hiroshi added a preliminary FM Voice Editor.\r\n  - Fixed FM emulation bug in Wonderboy 2 / Monster World 1 / Monica 1.\r\n  - FM writes are now delayed, and FM musics are now in better sync with PSG.\r\n  - Hiroshi dumped the original Japanese Master System BIOS. Then I hacked\r\n    and interfaced it to includes it in MEKA. To watch the demo included\r\n    in the Japanese SMS: change the machine country to Japanese, remove\r\n    cartridge if any is loaded and switch the power ON.\r\n  - Fixed a bug in VRAM access emulation (AX Battler sprites now works).\r\n  - Improved dynamic palette system:\r\n      - No more color bug in Itchy & Scratchy (GG) and Bust a Move (GG)\r\n      - Less flickering in Space Harrier (GG) menu\r\n  - Improved palette handling when a game quickly change the video mode\r\n    in the middle of a frame, fixing Back to the Future 2 (SMS).\r\n  - Fixed title screen bug in California Games 2 (SMS).\r\n  - Fixed top screen flickering in Addams Family (SMS)\r\n  - Fixed Pop Breaker (GG). I did introduce a bug just before releasing 0.10.\r\n  - Fixed dirty first column when reseting some SG-1000 games.\r\n  - Fixed dirty first column on badly programmed SMS games (Jurassic Park).\r\n  - Improved file browser:\r\n      - Added keyboard input (arrows, page up/down, home/end, letters)\r\n      - Added little flags next to Japanese, Brazilian and Australian games.\r\n      - Added a configuration switch to keep the browser open after loading.\r\n      - Selected file is now kept after loading a game.\r\n  - Rewrote some parts of the GUI engine (no visual changes).\r\n  - Fixed a command line bug.\r\n  - The pause/start button has been moved to the SPACE key for two reasons:\r\n    first, some games use it as an action button, and secondly, when the file\r\n    browser is open it would interfer with it because of the ENTER key.\r\n  - Added patch to fix Sega logo color in the Ninja Gaiden bad dump.\r\n  - Added tons of new entries to the checksum, name and compatibility lists.\r\n  - Added 3 new GUI themes (uncomment manually or enable with WonderTheme).\r\n  - A bunch of other minor fixes and improvements.\r\n\r\n\r\n MEKA 0.20\r\n ---------\r\n  - Removed delays when accessing to soundblaster hardware registers,\r\n    resulting in a 20 frame per seconds speedup in R-Type, and no more\r\n    slowdowns in Wonderboy 3 with YM2413 emulation enabled. If you have\r\n    problems with this version, try setting the value back to 16 in the\r\n    configuration file, and be sure to contact me.\r\n  - Added automatic peripheral type switching.\r\n  - Added Sport Pad controller emulation.\r\n  - Improved Paddle controller emulation (much more precise).\r\n  - Finally managed to understand peripheral detection, so you can\r\n    play Out Run with the Paddle controller enabled (ala Steering Wheel)\r\n    for the first time in your life :-)\r\n  - Fixed Light Phaser emulation bug in Operation Wolf.\r\n  - Added a switch to enable/disable YM-2413 emulation inside of the GUI.\r\n  - Added a switch to change country inside of the GUI.\r\n  - Emusphere.com sucks (just checking if they ever read what they paste).\r\n  - Messages are now shown in fullscreen mode, making things a bit slower.\r\n    You can disable that feature in the configuration file.\r\n  - Fixed snow when VSync is enabled and colors are being updated. Check the\r\n    Star Wars introduction to notice the difference. (thanks to Lord_B).\r\n  - Major checksum, name and compatibility lists update. Added more than\r\n    200 new entries, fixed some names, and added more product numbers and\r\n    Japanese name equivalents. (special thanks to Jossa and Tincho DJ)\r\n  - Fixed a potential nationalization bug.\r\n  - Added hard pause feature, available from the menu or with CTRL-P.\r\n  - Added ALT-F11 hotkey to enable/disable the background layer (for\r\n    sprites ripping).\r\n  - Added values in the configuration file to resize the file browser.\r\n  - Added values in the configuration file to remap the joystick buttons.\r\n  - Added necessary menu entries to swap keyboard and gamepad buttons.\r\n  - Added two new GUI themes, courtesy of Tincho DJ. Uncomment them in the\r\n    default theme file or enable them with Wonder Theme.\r\n  - Updated savegame format (backward compatible, of course).\r\n  - Increased end delay for non registered users.\r\n  - A few other cosmetic changes.\r\n\r\n Special thanks for this release goes to James McKay for having figured the\r\n big part of the controller thing by originally hacking Sport Pad Football.\r\n\r\n\r\n MEKA 0.13.1\r\n -----------\r\n  - Fixed many crashing bug introduced in version 0.13.\r\n  - Fixed FM persistant sound when loading a PSG game after a FM game.\r\n  - Fixed a bug when trying to free a ROM when the BIOS logo is running.\r\n  - Now you can load a savegame while the BIOS logo is running.\r\n  - Fixed Shining Force 3 (Game Gear).\r\n  - Added some more entries in the compatibility and checksum lists.\r\n\r\n\r\n MEKA 0.13\r\n ---------\r\n  - Various non emulation bug fixed.\r\n  - Added an option to free the current loaded ROM (to play the snail game).\r\n  - Added Colecovision emulation.\r\n  - Color themes are no more hardcored into the executable, so you can create\r\n    your own ones by editing the MEKA.THM file. Added the following new ones:\r\n      - Girl's Power (by me)\r\n      - Monochrome (by Limbs a Flyin')\r\n      - Necro (by Roni)\r\n      - Grey Box (by Puyolin and me)\r\n  - Added the necessary code for handling registration keys. Now registered\r\n    users have a permanent keyfile that unlock MEKA.\r\n  - All pause buttons bug with or without joypads enabled should be fixed\r\n    now, although I still cannot test the code.\r\n  - Fixed snow in SG-1000/SC-3000/Colecovision games.\r\n  - Fixed a keyboard lock bug that happened sometimes (mainly when starting\r\n    \"BrAin waSH\" but also in some other cases).\r\n  - Update savegame file format. Old files can still be loaded with this\r\n    version, but you won't be able to play the new savegames with an older\r\n    version. Oh well, who cares ?\r\n  - Removed SMS background picture anti-aliasing to fit with all color themes\r\n    and added a picture when no cartridges is inserted.\r\n  - Some optimizations in SG-1000/SC-3000/Colecovision games.\r\n  - Added FM patch for Monica Em: O Resgate.\r\n  - Added a few more titles to the compatibility and checksum lists.\r\n\r\n\r\n MEKA 0.12\r\n ---------\r\n  - Added preliminary voice emulation.\r\n  - Added joystick and video drivers entry in the configuration file\r\n    (you can now use four-buttons joypads, VESA modes, etc..).\r\n  - Fixed PSG/FM volumes.\r\n  - Fixed a bug that prevented Battery RAM to be saved in certain cases.\r\n  - Fixed a BIOS bug when no ROM was loaded in Japanese mode.\r\n  - Added an option to disable background refresh (for GFX ripping).\r\n  - Fixed virtual long filename duplicates creation.\r\n  - Changed default IPeriod to 228 and updated the list.\r\n  - Fixed Shining Force 2.\r\n  - Added new entries into checksum and compatibily lists.\r\n  - Improved double dump detection, via a tolerance system.\r\n  - Some minor optimizations.\r\n\r\n\r\n MEKA 0.11\r\n ---------\r\n  - Fixed sound crashing.\r\n  - Improved FM sound emulation.\r\n  - Mapped start/pause button on joystick (button 3).\r\n  - Fixed Orguss (SG-1000).\r\n  - Fixed Power Strike (SMS).\r\n\r\n\r\n MEKA 0.10\r\n ---------\r\n  - Initial public release.\r\n\r\n"
  },
  {
    "path": "meka/compat.txt",
    "content": "-----------------------------------------------------------------------------\r\n MEKA - Compatibility List\r\n-----------------------------------------------------------------------------\r\n Please contact me or post on MEKA forum if you suspect any game or having\r\n a problem not mentioned here.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA MASTER SYSTEM (SMS) COMPATIBILITY LIST\r\n-----------------------------------------------------------------------------\r\n FM:        Supports FM Music\r\n LP/(LP):   Requires/Supports Light Phaser\r\n PAD/(PAD): Requires/Supports Paddle Control (ala Steering Wheel)\r\n SP/(SP):   Requires/Supports Sports Pad Controller\r\n 3D:        Uses 3-D Glasses\r\n SMS-GG:    This version is a GG cartridge using the SMS compatibility mode\r\n SMS-MD:    This version is an MD cartridge using the SMS compatibility mode\r\n-----------------------------------------------------------------------------\r\n 11 Hap Gam-Boy (KR)                            -       Ok\r\n 128 Hap (KR)                                   -       Ok\r\n 2 Hap in 1 (Moai-ui bomul, David-2) (KR)       -       Ok\r\n 20 em 1 (BR)                                   -       Ok\r\n 3D Gunner [Proto]                              LP,3D   Ok\r\n 4 PAK All Action (AU)                          -       Ok\r\n 94 Super World Cup Soccer (KR)                 -       Ok\r\n Ace of Aces                                    -       Ok\r\n Action Fighter [v0] [Proto]                    -       Ok\r\n Action Fighter [v1]                            -       Ok\r\n Action Fighter [v2]                            -       Ok\r\n Action Fighter (TW)                            -       Ok\r\n Addams Family, The                             -       Ok\r\n Aerial Assault                                 -       Ok\r\n Aerial Assault (US)                            -       Ok\r\n Aerial Assault [HTH] [SMS-GG] (TW)             -       Ok\r\n After Burner                                   FM      Ok\r\n Agigongnyong Dooly (KR)                        -       Ok\r\n Air Rescue                                     -       Ok\r\n Aladdin (Disney's)                             -       Ok\r\n Aleste (JP)                                    FM      Ok\r\n Alex Kidd: High-Tech World                     -       Ok\r\n Alex Kidd: High-Tech World [Proto]             -       Ok\r\n Alex Kidd in Miracle World [v0] (US)           -       Ok\r\n Alex Kidd in Miracle World [v1]                -       Ok\r\n Alex Kidd no Miracle World (JP)                -       Ok\r\n Alex Kidd in Miracle World [HTH] [SMS-GG] (TW) -       Ok\r\n Alex Kidd in Shinobi World                     -       Ok\r\n Alex Kidd: The Lost Stars                      FM      Ok\r\n Alf                                            -       Ok\r\n Alibaba and 40 Thieves (KR)                    -       Ok\r\n Alien 3                                        -       Ok\r\n Alien Storm                                    -       Ok\r\n Alien Syndrome                                 FM      Ok\r\n Alien Syndrome (JP)                            FM      Ok\r\n Alien Syndrome [Proto]                         FM      Ok\r\n Altered Beast                                  FM      Ok\r\n American Baseball                              -       Ok\r\n American Pro Football                          -       Ok\r\n Andre Agassi Tennis                            -       Ok\r\n Anmitsu Hime (JP)                              -       Ok\r\n Arcade Smash Hits                              -       Ok\r\n Argos no Juujiken (JP)                         -       Ok\r\n Argos no Juujiken [HTH] [SMS-GG] (TW)          -       Ok\r\n Ariel - The Little Mermaid (Disney's) (BR)     -       Ok\r\n Ashura (JP)                                    -       Ok\r\n Assault City                                   -       Ok\r\n Assault City [Light Phaser]                    LP      Ok\r\n Asterix [v0]                                   -       Ok\r\n Asterix [v1]                                   -       Ok\r\n Asterix and the Great Rescue                   -       Ok\r\n Asterix and the Secret Mission                 -       Ok\r\n Astro Flash (JP)                               -       Ok\r\n Astro Warrior                                  -       Ok\r\n Astro Warrior / Pit Pot                        -       Ok\r\n Astro Warrior / Pit Pot [Proto]                -       Ok\r\n A-Team, The [Music] [Proto]                    -       Ok\r\n Aztec Adventure / Nazca '88                    FM      Ok\r\n Aztec Adventure [HTH] [SMS-GG] (TW)            FM      Ok\r\n Back to the Future Part II                     -       Ok\r\n Back to the Future Part III                    -       Ok\r\n Baku Baku Animal (BR)                          -       Ok\r\n Bank Panic                                     -       Ok\r\n Bart vs. The Space Mutants (The Simpsons)      -       Ok\r\n Bart vs. The World (The Simpsons)              -       Ok\r\n Basketball Nightmare                           -       Ok\r\n Basketball Nightmare [Proto 0]                 -       Ok\r\n Basketball Nightmare [Proto 1]                 -       Ok\r\n Batman Returns                                 -       Ok\r\n Battlemaniacs (BR)                             -       Ok\r\n Battle Out Run                                 (FM)    Ok (Hidden FM music)\r\n Battle Wings [Proto]                           FM      Ok\r\n Black Belt                                     -       Ok\r\n Black Belt [HTH] [SMS-GG] (TW)                 -       Ok\r\n Blade Eagle 3-D / Blade Eagle                  FM,3D   Ok\r\n Blade Eagle 3-D / Blade Eagle [Proto 0]        FM,3D   Ok\r\n Blade Eagle 3-D / Blade Eagle [Proto 1]        FM,3D   Ok\r\n Block Hole (KR)                                -       Ok\r\n BMX Trial - Alex Kidd (JP)                     FM,PAD  Ok\r\n Bomber Raid                                    FM      Ok\r\n Bonanza Bros.                                  -       Ok\r\n Bonkers Wax Up! (Disney's) (BR)                -       Ok\r\n Bobble Bobble [Clover] (KR)                    -       Ok\r\n Bubble Bobble                                  -       Ok\r\n Buggy Run                                      -       Ok\r\n California Games                               FM      Ok\r\n California Games II                            -       Ok\r\n Captain Silver                                 FM      Ok\r\n Captain Silver (US)                            FM      Ok\r\n Captain Silver [Proto]                         FM      Ok\r\n Casino Games                                   FM      Ok\r\n Castelo Rá-Tim-Bum (BR)                        -       Ok\r\n Castle of Illusion - Starring Mickey Mo.. [v0] -       Ok\r\n Castle of Illusion - Starring Mickey Mo.. [v1] -       Ok\r\n Castle of Illusion - Starring Mickey.. [Demo]  -       Ok\r\n Champions of Europe                            -       Ok\r\n Championship Hockey                            -       Ok\r\n Chapolim x Drácula - Um Duelo Assustador (BR)  -       Ok\r\n Cheese Cat-astrophe - Starring Speedy Gonzales -       Ok\r\n Choplifter                                     -       Ok\r\n Choplifter [HTH] [SMS-GG] (TW)                 -       Ok\r\n Choplifter [Proto]                             -       Ok\r\n Choplifter [Proto] (JP)                        -       Ok\r\n Chouon Senshi Borgman (JP)                     FM      Ok\r\n Chouon Senshi Borgman [Proto] (JP)             FM      Ok\r\n Chuck Rock                                     -       Ok\r\n Chuck Rock II: Son of Chuck                    -       Ok\r\n Chuck Rock II: Son of Chuck (BR)               -       Ok\r\n Circuit, The (JP)                              -       Ok\r\n Circuit, The (TW)                              -       Ok\r\n Cloud Master / Chuka Taisen                    FM      Ok\r\n Cloud Master / Chuka Taisen [HTH] [SMS-GG] (TW) FM    *Ok\r\n Color & Switch Test                            -       Ok\r\n Con-Dori (KR)                                  -       Ok\r\n Columns                                        -       Ok\r\n Columns [Proto]                                -       Ok\r\n Comical Machine Gun Joe (JP)                   -       Ok\r\n Comical Machine Gun Joe (KR)                   -       Ok\r\n Comical Machine Gun Joe (TW)                   -       Ok\r\n Comic Bakery (KR)                              -       Ok\r\n Cool Spot                                      -       Ok\r\n Cosmic Spacehead                               -       Ok\r\n C_So! [MSX] (KR)                               -       Ok\r\n Cyber Shinobi, The                             -       Ok\r\n Cyber Shinobi, The [Proto]                     -       Ok\r\n Cyber Shinobi, The [HTH] [SMS-GG] (TW)         -       Ok\r\n Cyborg Hunter                                  FM      Ok\r\n Cyborg Hunter [Proto]                          FM      Ok\r\n Cyborg Z (KR)                                  -       Ok\r\n Daffy Duck in Hollywood                        -       Ok\r\n Danan: The Jungle Fighter                      -       Ok\r\n Danan: The Jungle Fighter [HTH] [SMS-GG] (TW)  -      *Ok\r\n Dead Angle                                     -       Ok\r\n Dead Angle [Proto]                             -       Ok\r\n Deep Duck Trouble - Starring Donald Duck       -       Ok\r\n Desert Speedtrap - Starring Road Runner and..  -       Ok\r\n Desert Strike                                  -       Ok\r\n Dick Tracy                                     -       Ok\r\n Dinobasher - Starring Bignose the Ca.. [Proto] -       Ok\r\n Dinosaur Dooley, The (KR)                      -       Ok\r\n Dodgeball King (KR)                            -       Ok\r\n Doki Doki Penguin Land - Uchuu Daibouken (JP)  FM      Ok\r\n Doki Doki Penguin Land ... [HTH] [SMS-GG] (TW) FM      Ok\r\n Doki Doki Penguin Land ... [Proto] (JP)        FM      Ok\r\n Double Dragon                                  FM      Ok\r\n Double Dragon (KR)                             FM      Ok\r\n Double Dragon [HTH] [SMS-GG] (TW)              FM      Ok\r\n Double Hawk                                    (FM)    Ok (Hidden FM music)\r\n Double Hawk [Proto]                            (FM)    Ok (Hidden FM music)\r\n Double Target - Cynthia no Nemuri              -       Ok\r\n Dracula (Bram Stoker's)                        -       Ok\r\n Dr. Robotnik's Mean Bean Machine               -       Ok\r\n Dragon Crystal                                 -       Ok\r\n Dragon: The Bruce Lee Story                    -       Ok\r\n Dr. HELLO (KR)                                 -       Ok\r\n Dynamite Duke                                  -       Ok\r\n Dynamite Dux                                   (FM)    Ok (Hidden FM music)\r\n Dynamite Dux [Proto]                           (FM)    Ok (Hidden FM music)\r\n Dynamite Headdy (BR)                           -       Ok\r\n Eagles 5 (KR)                                  -       Ok\r\n Earthworm Jim (BR)                             -       Ok\r\n Ecco the Dolphin                               -       Ok\r\n Ecco - The Tides of Time (BR)                  -       Ok\r\n E.I. - Exa Innova (KR)                         -       Ok\r\n Enduro Racer                                   -       Ok\r\n Enduro Racer (JP)                              -       Ok\r\n E-SWAT [v0]                                    -       Ok\r\n E-SWAT [v1]                                    -       Ok\r\n E-SWAT [v1] [HTH] [SMS-GG] (TW)                -       Ok\r\n E-SWAT [Proto 0]                               -       Ok\r\n E-SWAT [Proto 1]                               -       Ok\r\n E-SWAT [Proto 2]                               -       Ok\r\n Excellent Dizzy Collection, The [Proto]        -       Ok (The prototype isn't really playable)\r\n F1                                             -       Ok\r\n F-1 Spirit - The way to Formula-1 (KR)         -       Ok\r\n F-16 Fighter                                   -       Ok\r\n F-16 Fighting Falcon (US)                      -       Ok\r\n F-16 Fighting Falcon (JP)                      -       Ok\r\n F-16 Fighting Falcon (TW)                      -       Ok\r\n Fantastic Dizzy                                -       Minor graphic bug when pausing.\r\n Fantasy Zone [v0] (JP)                         -       Ok\r\n Fantasy Zone [v1] [Proto]                      -       Ok\r\n Fantasy Zone [v2]                              -       Ok\r\n Fantasy Zone [v2] (TW)                         -       Ok\r\n Fantasy Zone II - The Tears of Opa-Opa         FM      Ok\r\n Fantasy Zone II - Opa-Opa no Namida (JP)       FM      Ok\r\n Fantasy Zone: The Maze                         FM      Ok\r\n Fantasy Zone: The Maze [Proto]                 FM      Ok\r\n Family Games (Party Games) (JP)                FM      Ok\r\n FA Tetris (KR)                                 -       Ok\r\n Férias Frustradas do Pica Pau (BR)             -       Ok\r\n FIFA International Soccer (BR)                 -       Ok\r\n Final Bubble Bobble (JP)                       -       Ok\r\n Final Bubble Bobble [HTH] [SMS-GG] (TW)        -       Ok\r\n Fire & Forget II                               -       Ok\r\n Fire & Ice (BR)                                -       Ok\r\n Flash, The                                     -       Ok\r\n Flashpoint (KR)                                -       Ok\r\n Flintstones, The                               -       Ok\r\n Forgotten Worlds                               -       Ok\r\n Forgotten Worlds [HTH] [SMS-GG]                -       Ok\r\n Fushigi no Oshiro Pit Pot (JP)                 -       Ok\r\n Fushigi no Oshiro Pit Pot [Proto] (JP)         -       Ok\r\n Gaegujangi Kkachi (KR)                         -       Ok\r\n Game Mo-eumjip 188 Hap [v0] (KR)               -       Ok\r\n Game Mo-eumjip 188 Hap [v1] (KR)               -       Ok\r\n Gain Ground                1                   -       Ok\r\n Gain Ground [Proto]                            -       Ok\r\n Galactic Protector (JP)                        FM,PAD  Ok\r\n Galaxian (KR)                                  -       Ok\r\n Galaxy Force                                   FM      Ok\r\n Galaxy Force (US)                              FM      Ok\r\n Game Box Série Esportes Radicais (BR)          FM      Ok\r\n Game Chongjiphap 200 (KR)                      -       Ok\r\n Game De Check! Koutsuu Anzen [Proto] (JP)      FM      Ok\r\n Game Jiphap 30 Hap [SMS-MD] (KR)               -      *Ok\r\n Gangcheol RoboCop (KR)                         -       Ok\r\n Gangster Town                                  LP      Ok\r\n Gauntlet                                       -       Ok\r\n George Foreman's KO Boxing                     -       Ok\r\n Geraldinho (BR)                                -       Ok\r\n Ghost House                                    -       Ok\r\n Ghost House (KR)                               -       Ok\r\n Ghost House (JP)                               -       Ok\r\n Ghost House [Proto]                            -       Ok\r\n Ghostbusters                                   -       Ok\r\n Ghouls'n Ghosts                                -       Ok\r\n Ghouls'n Ghosts [HTH] (SMS-GG) (TW)            -       Ok\r\n Ghouls'n Ghosts [Demo]                         -       Ok\r\n Global Defense                                 FM      Ok\r\n Global Defense [Proto]                         FM      Ok\r\n Global Gladiators                              -       Ok\r\n G-LOC - Air Battle                             -       Ok\r\n Gokuaku Doumei Dump Matsumoto (JP)             -       Ok\r\n Golden Axe                                     -       Ok\r\n Golden Axe [Demo]                              -       Ok\r\n Golden Axe Warrior                             -       Ok\r\n Golfamania                                     FM      Ok\r\n Golfamania [Proto]                             FM      Ok\r\n Golfamania (Super Golf) [Proto]                FM      Ok\r\n Golvellius - Valley of Doom                    FM      Ok\r\n GP Rider                                       -       Ok\r\n Great Baseball                                 -       Ok\r\n Great Baseball [JP] (JP)                       -       Ok\r\n Great Basketball                               -       Ok\r\n Great Basketball [HTH] [SMS-GG] (TW)           -       Ok\r\n Great Football                                 -       Ok\r\n Great Golf / Masters Golf                      FM      Ok\r\n Great Golf / Masters Golf [Mega-Tech]          FM      Ok\r\n Great Golf / Masters Golf [Proto] (JP)         FM      Ok\r\n Great Golf [JP] (JP)                           -       Ok\r\n Great Golf [JP] (KR)                           -       Ok\r\n Great Ice Hockey                               SP      Ok\r\n Great Soccer                                   -       Ok\r\n Great Soccer (JP)                              -       Ok\r\n Great Soccer (TW)                              -       Ok\r\n Great Tennis / Super Tennis (JP)               -       Ok\r\n Great Volleyball                               -       Ok\r\n Great Volleyball (JP)                          -       Ok\r\n Gun.Smoke (KR)                                 -       Ok\r\n Haja no Fuuin (JP)                             FM      Ok\r\n Hang On                                        -       Ok\r\n Hang On (JP)                                   -       Ok\r\n Hang On [Proto]                                -       Ok\r\n Hang On / Astro Warrior                        -       Ok\r\n Hang On / Safari Hunt                          LP      Ok\r\n Hang On / Safari Hunt [Proto]                  LP      Ok\r\n Heavyweight Champ                              -       Ok\r\n Heroes of the Lance                            -       Ok\r\n Heroes of the Lance [Proto]                    -       Ok\r\n Hi-Com 3-in-1 The Best Game Collection A (KR)  -       Ok\r\n Hi-Com 3-in-1 The Best Game Collection B (KR)  -       Ok\r\n Hi-Com 3-in-1 The Best Game Collection C (KR)  -       Ok\r\n Hi-Com 3-in-1 The Best Game Collection D (KR)  -       Ok\r\n Hi-Com 3-in-1 The Best Game Collection E (KR)  -       Ok\r\n Hi-Com 3-in-1 The Best Game Collection F (KR)  -       Ok\r\n Hi-Com 8-in-1 The Best Game Collection A (KR)  -       Ok\r\n Hi-Com 8-in-1 The Best Game Collection B (KR)  -       Ok\r\n Hi-Com 8-in-1 The Best Game Collection C (KR)  -       Ok\r\n High School! Kimengumi (JP)                    -       Ok\r\n Hokuto no Ken (JP)                             -       Ok\r\n Hokuto no Ken (TW)                             -       Ok (note: final boss graphic data is corrupted)\r\n Hokuto no Ken [HTH] [SMS-GG] (TW)              -       Ok\r\n Home Alone                                     -       Ok\r\n Hong Kil Dong (KR)                             -       Ok\r\n Hook [Proto]                                   -       Ok\r\n Hoshi wo Sagashite... (JP)                     FM      Ok\r\n Hwarang-ui Geom (KR)                           FM      Ok\r\n Impossible Mission                             -       Ok\r\n Impossible Mission [Proto]                     -       Ok\r\n Incredible Crash Dummies, The                  -       Ok\r\n Incredible Hulk, The                           -       Ok\r\n Indiana Jones and the Last Crusade             -       Ok\r\n Indiana Jones and the Last Crusade [Proto]     -       Ok\r\n Jaemiissneun Game Mo-eumjip 42 Hap [SMS-MD] (KR) -    *Ok\r\n Jaemiissneun Game Mo-eumjip 65 Hap [SMS-MD] (KR) -    *Ok\r\n James Bond 007: The Duel                       -       Ok\r\n James Bond 007: The Duel (BR)                  -       Ok\r\n James \"Buster\" Douglas Knockout Boxing         -       Ok\r\n James \"Buster\" Douglas Knockout Boxing [Proto] -       Ok\r\n James Pond II - Codename: RoboCod              -       Ok\r\n Janggun-ui Adeul (KR)                          -       Ok\r\n Jang Pung II (KR)                              -       Ok\r\n Jang Pung 3 (KR)                               -       Ok\r\n Joe Montana Football                           -       Ok\r\n Jogos de Verão II (BR)                         -       Ok\r\n Jungle Book, The (Walt Disney's Classic)       -       Ok\r\n Jurassic Park                                  -       Ok\r\n Kenseiden                                      FM      Ok\r\n Kenseiden (JP)                                 FM      Ok\r\n Kenseiden [HTH] [SMS-GG] (TW)                  FM      Ok\r\n King & Balloon (KR)                            -       Ok\r\n King's Quest - Quest for the Crown             -       Ok\r\n King's Quest - Quest for the Crown [Proto 0]   -       Ok\r\n King's Quest - Quest for the Crown [Proto 1]   -       Ok\r\n KLAX                                           -       Ok\r\n Knightmare II: The Maze of Galious (KR)        -       Ok\r\n Kujakuou (JP)                                  FM      Ok\r\n Kung Fu Kid                                    -       Ok\r\n Kung Fu Kid [HTH] [SMS-GG] (TW)                -       Ok\r\n Krusty's Fun House                             -       Ok\r\n Land of Illusion - Starring Mickey Mouse       -       Ok\r\n Laser Ghost                                    (LP)    Ok\r\n Lethal Weapon 3 [Music] [Proto]                -       Ok\r\n Legend of Illusion - Starring Mickey Mouse (BR)-       Ok\r\n Lemmings                                       -       Ok\r\n Lemmings [Proto]                               -       Ok\r\n Lemmings 2: The Tribes [Proto]                 -       Ok\r\n Lion King, The (Disney's)                      -       Ok\r\n Line of Fire                                   (3D)    Ok\r\n Loretta no Shouzou (JP)                        -       Ok\r\n Lord of Sword (JP)                             FM      Ok\r\n Lord of Sword [HTH] [SMS-GG] (TW)              FM      Ok\r\n Lord of The Sword                              FM      Ok\r\n Lucky Dime Caper, The - Starring Donald Duck   -       Ok\r\n Lucky Dime Caper, The - Starring Do... [Proto] -       Ok\r\n Mahjong Sengoku Jidai (JP)                     -       Ok\r\n Mahjong Sengoku Jidai [Proto] (JP)             -       Ok\r\n Makai Retsuden (JP)                            -       Ok\r\n Marble Madness                                 -       Ok\r\n Marksman Shooting & Trap Shooting              LP      Ok\r\n Marksman Shooting / Trap Shooting / Safari H.. LP      Ok\r\n Master of Darkness                             -       Ok\r\n Master of Darkness / Vampire [Proto]           -       Ok\r\n Masters of Combat                              -       Ok\r\n Maou Golvellius (JP)                           FM      Ok\r\n Maou Golvellius [Proto] (JP)                   -       Ok\r\n Maze Hunter 3-D                                FM,3D   Ok\r\n Maze Hunter 3-D [Proto]                        FM,3D   Ok\r\n Maze Walker (JP)                               FM,3D   Ok\r\n Megumi Rescue (JP)                             FM,PAD  Ok\r\n Mercs                                          -       Ok\r\n Mega Mode Super Game 30 [SMS-MD] (KR)          -       Ok\r\n Mega Mode Super Game 138 [SMS-MD] (KR)         -       Ok\r\n Mickey's Ultimate Challenge (BR)               -       Ok\r\n Micro Machines                                 -       Ok\r\n Micro Xevious, The (KR)                        -       Ok\r\n Miracle Warriors - Seal of The Dark Lord       FM      Ok\r\n Miracle Warriors - Seal of The Dark.. [Proto]  FM      Ok\r\n Missile Defense 3-D                            LP,3D   Ok\r\n Missile Defense 3-D [Proto]                    LP,3D   Ok\r\n Mônica no Castelo do Dragão (BR)               FM      Ok\r\n Monopoly                                       -       Ok\r\n Monopoly (US)                                  -       Ok\r\n Monopoly [Proto 0]                             -       Ok\r\n Monopoly [Proto 1]                             -       Ok\r\n Montezuma's Revenge - Featuring Panama Joe     -       Ok\r\n Montezuma's Revenge - Featuring Pana.. [Proto] -       Ok\r\n Moonwalker (Michael Jackson's)                 -       Ok\r\n Moonwalker (Michael Jackson's) [Proto]         -       Ok\r\n Moonwalker (Michael Jackson's) [HTH] [SMS-GG] (TW)    *Ok\r\n Mopiranger (KR)                                -       Ok\r\n Mortal Kombat                                  -       Ok\r\n Mortal Kombat II                               -       Ok\r\n Mortal Kombat 3 (BR)                           -       Ok\r\n Ms. Pac-Man                                    -       Ok\r\n MSX Soccer (KR)                                -       Ok\r\n My Hero                                        -       Ok\r\n NBA Jam [Proto]                                -       Ok\r\n Nekkyuu Koushien (JP)                          FM      Ok\r\n Nemesis (KR)                                   -       Ok\r\n Nemesis 2 (KR)                                 -       Ok\r\n New Boggle Boggle 2 (KR)                       -       Ok\r\n NewZealand Story, The                          -       Ok\r\n Ninja, The                                     -       Ok\r\n Ninja, The (JP)                                -       Ok\r\n Ninja, The [HTH] [SMS-GG] (TW)                 -       Ok\r\n Ninja Gaiden                                   -       Ok\r\n Ninja Gaiden [Proto]                           -       Ok\r\n Olympic Gold [v0]                              -       Ok\r\n Olympic Gold [v1]                              -       Ok\r\n Opa Opa (JP)                                   FM      Ok\r\n Operation Wolf                                 (LP)    Ok\r\n Ottifants, The                                 -       Ok\r\n Out Run                                        FM,(PAD)        In FM mode, wave sound hang at race start.\r\n Out Run 3-D                                    FM,(3D),(PAD)   Ok\r\n Out Run 3-D [Proto]                            FM,(3D),(PAD?)  Ok\r\n Out Run Europa                                 -       Ok\r\n Pac-Mania                                      -       Ok\r\n Paperboy [v0]                                  -       Ok\r\n Paperboy [v1]                                  -       Ok\r\n Paperboy [v1] [HTH] [SMS-GG] (TW)              -       Ok\r\n Parlour Games                                  FM      Ok\r\n Pat Riley Basketball [Proto]                   -       Ok\r\n Penguin Adventure (KR)                         -       Ok\r\n Penguin Land                                   FM      Ok\r\n PGA TOUR Golf                                  -       Ok\r\n Phantasy Star [v2]                             -       Ok\r\n Phantasy Star [v3]                             -       Ok\r\n Phantasy Star (JP)                             FM      Ok\r\n Phantasy Star (BR)                             -       Ok\r\n Phantasy Star (KR)                             -       Ok\r\n Phantasy Star Fukkokuban [SMS-MD] (JP)         FM      Ok\r\n Pigu-Wang 7 Hap - Jaemiiss-neun Game Mo-eumjip (KR) -  Ok\r\n Pit-Fighter                                    -       Ok\r\n Pit-Fighter (BR)                               -       Ok\r\n Populous                                       -       Ok\r\n Pooyan (KR)                                    -       Ok\r\n Poseidon Wars 3-D                              FM,(3D) Ok\r\n Power Boggle Boggle (KR)                       -       Ok\r\n Power Strike                                   FM      Ok\r\n Power Strike II                                -       Ok\r\n Predator 2                                     -       Ok\r\n Predator 2 (BR)                                -       Ok\r\n Prince of Persia                               -       Ok\r\n Prince of Persia [HTH] [SMS-GG] (TW)           -       Ok\r\n Promocao Especial M.System III Compact         -       Ok\r\n Pro Wrestling                                  -       Ok\r\n Pro Yakyuu Pennant Race, The (JP)              -       Ok\r\n Psychic World                                  -       Ok\r\n Psycho Fox                                     -       Ok\r\n Psycho Fox [Proto]                             -       Ok\r\n Putt & Putter                                  -       Ok\r\n Putt & Putter [Proto]                          -       Ok\r\n Puznic (KR)                                    -       Ok\r\n Quartet                                        -       Ok\r\n Quartet [HTH] [SMS-GG] (TW)                    -       Ok\r\n Quest for the Shaven Yak Starring Ren Ho..(BR) -       Ok\r\n R-Type                                         FM      Ok\r\n R-Type [Proto]                                 FM      Ok\r\n R-Type [HTH] [SMS-GG] (TW)                     FM      Ok\r\n Rainbow Islands                                -       Ok\r\n Rainbow Islands (BR)                           -       Ok\r\n Rambo - First Blood Part II                    -       Ok\r\n Rambo III                                      LP,(FM) Ok (Hidden FM music)\r\n Rampage                                        FM      Ok\r\n Rampage [Proto]                                FM      Ok\r\n Rampart                                        -       Ok\r\n Rastan                                         FM      Ok\r\n Rastan [Proto]                                 FM      Ok\r\n R.C. Grand Prix                                -       Ok\r\n R.C. Grand Prix [Proto]                        -       Ok\r\n Reggie Jackson Baseball                        -       Ok\r\n Renegade                                       -       Ok\r\n Rescue Mission                                 FM,LP   Ok\r\n Road Fighter (KR)                              -       Ok\r\n Road Rash                                      -       Ok\r\n RoboCop 3                                      -       Ok\r\n RoboCop versus The Terminator                  -       Ok\r\n Rocky                                          -       Ok\r\n Running Battle                                 -       Ok\r\n SDI (JP)                                       FM      Ok\r\n Sagaia                                         -       Ok\r\n Sagaia [HTH] [SMS-GG] (TW)                     -      *Ok\r\n Samgukji III (KR)                              -       Ok\r\n Sapo Xulé O Mestre do Kung Fu (BR)             -       Ok\r\n Sapo Xulé S.O.S. Lagoa Poluída (BR)            -       Ok\r\n Sapo Xulé Vs Os Invasores do Brejo (BR)        -       Ok\r\n Satellite 7 (JP)                               -       Ok\r\n Scramble Spirits                               FM      Ok\r\n Scramble Spirits [Proto]                       FM      Ok\r\n Scramble Spirits [HTH] [SMS-GG] (TW)           FM      Ok\r\n Secret Command                                 -       Ok\r\n Secret Command [HTH] [SMS-GG] (TW)             -       Ok\r\n Sega Chess                                     -       Ok\r\n Sega Graphic Board v2.0 [Proto]                GB2     Ok. Requires Graphic Board v2.0 (Prototype hardware)\r\n Sega World Tournament Golf                     -       Ok\r\n Seishun Scandal (JP)                           -       Ok\r\n Seishun Scandal [HTH] [SMS-GG] (TW)            -       Ok\r\n Sensible Soccer                                -       Ok\r\n Shadow Dancer - The Secret Of Shinobi          -       Ok\r\n Shadow Dancer - The Secr.. [HTH] [SMS-GG] (TW) -       Ok\r\n Shadow of the Beast                            -       Ok\r\n Shadow of the Beast [HTH] [SMS-GG] (TW)        -       Ok\r\n Shanghai                                       FM      Ok\r\n Shanghai [Proto]                               FM      Ok\r\n Shinobi [v0]                                   FM      Ok\r\n Shinobi [v1]                                   FM      Ok\r\n Shooting Gallery                               LP      Ok\r\n Sítio do Picapau Amarelo (BR)                  -       Ok\r\n Sky Fighter (KR)                               -       Ok\r\n Sky Jaguar (KR)                                -       Ok\r\n Sky Jaguar [Clover] (KR)                       -       Ok\r\n Slap Shot [v0]                                 -       Ok\r\n Slap Shot [v1]                                 -       Ok\r\n Slap Shot [v2] (US)                            -       Ok\r\n Slap Shot [Proto]                              -       Ok\r\n Smurfs, The                                    -       Ok\r\n Smurfs Travel the World, The                   -       Ok\r\n Smurfs Travel the World, The [Proto]           -       Ok\r\n Solomon no Kagi - Oujo Rihita no Namida (JP)   FM      Ok\r\n Solomon no Kagi - Oujo Rihita.. [Proto] (JP)   FM      Ok\r\n Sonic Blast                                    -       Ok\r\n Sonic Chaos                                    -       Ok\r\n Sonic Spinball                                 -       Ok\r\n Sonic The Hedgehog                             -       Ok\r\n Sonic The Hedgehog 2 [v0]                      -       Ok\r\n Sonic The Hedgehog 2 [v1]                      -       Ok\r\n Sonic's Edusoft [Proto]                        -       Ok\r\n Space Gun                                      LP      Ok\r\n Space Harrier [50 Hz]                          -       Ok\r\n Space Harrier [50 / 60 Hz]                     -       Ok\r\n Space Harrier 3-D                              FM,(3D) Ok\r\n Space Harrier 3D (JP)                          FM,(3D) Ok\r\n Special Criminal Investigation - S.C.I.        -       Ok\r\n Special Criminal Investigation - S.C.I. [Proto]-       Ok\r\n Speedball [Image Works]                        -       Ok\r\n Speedball [Virgin]                             -       Ok\r\n Speedball 2                                    -       Ok\r\n SpellCaster                                    FM      Ok\r\n Spider-Man - Return of the Sinister Six        -       Ok\r\n Spider-Man - vs. The Kingpin                   -       Ok\r\n Sports Pad Soccer                              SP      Ok\r\n Sports Pad Football                            SP      Ok\r\n Spy vs Spy                                     -       Ok\r\n Spy vs Spy (JP)                                -       Ok\r\n Spy vs Spy (TW)                                -       Ok\r\n Star Wars                                      -       Ok\r\n Street Fighter II' (BR)                        -       Ok\r\n Street Master (KR)                             -       Ok\r\n Streets of Rage                                -       Ok\r\n Streets of Rage II                             -       Ok\r\n Strider                                        -       Ok\r\n Strider [HTH] [SMS-GG] (TW)                    -       Ok\r\n Strider [Demo]                                 -       Ok\r\n Strider II                                     -       Ok\r\n Submarine Attack                               -       Ok\r\n Submarine Attack [HTH] [SMS-GG] (TW)           -       Ok\r\n Sukeban Deka II - Shoujo Tekkamen Densetsu (JP)-       Ok\r\n Summer Games                                   (FM)    Ok (Hidden FM music)\r\n Summer Games [Proto 0]                         -       Ok (No audio)\r\n Summer Games [Proto 1]                         FM      Ok\r\n Suho Jeonsa (KR)                               -       Ok\r\n Super Basketball [Demo]                        -       Ok\r\n Super Bioman I (KR)                            -       Ok\r\n Super Boy I (KR)                               -       Ok\r\n Super Boy II (KR)                              -       Ok\r\n Super Boy 3 (KR)                               -       Ok\r\n Super Boy 4 (KR)                               -       Ok\r\n Super Bubble Bobble (KR)                       -       Ok\r\n Super Columns (KR)                             -       Ok\r\n Super Futebol II [Game Box Série Esportes] (BR)-       Ok\r\n Super Game 45 (KR)                             -       Ok\r\n Super Game 52 Hap (KR)                         -       Ok\r\n Super Game 150 (KR)                            -       Ok\r\n Super Game 180 (KR)                            -       Ok\r\n Super Game 200 (KR)                            -      *Ok\r\n Super Game 270 (KR)                            -      *Ok\r\n Super Game 270 Hap ~ Jaemissneun-270 (KR)      -      *Ok\r\n Super Game World 30 Hap [v0] (KR)              -       Ok\r\n Super Game World 30 Hap [v1] (KR)              -       Ok\r\n Super Game World 75 Hap (KR)                   -       Ok\r\n Super Game World 260 Hap (KR)                  -      *Ok\r\n Superman - The Man of Steel                    -       Ok\r\n Super Kick Off                                 -       Ok\r\n Super Monaco GP [v0]                           -       Ok\r\n Super Monaco GP [v1] (US)                      -       Ok\r\n Super Monaco GP [Proto 0]                      -       Ok\r\n Super Monaco GP [Proto 1]                      -       Ok\r\n Super Monaco GP [Proto 2] (US)                 -       Ok\r\n Super Monaco GP II (Ayrton Senna's)            -       Ok\r\n Super Multi Game - Super 75 in 1 (KR)          -       Ok\r\n Super Multi Game - Super 125 in 1 (KR)         -       Ok\r\n Super Off Road                                 -       Ok\r\n Super Off Road [Proto]                         -       Ok\r\n Super Penguin (KR)                             -       Ok\r\n Super Racing (JP)                              FM,(PAD)Ok\r\n Super Smash T.V.                               -       Ok\r\n Super Space Invaders                           -       Ok\r\n Super Tennis                                   -       Ok\r\n Super Tetris                                   -       Ok\r\n Super Wonder Boy Monster World (Super...) (JP) FM      Ok\r\n T2: The Arcade Game                            -       Ok\r\n Taito Chase H.Q.                               -       Ok\r\n Taito Chase H.Q. [Proto]                       -       Ok\r\n Tank Battalion (KR)                            -       Ok\r\n Taz in Escape From Mars (BR)                   -       Ok\r\n Taz-Mania                                      -       Ok\r\n Taz-Mania [Proto]                              -       Ok\r\n Tecmo World Cup '93                            -       Ok\r\n Tecmo World Cup '93 [Proto]                    -       Ok\r\n Teddy Boy                                      -       Ok\r\n Teddy Boy Blues (JP)                           -       Ok\r\n Teddy Boy Blues [EP-MyCard] (JP)               -       Ok\r\n Tennis Ace                                     FM      Ok\r\n Tensai Bakabon (JP)                            FM      Ok\r\n Terminator, The                                -       Ok\r\n Terminator, The (BR)                           -       Ok\r\n Terminator 2 - Judgment Day                    -       Ok\r\n Three Dragon Story, The (KR)                   -       Ok\r\n Thunder Blade                                  FM      Ok\r\n Thunder Blade (JP)                             FM      Ok\r\n Thunder Blade [Proto] (JP)                     FM      Ok\r\n Thunder Blade [HTH] [SMS-GG] (TW)              FM      Ok\r\n Time Soldiers                                  FM      Ok\r\n Tom and Jerry: The Movie                       -       Ok\r\n Tom and Jerry: The Movie [Proto]               -       Ok\r\n Toto World 3 (KR)                              -       Ok\r\n TransBot                                       -       Ok\r\n TransBot [Proto]                               -       Ok\r\n Trivial Pursuit - Genus Edition                -       Ok\r\n Ttoriui Moheom (KR)                            -       Ok\r\n Turma da Mônica em: O Resgate (BR)             FM/J    Ok\r\n TV Colosso (As Aventuras da) (BR)              -       Ok\r\n Ultima IV                                      FM      Ok\r\n Ultima IV [Proto]                              FM      Ok\r\n Ultimate Soccer                                -       Ok\r\n Vigilante                                      FM      Ok\r\n Virtua Fighter Animation                       -       Ok\r\n Walter Payton Football                         -       Ok\r\n Wanted                                         LP      Ok\r\n Where in the World is Carmen Sandiego?         -       Ok\r\n Where in the World is Carmen Sandiego? (BR)    -       Ok\r\n Wimbledon [v0] (BR) [Game Box Série Esportes]  -       Ok\r\n Wimbledon [v1]                                 -       Ok\r\n Wimbledon II                                   -       Ok\r\n Winter Olympics                                -       Ok\r\n Winter Olympics (BR)                           -       Ok\r\n Wolfchild                                      -       Ok\r\n Wonder Boy [v0]                                -       Ok\r\n Wonder Boy [v1]                                -       Ok\r\n Wonder Boy III: The Dragon's Trap              FM/J    Ok\r\n Wonder Boy in Monster Land                     FM      Ok\r\n Wonder Boy in Monster Land [Proto]             FM      Ok\r\n Wonder Boy in Monster World                    -       Ok\r\n Wonder Boy in Monster World [Proto]            -       Ok\r\n Wonsiin (KR)                                   -       Ok\r\n Woody Pop - Shinjinrui no Block Kuzushi (JP)   PAD     Ok\r\n Woody Pop (Super Arkanoid) (KR)                -       Ok\r\n World Class Leader Board                       -       Ok\r\n World Cup Italia '90                           -       Ok\r\n World Cup Italia '90 [Demo]                    -       Ok\r\n World Cup USA 94                               -       Ok\r\n World Games                                    -       Ok\r\n World Games [Proto]                            -       Ok\r\n World Grand Prix [v0]                          -       Ok\r\n World Grand Prix [v2]                          -       Ok\r\n World Grand Prix [Proto]                       -       Ok\r\n World Soccer                                   (SP)    Ok\r\n WWF WrestleMania Steel Cage Challenge          -       Ok\r\n X-Men: Mojo World (BR)                         -       Ok\r\n Xenon 2 - Megablast [Image Works]              -       Ok\r\n Xenon 2 - Megablast [Virgin]                   -       Ok\r\n Xenon 2 - Megablast [HTH] [SMS-GG] (TW)        -      *Ok\r\n Xyzolog (KR)                                   -       Ok\r\n Ys (JP)                                        FM      Ok\r\n Y's: The Vanished Omens                        -       Ok\r\n Y's: The Vanished Omens [Demo]                 FM      Ok\r\n Zaxxon 3-D / Zaxxon 3D                         FM,(3D) Ok\r\n Zaxxon 3-D / Zaxxon 3D [Proto]                 (3D)    Ok\r\n Zemina 4-in-1 (Q-Bert, Sports 3, Gulkave..)(KR)-       Ok\r\n Zemina Best 25 (KR)                            -       Ok\r\n Zemina Best 39 (KR)                            -       Ok\r\n Zemina Best 88 (KR)                            -       Ok\r\n Zillion [v0] / Akai Koudan Zillion             -       Ok\r\n Zillion [v1]                                   -       Ok\r\n Zillion [v2]                                   -       Ok\r\n Zillion II: The Tri Formation / Tri Formation  FM      Ok\r\n Zillion II: The Tri Formation [Proto]          FM      Ok\r\n Zool                                           -       Ok\r\n-----------------------------------------------------------------------------\r\n 666 games tested - 659 are \"Ok\"\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA MASTER SYSTEM (SMS) BIOS IMAGES\r\n-----------------------------------------------------------------------------\r\n Note: the games/animations works properly, but full BIOS behavior is not\r\n emulated. It is not necessary for gaming purpose.\r\n-----------------------------------------------------------------------------\r\n Alex Kidd in Miracle World [BIOS]              -       Ok\r\n Alex Kidd in Miracle World [BIOS] (KR)         -       Ok\r\n Hang On [BIOS]                                 -       Ok\r\n Hang On / Safari Hunt [BIOS]                   LP      Ok\r\n Missile Defense 3-D [BIOS]                     LP,3D   Ok\r\n Sonic The Hedgehog [BIOS]                      -       Ok\r\n SMS (v1.3) [BIOS]                              -       Ok\r\n SMS (v2.0) [BIOS]                              -       Ok\r\n SMS Japanese (v2.1) [BIOS]                     FM      Ok\r\n SMS Prototype (M404) [BIOS]                    -       Ok\r\n SMS Prototype (v1.0) [BIOS]                    -       Ok\r\n SMS Store Display Unit [BIOS]                  KIOSK   Kiosk not emulated.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA GAME 1000 (SG-1000) COMPATIBILITY LIST\r\n-----------------------------------------------------------------------------\r\n Note: (JP) flags are not marked there unless when there's several version.\r\n All SG-1000 games were originally released in Japan.\r\n-----------------------------------------------------------------------------\r\n Adventure Island [DahJee] (TW)                 Ok\r\n Bank Panic                                     Ok\r\n Bank Panic (TW)                                Ok\r\n Black Onyx, The                                Ok\r\n Bomberman Special (TW)                         Ok\r\n Bomberman Special [DahJee] (TW)                Ok\r\n Bomb Jack                                      Ok\r\n Bomb Jack [chinese logo] (TW)                  Ok\r\n Bomb Jack [english logo] (TW)                  Ok\r\n Bomb Jack [english logo] (KR)                  Ok\r\n Bomb Jack [korean logo] (KR)                   Ok\r\n Borderline                                     Ok\r\n Cabbage Patch Kids (TW)                        Ok\r\n Castle, The                                    Ok\r\n Castle, The [MSX] (TW)                         Ok\r\n Chack'n Pop                                    Ok\r\n Chack'n Pop (TW)                               Ok\r\n Champion Baseball                              Ok\r\n Champion Baseball (TW)                         Ok\r\n Champion Baseball [40k map]                    Ok\r\n Champion Billiards                             Ok\r\n Champion Billiards (TW)                        Ok\r\n Champion Boxing [v0]                           Ok\r\n Champion Boxing [v0] (TW)                      Ok\r\n Champion Boxing [v1]                           Ok\r\n Champion Golf [v0]                             Ok\r\n Champion Golf [v0] (KR)                        Ok\r\n Champion Golf [v1]                             Ok\r\n Champion Ice Hockey                            Ok\r\n Champion Ice Hockey (KR)                       Ok\r\n Champion Ice Hockey (TW)                       Ok\r\n Champion Kendou                                Ok\r\n Champion Kendou (TW)                           Ok\r\n Champion Pro Wrestling                         Ok\r\n Champion Soccer                                Ok\r\n Champion Soccer (TW)                           Ok\r\n Champion Tennis                                Ok\r\n Championship Lode Runner                       Ok (can't write to tape)\r\n Championship Lode Runner [chinese logo] (TW)   Ok (can't write to tape)\r\n Championship Lode Runner [english logo] (TW)   Ok (can't write to tape)\r\n Choplifter                                     Ok\r\n Choplifter (KR)                                Ok\r\n Choplifter [Proto]                             Ok\r\n Choplifter [chinese logo] (TW)                 Ok\r\n Choplifter [english logo] (TW)                 Ok\r\n Choplifter [no logo] (TW)                      Ok\r\n Circus Charlie (KR)                            Ok\r\n Circus Charlie (TW)                            Ok\r\n Congo Bongo [v0] (JP)                          Ok\r\n Congo Bongo [v1]                               Ok\r\n Congo Bongo [v1] (TW)                          Ok\r\n Congo Bongo [v1] [40k map]                     Ok\r\n C_So!                                          Ok (can't write to tape)\r\n C_So! (TW)                                     Ok (can't write to tape)\r\n Doki Doki Penguin Land                         Ok\r\n Doki Doki Penguin Land (TW)                    Ok\r\n Dragon Wang [v0]                               Ok\r\n Dragon Wang [v0] [chinese logo] (TW)           Ok\r\n Dragon Wang [v0] [english logo] (TW)           Ok\r\n Dragon Wang [v1] (JP)                          Ok\r\n Drol                                           Ok\r\n Drol (KR)                                      Ok\r\n Drol (TW)                                      Ok\r\n Elevator Action                                Ok\r\n Elevator Action (TW)                           Ok\r\n Exerion                                        Ok\r\n Exerion (KR)                                   Ok\r\n Exerion (TW)                                   Ok\r\n Flicky [v0]                                    Ok\r\n Flicky [v1]                                    Ok\r\n Flicky [v1] (TW)                               Ok\r\n Girl's Garden                                  Ok\r\n Girl's Garden (TW)                             Ok\r\n Golgo 13                                       Ok\r\n Goonies, The [DahJee] (TW)                     Ok\r\n GP World [v0]                                  Ok\r\n GP World [v1]                                  Ok\r\n Gulkave                                        Ok\r\n Gulkave (KR)                                   Ok\r\n Hang On II                                     Ok\r\n Hang On II [chinese logo] (TW)                 Ok\r\n Hang On II [english logo] (TW)                 Ok\r\n H.E.R.O.                                       Ok\r\n H.E.R.O. [chinese logo] (TW)                   Ok\r\n H.E.R.O. [english logo] (TW)                   Ok\r\n Home Mahjong [v0]                              Ok\r\n Home Mahjong [v1]                              Ok\r\n Home Mahjong [v1] (TW)                         Ok\r\n Hustle Chumy                                   Ok\r\n Hustle Chumy (TW)                              Ok\r\n Hyper Sports (Konami no)                       Ok\r\n Hyper Sports (Konami no) (KR)                  Ok\r\n Hyper Sports (Konami no) (TW)                  Ok\r\n Hyper Sports 2 (TW)                            Ok\r\n King's Valley (TW)                             Ok\r\n Knightmare [Jumbo] (TW)                        Ok\r\n Legend of Kage, The [DahJee] (TW)              Ok\r\n Lode Runner                                    Ok\r\n Lode Runner (KR)                               Ok\r\n Lode Runner (TW)                               Ok\r\n Magical Kid Wiz (TW)                           Ok\r\n Magical Tree (TW)                              Ok\r\n Mahjong [big 1983]                             Ok\r\n Mahjong [small 1983]                           Ok\r\n Mahjong (TW)                                   Ok\r\n Monaco GP [24k] [v0] [40k map]                 Ok\r\n Monaco GP [32k] [v1]                           Ok\r\n Monaco GP [32k] [v1] (TW)                      Ok\r\n Monaco GP [32k] [v2]                           Ok\r\n N-Sub                                          Ok\r\n N-Sub [1988]                                   Ok\r\n N-Sub [40k map]                                Ok\r\n N-Sub (TW)                                     Ok\r\n Ninja Princess                                 Ok\r\n Ninja Princess (TW)                            Ok\r\n Orguss                                         Ok\r\n Orguss (TW)                                    Ok\r\n Othello                                        Ok\r\n Othello (TW)                                   Ok\r\n Pacar                                          Ok\r\n Pacar [40k map]                                Ok\r\n Pacar (TW)                                     Ok\r\n Pachinko                                       Ok\r\n Pachinko II                                    Ok\r\n Pachinko II (TW)                               Ok\r\n Pac-Man [DahJee] (TW)                         *Ok\r\n Ping Pong (Konami's) (TW)                      Ok\r\n Pippols [Jumbo] (TW)                           Ok\r\n Pitfall II ~The Lost Caverns~ [v0]             Ok\r\n Pitfall II ~The Lost Caverns~ [v0] [chin..(TW) Ok\r\n Pitfall II ~The Lost Caverns~ [v0] [engl..(TW) Ok\r\n Pitfall II ~The Lost Caverns~ [v1]             Ok\r\n Pop Flamer                                     Ok\r\n Pop Flamer (TW)                                Ok\r\n Rally-X (TW)                                   Ok\r\n Rally-X [DahJee] (TW)                          Ok\r\n Road Fighter (TW)                              Ok\r\n Road Fighter [Jumbo] (TW)                      Ok\r\n Rock n' Bolt                                   Ok\r\n Rock n' Bolt [chinese logo] (TW)               Ok\r\n Rock n' Bolt [english logo] (TW)               Ok\r\n Safari Hunting                                 Ok\r\n Safari Hunting (TW)                            Ok\r\n Safari Race                                    Ok\r\n Safari Race (TW)                               Ok\r\n Safari Race [1988]                             Ok\r\n Sega Flipper                                   Ok\r\n Sega Flipper (TW)                              Ok\r\n Sega Flipper [40k map]                         Ok\r\n Sega-Galaga                                    Ok\r\n Sega-Galaga (TW)                               Ok\r\n Sega-Galaga [40k map]                          Ok\r\n Serizawa Hachidan no Tsumeshogi                Ok\r\n SG-1000 M2 Check Program [Proto]               Ok\r\n Shinnyuushain Tooru-Kun (Konami no)            Ok\r\n Shinnyuushain Tooru-Kun (Konami no) (TW)       Ok\r\n Sindbad Mystery                                Ok\r\n Sindbad Mystery (TW)                           Ok\r\n Soukoban                                       Ok\r\n Soukoban (KR)                                  Ok\r\n Soukoban [IQ logo] (KR)                        Ok\r\n Soukoban (TW)                                  Ok\r\n Space Invaders                                 Ok\r\n Space Invaders (TW)                            Ok\r\n Space Slalom                                   Ok\r\n Star Force                                     Ok\r\n Star Force [A] (TW)                            Ok\r\n Star Force [B] (TW)                            Ok\r\n Star Force (KR)                                Ok\r\n Star Jacker [v0] (JP)                          Ok\r\n Star Jacker [v1]                               Ok\r\n Star Jacker [v1] (TW)                          Ok\r\n Star Jacker [v2]                               Ok\r\n Star Soldier [DahJee] (TW)                     Ok\r\n Super Tank                                     Ok\r\n Super Tank (KR)                                Ok\r\n Super Tank (TW)                                Ok\r\n Tank Battalion [DahJee] (TW)                   Ok\r\n Terebi Oekaki Graphic Software                 Ok (uses Sega Graphic Board)\r\n TwinBee [Jumbo] (TW)                           Ok\r\n Wonder Boy [v0]                                Ok\r\n Wonder Boy [v1]                                Ok\r\n Wonder Boy [v1] (TW)                           Ok\r\n Yamato                                         Ok\r\n Yamato [40k map]                               Ok\r\n Yamato (TW)                                    Ok\r\n Yie Ar Kung-Fu (TW)                            Ok\r\n Yie Ar Kung-Fu II (TW)                         Ok\r\n Zanac [DahJee] (TW)                            Ok\r\n Zaxxon                                         Ok\r\n Zaxxon (TW)                                    Ok\r\n Zippy Race                                     Ok\r\n Zippy Race (TW)                                Ok\r\n Zoom 909                                       Ok\r\n Zoom 909 (TW)                                  Ok\r\n-----------------------------------------------------------------------------\r\n 195 games tested - 195 are \"Ok\"\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n OTHELLO MULTIVISION COMPATIBILITY LIST\r\n-----------------------------------------------------------------------------\r\n 007 James Bond [v2.6] [40k map]                Ok\r\n 007 James Bond [v2.7]                          Ok\r\n 007 James Bond [v2.7] (TW)                     Ok\r\n Challenge Derby [A]                            Ok\r\n Challenge Derby [A] [40k map]                  Ok\r\n Challenge Derby [B] [40k map]                  Ok\r\n Guzzler                                        Ok\r\n Guzzler (TW)                                   Ok\r\n Okamoto Ayako no Match Play Golf [A]           Ok\r\n Okamoto Ayako no Match Play Golf [B]           Ok\r\n Okamoto Ayako no Match Play Golf [B] (TW)      Ok\r\n Othello Multivision [BIOS]                     Keyboard not emulated.\r\n Q*bert                                         Ok\r\n San-nin Mahjong                                Ok\r\n San-nin Mahjong [40k map]                      Ok\r\n San-nin Mahjong (TW)                           Ok\r\n Space Armor [v1.0] [v0] [40k map]              Ok\r\n Space Armor [v2.0] [v1]                        Ok\r\n Space Armor [v2.0] [v1] (TW)                   Ok\r\n Space Armor [v2.0] [v2]                        Ok\r\n Space Mountain                                 Ok\r\n-----------------------------------------------------------------------------\r\n  21 games tested - 20 are \"Ok\"\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA COMPUTER 3000 (SC-3000) COMPATIBILITY LIST\r\n-----------------------------------------------------------------------------\r\n Note: (JP) flags are not marked there unless when there's several version.\r\n All SC-3000 cartridge software were originally released in Japan.\r\n-----------------------------------------------------------------------------\r\n Basic Level II [v1.0] (JP)                                     Ok (can't write to tape)\r\n Basic Level II [v1.0b] (JP)                                    Ok (can't write to tape)\r\n Basic Level II [v1.0] (PAL)                                    Ok (can't write to tape)\r\n Basic Level III [v1.0] (JP)                                    Ok (can't write to tape)\r\n Basic Level III [v1.1] (JP)                                    Ok (can't write to tape)\r\n Basic Level III [v1.0] (PAL)                                   Ok (can't write to tape)\r\n Home Basic (JP)                                                Ok (can't write to tape)\r\n-----------------------------------------------------------------------------\r\n Chuugaku Hisshuu Eibunpou (Chuugaku 1-Nen)             E-105   Ok\r\n Chuugaku Hisshuu Eibunpou (Chuugaku 2-Nen)             E-112   Ok\r\n Chuugaku Hisshuu Eisakubun (Chuugaku 1-Nen)            E-104   Ok\r\n Chuugaku Hisshuu Eisakubun (Chuugaku 1-Nen) [40k map]  E-104   Ok\r\n Chuugaku Hisshuu Eisakubun (Chuugaku 2-Nen)            E-111   Ok\r\n Chuugaku Hisshuu Eisakubun (Chuugaku 2-Nen) [40k map]  E-111   Ok\r\n Chuugaku Hisshuu Eitango (Chuugaku 1-Nen)              E-103   Ok\r\n Chuugaku Hisshuu Eitango (Chuugaku 2-Nen)              E-110   Ok\r\n Chuugaku Hisshuu Eitango (Chuugaku 2-Nen) [40k map]    E-110   Ok\r\n Kagaku (Gensokigou Master)                             E-107   Ok\r\n Music                                                  E-101   Ok (can't write to tape)\r\n Music (JP)                                             E-101   Ok (can't write to tape)\r\n Nihonshi Nenpyou                                       E-108   Ok\r\n Sekaishi Nenpyou                                       E-109   Ok\r\n Tanoshii Sansuu (Shougaku 4-Nen Ge)                    E-113   Ok\r\n Tanoshii Sansuu (Shougaku 4-Nen Jou)                   E-106   Ok\r\n Tanoshii Sansuu (Shougaku 4-Nen Jou) [40k map]         E-106   Ok\r\n Tanoshii Sansuu (Shougaku 5-Nen Ge)                    E-114   Ok\r\n Tanoshii Sansuu (Shougaku 5-Nen Jou)                   E-116   Ok\r\n Tanoshii Sansuu (Shougaku 6-Nen Ge)                    E-115   Ok\r\n Tanoshii Sansuu (Shougaku 6-Nen Jou)                   E-117   Ok\r\n Uranai Angel Cutie                                     E-119   Ok\r\n-----------------------------------------------------------------------------\r\n John Sands Micromodem cartridges (AU)\r\n-----------------------------------------------------------------------------\r\n AutoCom [Build 3] [v1.1c] [Proto]                      SC0460  Micromodem 4 is not emulated.\r\n AutoCom [Build 4] [v1.1c] [Proto]                      SC0460  Micromodem 4 is not emulated.\r\n AutoCom [Build 5] [v1.1c] [Proto]                      SC0460  Micromodem 4 is not emulated.\r\n AutoCom [Build 6] [v2.0c] [Proto]                      SC0460  Micromodem 4 is not emulated.\r\n AutoCom [Build 7] [v2.0c] [Proto]                      SC0460  Micromodem 4 is not emulated.\r\n AutoCom [Build 8] [v2.0(T)c] [Proto]                   SC0460  Micromodem 4 is not emulated.\r\n SegaCom [Build 0] [Proto]                              SC0430  Micromodem 3 is not emulated.\r\n SegaCom [Build 1] [v1.0c]\t\t\t\t\t\t\t    SC0430  Micromodem 3 is not emulated.\r\n SegaCom [Build 2] [v1.1c]\t\t\t\t\t            SC0430  Micromodem 3 is not emulated.\r\n-----------------------------------------------------------------------------\r\n  35 roms tested - 26 are \"Ok\"\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SUPER CONTROL STATION (SF-7000) COMPATIBILITY LIST\r\n-----------------------------------------------------------------------------\r\n Note:\r\n  Disk writing is not yet well supported, and modified disks are not saved.\r\n  Some of the software are known not to function even on a real system, so\r\n  it's difficult to establish a good compatibility list.\r\n-----------------------------------------------------------------------------\r\n Complete Arcade Pack Collection, The (NZ)          Ok\r\n Crocky (FR)                                        Bad Dump\r\n Kamikaze  (FR)                                     Ok\r\n HuCAL                                              Ok (can't write to disk / cassette)\r\n Sega Disk Basic v1.0p                              Ok (can't write to disk / cassette)\r\n Sega Logo v1.0e                                    Ok (can't write to disk / cassette)\r\n Poseidon Wars / Space Panic / Rambo (FR)           Ok (Rambo isn't finished)\r\n Yeno Draw (FR)                                     Ok\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA GAME GEAR (GG) COMPATIBILITY LIST\r\n-----------------------------------------------------------------------------\r\n 5 in One Fun Pak                                   Ok\r\n Aah! Harimanada (JP)                               Ok\r\n Addams Family, The                                 Ok\r\n Adventures of Batman & Robin, The                  Flickering status (LCD persistance).\r\n Aerial Assault [v0]                                Ok\r\n Aerial Assault [v1] (JP)                           Ok\r\n Aladdin (Disney's)                                 Ok\r\n Aladdin (Disney's) (JP)                            Ok\r\n Alien 3                                            Ok\r\n Alien 3 (JP)                                       Ok\r\n Alien Syndrome                                     Ok\r\n Alien Syndrome (JP)                                Ok\r\n Andre Agassi Tennis                                Ok\r\n Andre Agassi Tennis [Proto]                        Ok\r\n Arcade Classics                                    Ok\r\n Arch Rivals                                        Ok\r\n Arena - Maze of Death / Arena                      Ok\r\n Ariel - The Little Mermaid (Disney's)              Ok\r\n Arliel - Crystal Densetsu (JP)                     Ok\r\n Astérix and the Great Rescue                       Ok\r\n Astérix and the Great Rescue (US)                  Ok\r\n Astérix and the Secret Mission                     Ok\r\n Ax Battler - A Legend of Golden Axe [v1.5] (JP)    Ok\r\n Ax Battler - A Legend of Golden Axe [v2.0] [Proto] Ok\r\n Ax Battler - A Legend of Golden Axe [v2.4]         Ok\r\n Baku Baku                                          Ok\r\n Baku Baku (US)                                     Ok\r\n Baku Baku Animal - Sekai Shiikugakari Senshu..(JP) Ok\r\n Barbie Super Model [Proto]                         Ok\r\n Bart vs. The Space Mutants (The Simpsons)          Ok\r\n Bart vs. The World (The Simpsons) / Bart World     Ok\r\n Bartman meets Radioactive Man (The Simpsons)       Ok\r\n Batman Forever                                     Ok\r\n Batman Returns                                     Ok\r\n Batter Up                                          Ok\r\n Battleship - The classic naval combat game         Ok\r\n Battletoads                                        Ok\r\n Battletoads (US)                                   Ok\r\n Beavis and Butt-Head (MTV's)                       Ok\r\n Beavis and Butt-Head (MTV's) [Proto]               Ok\r\n Berenstain Bears' Camping Adventure, The           Ok\r\n Berlin no Kabe - The BerlinWall (JP)               Ok\r\n Bishoujo Senshi Sailor Moon S (JP)                 Ok\r\n BreakThru! [Proto]                                 Ok (game does NOT run neither on real hardware, hence \"Ok\". Switching to PAL gets it to run)\r\n BreakThru! [Proto] [Patched]                       Ok\r\n Bonkers Wax Up! (Disney's)                         Ok\r\n Bubble Bobble                                      Ok\r\n Bubble Bobble [Proto]                              Ok\r\n Bugs Bunny in Double Trouble                       Ok\r\n Bust a Move                                        Ok\r\n Buster Ball                                        Ok\r\n Buster Fight                                       Ok\r\n Caesars Palace                                     Ok\r\n Captain America and The Avengers                   Ok\r\n Car Licence (JP)                                   Ok\r\n Casino FunPak                                      Ok\r\n Castle of Illusion - Starring Mickey Mouse [SMS-GG]Ok\r\n Castle of Illusion - Starring Mick.. [SMS-GG] (JP) Ok\r\n Cave Dude [Proto] [SMS-GG]                         Ok\r\n Chakan                                             Ok\r\n Championship Hockey                                Ok\r\n Cheese Cat-astrophe - Starring Speedy Gonzales     Ok\r\n Chessmaster                                        Ok\r\n Chicago Syndicate                                  Ok\r\n Chicago Syndicate [Proto] [1995-03-20]             Ok (Empire Syndicate)\r\n Choplifter III                                     Ok\r\n Chuck Rock                                         Ok\r\n Chuck Rock [Proto]                                 Ok\r\n Chuck Rock II: Son of Chuck                        Ok\r\n Chuck Rock II: Son of Chuck (US)                   Ok\r\n CJ Elephant Fugitive                               Ok\r\n CJ Elephant Fugitive [Proto]                       Ok\r\n Cliffhanger                                        Ok\r\n Clutch Hitter                                      Ok\r\n Coca Cola Kid                                      Ok\r\n Columns [v0] (JP)                                  Ok\r\n Columns [v1] (JP)                                  Ok\r\n Columns [v2]                                       Ok\r\n Cool Spot                                          Ok\r\n Cool Spot (US)                                     Ok\r\n Cosmic Spacehead                                   Ok\r\n Crayon Shin-chan - Taiketsu! Tankam Panic!! (JP)   Ok\r\n Crazy Faces [Proto]                                Ok\r\n Crystal Warriors                                   Ok\r\n Cutthroat Island                                   Ok\r\n Cutthroat Island [Proto]                           Ok\r\n Daffy Duck in Hollywood                            Ok\r\n David Robinson's Supreme Court [Demo] [Proto]      Ok\r\n Deep Duck Trouble - Starring Donald Duck           Ok\r\n Defenders of Oasis                                 Ok\r\n Defenders of Oasis [Proto]                         Ok\r\n Desert Speedtrap - Starring Road Runner and Wile.. Ok\r\n Desert Speedtrap - Starring Road Runner.. (US,BR)  Ok\r\n Desert Strike (EU)                                 Ok\r\n Desert Strike: Return to the Gulf (US)             Ok\r\n Devilish                                           Ok\r\n Devilish (US)                                      Ok\r\n Devilish (JP)                                      Ok\r\n Dinobasher - Starring Bignose the Caveman [Proto]  Ok\r\n Donald Duck no Lucky Dime (JP)                     Ok\r\n Donald Duck no Yottsu no Hihou (JP)                Ok\r\n Donald no Magical World (Ronald in the Magic.. (JP)Ok\r\n Doraemon Waku Waku Pocket Paradise (JP)            Ok\r\n Double Dragon / Double Dragon - The Revenge of B.. Ok\r\n Double Dragon [Proto]                              Ok\r\n Dr. Franken [Demo]                                 Ok\r\n Dr. Robotnik's Mean Bean Machine                   Ok\r\n Dracula (Bram Stoker's)                            Ok\r\n Dracula (Bram Stoker's) (US)                       Ok\r\n Dragon Crystal                                     Ok\r\n Dragon Crystal - Tsurani no Meikyuu (JP)           Ok\r\n Dragon: The Bruce Lee Story                        Ok\r\n Dragon: The Bruce Lee Story (US)                   Ok\r\n Dragon: The Bruce Lee Story [Proto]                Ok\r\n Dropzone (Archer MacLean's)                        Ok\r\n Dunk Kids (JP)                                     Ok\r\n Dynamite Headdy                                    Ok\r\n Dynamite Headdy (JP)                               Ok\r\n Dynamite Headdy [Proto]                            Ok\r\n Earthworm Jim                                      Ok\r\n Earthworm Jim (US)                                 Ok\r\n Ecco the Dolphin                                   Ok\r\n Ecco the Dolphin (JP)                              Ok\r\n Ecco the Dolphin II (JP)                           Ok\r\n Ecco - The Tides of Time                           Ok\r\n Ernie Els Golf                                     Ok\r\n Eternal Legend (JP)                                Ok\r\n Evander Holyfield's \"Real Deal\" Boxing             Ok\r\n Excellent Dizzy Collection, The [SMS-GG]           Ok\r\n F1 / Formula One                                   Ok\r\n F1 - World Championship Edition                    Ok\r\n F-15 Strike Eagle                                  Ok\r\n Face Ball 2000 (JP)                                Ok\r\n Factory Panic                                      Ok\r\n Fantastic Dizzy [SMS-GG]                           Minor graphic bug when pausing.\r\n Fantasy Zone / Fantasy Zone Gear - Opa Opa Jr. no..Ok\r\n Fantasy Zone (US)                                  Ok\r\n Fatal Fury Special                                 Ok\r\n Fatal Fury Special (US)                            Ok\r\n FIFA International Soccer                          Ok\r\n FIFA International Soccer (JP)                     Ok\r\n FIFA Soccer 96                                     Ok\r\n Foreman for Real                                   Ok\r\n Frank Thomas Big Hurt Baseball                     Ok\r\n Fray ~Shugyou hen~ (JP)                            Ok\r\n Fred Couples Golf                                  Ok\r\n Fred Couples Golf (JP)                             Ok\r\n Frogger [Proto]                                    Ok\r\n Galaga 2                                           Ok\r\n Galaga '91 (JP)                                    Ok\r\n Gamble Panic (JP)                                  Ok\r\n Gambler Jikochuushin Ha (JP)                       Ok\r\n Garou Densetsu Special (JP)                        Ok\r\n Ganbare Gorby! (JP)                                Ok\r\n Garfield: Caught in the Act                        Ok\r\n Gear Stadium (JP)                                  Ok\r\n Gear Stadium Heiseiban (JP)                        Ok\r\n Gear Works                                         Ok\r\n George Foreman's KO Boxing                         Ok\r\n GG Aleste (JP)                                     Ok\r\n GG Doraemon Nora no Suke no Yabou (JP)             Ok\r\n GG Portrait - Pai Chen (JP)                        Ok\r\n GG Portrait - Yuuki Akira (JP)                     Ok\r\n GG Shinobi, The (JP)                               Ok\r\n Global Gladiators                                  Ok\r\n Global Golf [Proto]                                Ok\r\n G-LOC - Air Battle                                 Ok\r\n G-LOC - Air Battle [v0] (JP)                       Ok\r\n G-LOC - Air Battle [v1] (JP)                       Ok\r\n Godzilla - Kaijuu Daishingeki (JP)                 Ok\r\n GP Rider                                           Ok\r\n GP Rider (JP)                                      Ok\r\n Greendog - The Beached Surfer Dude!                Ok\r\n Griffin (JP)                                       Ok\r\n Gunstar Heroes (JP)                                Ok\r\n Honoo no Toukyuuji Dodge Danpei (JP)               Ok\r\n Halley Wars                                        Flickering Status (LCD persistance).\r\n Halley Wars (JP)                                   Flickering Status (LCD persistance).\r\n Head Buster (JP)                                   Ok\r\n Heavy weight Champ (JP)                            Ok\r\n Home Alone                                         Ok\r\n Hook (EU)                                          Ok\r\n Hook (US)                                          Ok\r\n Tarot no Yakata / House of Tarot (JP)              Ok\r\n Hurricanes                                         Ok\r\n Hyokkori Hyoutan Jima - Hyoutan Jima no Dai.. (JP) Ok\r\n Hyper Chou Pro Yakyuu '92 (JP)                     Ok\r\n Ichidant~R GG (Puzzle & Action)                    Ok\r\n Incredible Crash Dummies, The                      Ok\r\n Incredible Hulk, The                               Ok\r\n Indiana Jones and the Last Crusade                 Ok\r\n In the Wake of Vampire (JP)                        Ok\r\n Iron Man X-O Manowar in Heavy Metal                Ok\r\n Itchy & Scratchy Game, The                         Ok\r\n James Bond 007: The Duel                           Ok\r\n James Bond 007: The Duel [Proto]                   Ok\r\n James Pond II - Codename: RoboCod                  Ok\r\n James Pond II - Codename: RoboCod (US)             Ok\r\n Jang Pung II [SMS-GG] (KR)                         Ok\r\n Jeopardy!                                          Ok\r\n Jeopardy! [Proto]                                  Ok\r\n Jeopardy! - Sports Edition                         Ok\r\n J League GG Pro Striker '94 (JP)                   Ok\r\n J League Soccer Dream Eleven (JP)                  Ok\r\n Joe Montana Football [v0]                          Ok\r\n Joe Montana Football [v1]                          Ok\r\n Judge Dredd                                        Ok\r\n Junction (JP)                                      Ok\r\n Junction (US)                                      Ok\r\n Jungle Book, The (Walt Disney's Classic)           Ok\r\n Jungle Book, The (Walt Disney's) (US)              Ok\r\n Jungle Strike (US)                                 Ok\r\n Jurassic Park                                      Ok\r\n Jurassic Park (JP)                                 Ok\r\n Kaitou Saint Tail (JP)                             Ok\r\n Kawasaki Superbike Challenge / Kawasaki Superbikes Ok\r\n Kawasaki Superbike Challenge (US)                  Ok\r\n Kenyuu Densetsu Yaiba (JP)                         Ok\r\n Kick & Rush (JP)                                   Ok\r\n Kinetic Connection (JP)                            Ok\r\n Kishin Douji Zenki (JP)                            Ok\r\n KLAX                                               Ok\r\n Krusty's Fun House                                 Ok\r\n Kuni Chan no Game Tengoku (JP)                     Ok\r\n Kuni Chan no Game Tengoku Part 2 (JP)              Ok\r\n Land of Illusion - Starring Mickey Mouse           Ok\r\n Last Action Hero                                   Ok\r\n Legend of Illusion                                 Ok\r\n Lemmings                                           Ok\r\n Lemmings [Proto]                                   Ok\r\n Lemmings 2: The Tribes [Proto]                     Ok\r\n Lion King, The (Disney's) (EU)                     Ok\r\n Lion King, The (Disney's) (US)                     Ok\r\n Lion King, The (Disney's) (JP)                     Ok\r\n Lost World: Jurassic Park, The                     Ok\r\n Lucky Dime Caper, The                              Ok\r\n Lunar - Sanpo-suru Gakuen (JP)                     Ok\r\n Madden NFL 95                                      Ok\r\n Madden 96                                          Ok\r\n Madoh Monogatari I - Mittsu no Madoukyuu (JP)      Ok\r\n Madoh Monogatari II - Aruru 16-sai (JP)            Ok\r\n Madoh Monogatari III - Kyuukyoku Joou.. [v0] (JP)  Ok\r\n Madoh Monogatari III - Kyuukyoku Joou.. [v1] (JP)  Ok\r\n Madoh Monogatari III - Kyuukyoku Jo.. [Proto] (JP) Ok\r\n Madoh Monogatari A - Doki Doki Vacation (JP)       Ok\r\n Magic Knight Ray Earth (JP)                        Ok\r\n Magic Knight Ray Earth 2 ~making of magic k.. (JP) Ok\r\n Magical Puzzle Popils (JP)                         Ok\r\n Magical Taruruuto-kun (JP)                         Ok\r\n Majors Pro Baseball, The                           Ok\r\n Man Overboard!                                     Ok\r\n Mappy (JP)                                         Ok\r\n Marble Madness                                     Ok\r\n Marko's Magic Football                             Ok\r\n Master of Darkness                                 Ok\r\n Megaman                                            Ok\r\n Megami Tensei Gaiden: Last Bible (JP)              Ok\r\n Megami Tensei Gaiden: Last Bible Special (JP)      Ok\r\n Mickey Mouse Densetsu no Oukoku (JP)               Ok\r\n Mickey Mouse no Mahou no Crystal (JP)              Ok\r\n Mickey's Ultimate Challenge                        Ok\r\n Micro Machines                                     Ok\r\n Micro Machines [Proto]                             Ok\r\n Micro Machines 2: Turbo Tournament                 Ok\r\n Mighty Morphin Power Rangers                       Ok\r\n Mighty Morphin Power Rangers: The Movie            Ok\r\n MLBPA Baseball                                     Flickering Status (LCD Persistance).\r\n Moldorian ~Hikari to Yami no Shisutaa~ (JP)        Ok\r\n Monster Truck Wars                                 Ok\r\n Monster World II - Dragon no Wana (JP)             Ok\r\n Mortal Kombat                                      Ok\r\n Mortal Kombat - Shinken Kourin Densetsu (JP)       Ok\r\n Mortal Kombat [Proto]                              Ok\r\n Mortal Kombat II / Mortal Kombat II - Kyukyoku S.. Ok\r\n Mortal Kombat 3                                    Ok\r\n Ms. Pac-Man                                        Ok\r\n Nazo Puyo [v0] (JP)                                Ok\r\n Nazo Puyo [v1] (JP)                                Ok\r\n Nazo Puyo 2 (JP)                                   Ok\r\n Nazo Puyo Aruru no Ruu (JP)                        Ok\r\n Nazo Puyo Aruru no Ruu [Editor Proto] (JP)         Ok\r\n NBA Action - Starring David Robinson               Ok\r\n NBA Jam                                            Ok\r\n NBA Jam (JP)                                       Ok\r\n NBA Jam Tournament Edition                         Ok\r\n Neko Dai Suki! (JP)                                Ok\r\n NFL '95                                            Ok\r\n NFL Quarterback Club                               Ok\r\n NFL Quarterback Club 96                            Ok\r\n NHL All Star Hockey                                Ok\r\n NHL Hockey                                         Ok\r\n Ninja Gaiden                                       Ok\r\n Ninja Gaiden (JP)                                  Ok\r\n Ninkuu (JP)                                        Ok\r\n Ninkuu 2 ~Tenkuuryuu-e no Michi~ (JP)              Ok\r\n Ninkuu Gaiden - Hiroyuki Daikatsugeki (JP)         Ok\r\n Nomo's World Series Baseball / Nomo Hideo no..(JP) Ok\r\n Off The Wall [Proto]                               Ok\r\n Olympic Gold [v0] [SMS-GG]                         Ok\r\n Olympic Gold [v0] [SMS-GG] (TW)                    Ok\r\n Olympic Gold [v1] [SMS-GG]                         Ok\r\n Operation Starfi5h                                 Ok\r\n Ottifants, The                                     Ok\r\n Out Run                                            Ok\r\n Out Run (JP)                                       Ok\r\n Out Run Europa [SMS-GG]                            Ok\r\n Out Run Europa [SMS-GG] (US)                       Ok\r\n Pac-Attack                                         Ok\r\n Pac-In-Time [Proto]                                Ok\r\n Pac-Man                                            Ok\r\n Pac-Man (JP)                                       Ok\r\n Panzer Dragoon Mini (JP)                           Ok\r\n Paperboy                                           Ok\r\n Paperboy 2                                         Ok\r\n Paperboy 2 [Proto]                                 Ok\r\n Pengo                                              Ok\r\n Pengo (JP)                                         Ok\r\n Pet Club Inu Dai Suki! (JP)                        Ok\r\n Pete Sampras Tennis                                Ok\r\n Pete Sampras Tennis (US)                           Ok\r\n PGA TOUR Golf                                      Ok\r\n PGA TOUR Golf II                                   Ok\r\n PGA TOUR 96                                        Ok\r\n Phantasy Star Adventure (JP)                       Ok\r\n Phantasy Star Gaiden (JP)                          Ok\r\n Phantom 2040                                       Ok\r\n Pinball Dreams                                     Ok\r\n Pocket Jansou (JP)                                 Ok\r\n Poker Face Paul's Blackjack                        Ok\r\n Poker Face Paul's Cribbage [Proto]                 Ok\r\n Poker Face Paul's Gin                              Ok\r\n Poker Face Paul's Poker                            Ok\r\n Poker Face Paul's Solitaire                        Ok\r\n Pop Breaker (JP)                                   Ok\r\n Popeye's Beach Volleyball (JP)                     Ok\r\n Power Drive                                        Flickering parts (using LCD Persistance).\r\n Power Strike II / GG Aleste II                     Ok\r\n Predator 2 [SMS-GG]                                Ok\r\n Prince of Persia [SMS-GG]                          Ok\r\n Prince of Persia [SMS-GG] (US)                     Ok\r\n Primal Rage                                        Ok\r\n Pro Yakyuu '91, The (JP)                           Ok\r\n Pro Yakyuu GG League (JP)                          Ok\r\n Pro Yakyuu GG League '94 (JP)                      Ok\r\n Psychic World                                      Ok\r\n Psychic World (JP)                                 Ok\r\n Putt & Putter / Putt & Putter - Miniature Golf     Ok\r\n Putt & Putter (JP)                                 Ok\r\n Puyo Puyo (Puzlow Kids) (JP)                       Ok\r\n Puyo Puyo 2 (JP)                                   Ok\r\n Puzzle Bobble (JP)                                 Ok\r\n Quest for the Shaven Yak Starring Ren Hoëk & Sti.. Ok\r\n Quiz Gear Fight!!, The (JP)                        Ok\r\n Rastan Saga [SMS-GG] (JP)                          Ok\r\n R.C. Grand Prix [SMS-GG]                           Ok\r\n R.C. Grand Prix [Proto] [SMS-GG]                   Ok\r\n Revenge of Drancon                                 Ok\r\n Riddick Rowe Boxing (US)                           Ok\r\n Riddick Rowe Boxing (JP)                           Ok\r\n Rise of the Robots                                 Ok\r\n Ristar / Ristar the Shooting Star                  Ok\r\n Road Rash                                          Ok\r\n Road Rash (US)                                     Ok\r\n RoboCop 3                                          Ok\r\n RoboCop versus The Terminator                      Ok\r\n R.B.I. Baseball '94                                Ok\r\n Royal Stone ~Hirakareshi Toki no Tobira~ (JP)      Ok\r\n Ryuu Kyuu (JP)                                     Ok\r\n Samurai Shodown                                    Ok\r\n Samurai Spirits                                    Ok\r\n Scratch Golf (US)                                  Ok\r\n Scratch Golf (JP)                                  Ok\r\n SD Gundam Winner's History (JP)                    Ok\r\n Sega Game Pack 4 in 1                              Ok\r\n Sega Game Pack 4 in 1 [Proto]                      Ok\r\n Sensible Soccer                                    Ok\r\n Shadam Crusader ~Harukanaru Oukoku~ (JP)           Ok\r\n Shanghai II [v0] (JP)                              Ok\r\n Shanghai II [v1] (JP)                              Ok\r\n Shaq Fu                                            Ok\r\n Shining Force - The Sword of Hajya                 Ok\r\n Shining Force Gaiden ~Ensei Jashin no Kuni e~ (JP) Ok\r\n Shining Force Gaiden II ~Jashin no Mezame~ (JP)    Ok\r\n Shining Force Gaiden ~Final Conflict~ (JP)         Ok\r\n Shikinjo (JP)                                      Ok\r\n Skweek (JP)                                        Ok\r\n Shinobi / GG Shinobi, The                          Ok\r\n Shinobi II - The Silent Fury / GG Shinobi II (JP)  Ok\r\n Side Pocket (US)                                   Ok\r\n Slam Dunk - Shouri-e no Starting 5 (From TV.. (JP) Ok\r\n Slider                                             Ok\r\n Sokoban World (JP)                                 Ok\r\n Solitaire Fun Pak                                  Ok\r\n Solitaire Poker                                    Ok\r\n Sonic & Tails (JP)                                 Ok\r\n Sonic & Tails [Demo] (JP)                          Ok\r\n Sonic & Tails 2 (JP)                               Ok\r\n Sonic Blast / G-Sonic                              Ok\r\n Sonic Chaos                                        Ok\r\n Sonic Drift                                        Ok\r\n Sonic Drift [Demo] (JP)                            Replay loose synchronization on second race.\r\n Sonic Drift 2                                      Ok\r\n Sonic Labyrinth                                    Ok\r\n Sonic Spinball                                     Ok\r\n Sonic The Hedgehog [v0]                            Ok\r\n Sonic The Hedgehog [v1]                            Ok\r\n Sonic The Hedgehog [Proto]                         Ok\r\n Sonic The Hedgehog 2                               Ok\r\n Sonic The Hedgehog 2 [Demo]                        Ok\r\n Sonic The Hedgehog Triple Trouble                  Ok\r\n Space Harrier                                      Flickering status (LCD persistance).\r\n Spider-Man - Return of the Sinister Six            Ok\r\n Spider-Man - vs. The Kingpin                       Ok\r\n Spider-Man / X-Men: Arcade's Revenge               Ok\r\n Spirou [Proto]                                     Ok\r\n Sports Illustrated: Championship Football & Baseb. Ok\r\n Sports Trivia                                      Ok\r\n Sports Trivia - Championship Edition               Ok\r\n Star Gate                                          Ok\r\n Star Trek: Generations - Beyond the Nexus          Ok\r\n Star Trek: The Next Generation - The Advanced Ho.. Ok\r\n Star Wars                                          Ok\r\n Star Wars (US)                                     Ok\r\n Streets of Rage / Bare Knuckle                     Ok\r\n Streets of Rage II / Bare Knuckle II               Ok\r\n Streets of Rage II / Bare Knuckle II [Proto]       Ok\r\n Street Battle [Proto] [SMS-GG]                     Ok\r\n Street Hero [Proto 0] [SMS-GG]                     Ok\r\n Street Hero [Proto 1] [SMS-GG]                     Ok\r\n Strider Returns (Journey from Darkness)            Ok\r\n Strider Returns (Journey from Darkness) [Proto]    Ok\r\n Striker                                            Ok\r\n Super Battletank                                   Ok\r\n Super Columns                                      Ok\r\n Super Columns (JP)                                 Ok\r\n Super Golf (JP)                                    Ok\r\n Super Golf (US)                                    Ok\r\n Super Kick Off [SMS-GG]                            Ok\r\n Superman - The Man of Steel                        Ok\r\n Superman - The Man of Steel [Proto]                Ok\r\n Super Momotarou Dentetsu III (JP)                  Ok\r\n Super Monaco GP                                    Ok\r\n Super Monaco GP (JP)                               Ok\r\n Super Monaco GP II (Ayrton Senna's)                Flickering title screen (LCD Persistance).\r\n Super Monaco GP II (Ayrton Senna's) [v0] (JP)      Flickering title screen (LCD Persistance).\r\n Super Monaco GP II (Ayrton Senna's) [v1] (JP)      Flickering title screen (LCD Persistance).\r\n Super Monaco GP II (Ayrton Senna's) [Proto]        Flickering title screen (LCD Persistance).\r\n Super Off Road                                     Ok\r\n Super Off Road [Proto]                             Ok\r\n Super Return of the Jedi (Star Wars)               Ok\r\n Super Smash T.V.                                   Ok\r\n Super Space Invaders                               Ok\r\n Surf Ninjas                                        Ok\r\n Sylvan Tale (JP)                                   Ok\r\n T2: The Arcade Game                                Ok\r\n T2: The Arcade Game (JP)                           Ok\r\n Tails Adventure                                    Ok\r\n Tails' Skypatrol (JP)                              Ok\r\n Taisen-gata Daisenryaku G (JP)                     Ok\r\n Taisen Mahjong Hao-Pai (JP)                        Ok\r\n Taisen Mahjong Hao-Pai 2 (JP)                      Ok\r\n Taito Chase H.Q. / Chase H.Q. [SMS-GG]             Ok\r\n Taito Chase H.Q. [SMS-GG] (JP)                     Ok\r\n TaleSpin (Disney's)                                Ok\r\n Tama & Friends - 3 Choume Kouen Tamalympic (JP)    Ok\r\n Tant~R (Puzzle & Action) (JP)                      Ok\r\n Tarzan - Lord of the Jungle                        Status bar numbers are displayed one line too late.\r\n Tatakae! Pro Yakyuu Twin League (JP)               Ok\r\n Taz in Escape From Mars                            Ok\r\n Taz-Mania                                          Ok\r\n Tempo Jr.                                          Ok\r\n Tengen World Cup Soccer                            Ok\r\n Tengen World Cup Soccer [Proto]                    Ok\r\n Terminator, The                                    Ok\r\n Terminator 2 - Judgment Day                        Ok\r\n Tesserae                                           Ok\r\n Tesserae [Proto]                                   Ok\r\n Smurfs, The                                        Ok\r\n Smurfs Travel the World, The                       Ok\r\n Tintin in Tibet                                    Ok\r\n Tom and Jerry: The Movie                           Ok\r\n Tom and Jerry: The Movie (JP)                      Ok\r\n Torarete Tamaruka!? (JP)                           Ok\r\n True Lies                                          Ok\r\n Ultimate Soccer                                    Ok\r\n Urban Strike                                       Ok\r\n Vampire - Master of Darkness (US)                  Ok\r\n Virtua Fighter Animation                           Ok\r\n Virtua Fighter Mini (JP)                           Ok\r\n VR Troopers                                        Ok\r\n Wagan Land (JP)                                    Ok\r\n Wakiyanrando (JP)                                  Ok\r\n Wheel of Fortune                                   Ok\r\n WildSnake [Proto]                                  Ok\r\n Wimbledon / Wimbledon - Tennis                     Ok\r\n Winter Olympics / Winter Olympics Games            Ok\r\n Winter Olympics (JP)                               Ok\r\n Wizard Pinball                                     Ok\r\n Wolfchild                                          Ok\r\n Wonder Boy                                         Ok\r\n Wonder Boy (JP)                                    Ok\r\n Wonder Boy [Proto] (US)                            Ok\r\n Wonder Boy: The Dragon's Trap                      Ok\r\n Wonder Boy: The Dragon's Trap [Proto]              Ok\r\n Wonder Kid [Proto] [SMS-GG] (US)                   Ok\r\n Woody Pop [v0] (JP)                                Ok\r\n Woody Pop [v1]                                     Ok\r\n World Class Leaderboard Golf / World Class Leade.. Ok\r\n World Cup USA 94                                   Ok\r\n World Derby (JP)                                   Ok\r\n World Series Baseball [v0]                         Ok\r\n World Series Baseball [v1]                         Ok\r\n World Series Baseball '95                          Ok\r\n WWF Raw                                            Ok\r\n WWF WrestleMania Steel Cage Challenge [SMS-GG]     Ok\r\n X-Men                                              Ok\r\n X-Men: GamesMaster's Legacy                        Ok\r\n X-Men: Mojo World                                  Ok\r\n Yogi Bear in Yogi Bear's Goldrush [Proto]          Ok\r\n Yuu Yuu Hakusho - Horobishi Mono no Gyakushuu (JP) Ok\r\n Yuu Yuu Hakusho II - Gekitou! Nanakyou no T.. (JP) Ok\r\n Yuu Yuu Hakusho (JP)                               Ok\r\n Yuu Yuu Hakusho II (JP)                            Ok\r\n Zan Gear (JP)                                      Ok\r\n Zool: Ninja of the Nth Dimension                   Ok\r\n Zool: Ninja of the Nth Dimension (US)              Ok\r\n Zool - Zool no Yume Bouken (JP)                    Ok\r\n Zoop (US)                                          Ok\r\n Zoop [Proto] (US)                                  Ok\r\n-----------------------------------------------------------------------------\r\n 527 games tested - 516 are \"Ok\"\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA GAME GEAR (GG) BIOS IMAGES\r\n-----------------------------------------------------------------------------\r\n Note: the games/animations works properly, but full BIOS behavior is not\r\n emulated. It is not necessary for gaming purpose.\r\n-----------------------------------------------------------------------------\r\n Game Gear Majesco [BIOS]                           Ok\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n COLECOVISION (COL) COMPATIBILITY LIST\r\n by Tincho DJ, Jossa and Bock\r\n-----------------------------------------------------------------------------\r\n Note: this list is outdated. Please help rewriting it if you're interested.\r\n-----------------------------------------------------------------------------\r\n D:     Requires Driving Controller\r\n DO:    Supports Driving Controller (Optional)\r\n R:     Requires Roller Controller\r\n RO:    Supports Roller Controller (optional)\r\n S:     Requires Super Action Controller\r\n SO:    Supports Super Action Controller (optional)\r\n-----------------------------------------------------------------------------\r\n 2010: The Graphic Action Game                2618   -       Ok\r\n Adam's Musicbox Demo                                -       Ok\r\n Alcazar: The forgotten fortress            TC-201   -       Ok\r\n Alphabet Zoo                               ABC-CV   -       Ok\r\n Amazing Bumpman                                     -       Ok\r\n Antarctic Adventure                          2429   -       Ok\r\n Antarctic Adventure (alt)                           -       Ok\r\n Aquattack                                   2-004   -       Ok\r\n Artillery Duel                              99022   -       Ok\r\n BC's Quest                                OTL-902   -       Ok\r\n Beamrider                                  VS-003   -       Ok\r\n Blockade Runner                             2-002   -       Ok\r\n Boulder Dash                                TC203   -       Ok\r\n Brainstrainers                               2696   -       Ok\r\n Bump'n Jump                                  2440   DO      Not playable. Freezes after menu selection.\r\n Burgertime                                   2430   -       Ok\r\n Burgertime (Mattel)                          7514   -       Ok\r\n Cabbage Patch Kids Adv. in the Park          2682   -       Ok\r\n Cabbage Patch Kids Adv. in the Park (alt)           -       Ok\r\n Cabbage Patch Kids Picture Show              2600   -       Ok\r\n Campaign '84                                 1604   -       Ok\r\n Carnival                                     2445   -       Ok\r\n Centipede                                   70004   RO      Ok\r\n Choplifter                                   2690   -       ok\r\n Choplifter (alt)                                    -       Ok\r\n Chuck Norris Superkicks                             -       Ok\r\n ColecoVision Noise Generator                        -       Ok\r\n Congo Bongo                                  2669   -       Ok\r\n Cosmic Avenger                               2434   -       Ok\r\n Cosmic Avenger (alt)                                -       Ok\r\n Cosmic Crisis                              PG-901   -       Ok\r\n Cosmo Fighter 2                                     -       Ok\r\n Dance Fantasy                              DCF-CV   -       Graphic bugs?\r\n Decathlon                                  VS-006   -       Ok\r\n Defender                                    70002   -       Ok\r\n Destructor                                   2602   D       Does not work. Hangs at menu screen.\r\n Dig Dug                                             -       Ok\r\n Donkey Kong                                  2411   -       Freeze at the end of level 1.\r\n Donkey Kong 24K                                     -       Ok\r\n Donkey Kong 24K (ADAM version)                      -       Ok\r\n Donkey Kong Jr.                              2601   -       Ok\r\n Donkey Kong Jr. 24K (ADAM Version)                  -       Ok\r\n Dr. Seuss Fix Up The Mix Up Puzzle           2699   -       Ok\r\n Dragonfire                                  O6611   -       Buggy on second scene (BAD DUMP?)\r\n Escape from the Mindmaster [Proto]           6200   -       Ok\r\n Evolution                                           -       Ok\r\n Facemaker                                  FMK-CV   -       Ok\r\n Fallguy [Proto]                                     -       Ok\r\n Fathom                                      O6205   -       Does not work. Game restarts.\r\n Final Test Cartridge                                -       Ok?\r\n Flipper Slipper                                     -       Ok\r\n Fortune Builder                              2601   -       Ok\r\n Fraction Fever                             FRF-CV   -       Ok\r\n Frantic Freddie                             SE232   -       Ok\r\n Frenzy                                       2613   -       Ok\r\n Frenzy (alt)                                        -       Ok\r\n Frogger                                      9830   -       Ok\r\n Frogger II - ThreeDeep                       9990   -       Ok\r\n Front Line                                   2650   -       Ok\r\n Galaxian                                    70006   -       Ok\r\n Gateway to Apshai                            610R   -       Ok\r\n Gorf                                         2449   -       Ok\r\n Grog's Revenge                               2620   -       Ok\r\n Grog's Revenge (32k)                                -       Ok\r\n Gust Buster                                  1601   -       Ok\r\n Gyruss                                       9980   -       Ok\r\n H.E.R.O.                                   VS-005   -       Ok\r\n It's Only Rock'n'Roll                       99062   -       Ok\r\n James Bond                                   9900   -       Ok\r\n Joust                                               -       Ok\r\n Juke Box                                   JUK-CV   -       Ok\r\n Jumpman Junior                               590R   -       Ok\r\n Jumpman Junior (alt)                                -       Ok\r\n Jungle Hunt                                 70007   -       Ok\r\n Ken Uston Blackjack-Poker                    2431   -       Ok\r\n Kevtris                                             -       Ok\r\n Keystone Kapers                            VS-004   -       Ok\r\n Kill Barney In Tokyo                                -       Ok\r\n Killer Instinct                                     -       Ok\r\n Lady Bug                                     2433   -       Ok\r\n Linking Logic                              LNL-CV   -       Ok\r\n Logic Levels                               LLV-CV   -       Ok\r\n Looping                                      2603   -       Ok\r\n M.A.S.H. [Proto]                                    -       Ok\r\n Memory Manor                               MEM-CV   -       Ok\r\n Meteoric Shower                                     -       Ok\r\n Miner 2049er                               MCL521   -       Ok\r\n Miner 2049er (alt)                                  -       Ok\r\n Monkey Academy                               2694   -       Ok\r\n Monkey Academy (alt)                                -       Ok\r\n Montezuma's Revenge                          9660   -       Ok\r\n Moom Patrol [Proto]                                 -       Ok\r\n Moonsweeper                                 O2607   -       Ok\r\n Motocross Racer                             99026   -       Ok\r\n Mountain King                                1605   -       Ok\r\n Mouse Trap                                   2419   -       Ok\r\n Mr Do!                                       2622   -       Ok\r\n Mr Do! (alt)                                        -       Ok\r\n Mr Do's Castle                              A9820   -       Ok\r\n Nova Blast                                  O6607   -       Ok\r\n Oil's Well                                OWL-901   -       Ok\r\n Omega Race                                   2448   RO      Ok\r\n One On One                                          -       Ok\r\n Pac-Man                                             -       Ok\r\n Pepper II                                    2605   -       Ok\r\n Pitfall 2: Lost Caverns                    VS-008   -       Freeze (was Ok with MEKA <= 0.60)\r\n Pitstop                                      600R   Do      Ok\r\n Popeye                                       9810   -       Ok\r\n Porky's [Proto]                                     -       Ok\r\n Purple Dinosaur Massacre                            -       Ok\r\n Q*bert                                       9800   -       Ok\r\n Q*bert (alt)                                        -       Ok\r\n Q*bert II (AKA Q*bert Qubes)                 9950   -       Ok\r\n Quest for Quintana Roo                       1603   -       Ok\r\n River Raid                                 VS-002   -       Ok\r\n Robin Hood                                  99023   -       Ok\r\n Roc 'N Rope                                  2668   -       Ok\r\n Rock 'N Bolt                               TC-202   -       Ok\r\n Rocky Super Action Boxing                    2606   SO      Ok\r\n Rolloverture                                 1602   -       Ok\r\n Sammy Light Foot                          SLL-901   -       Ok\r\n Sammy Light Foot (alt)                              -       Ok\r\n Sector Alpha                                SE220   -       Various graphic bugs.\r\n Sector Alpha (alt)                                  -       Various graphic Bugs.\r\n Sewer Sam                                   2-001   -       Ok\r\n Sir Lancelot                                99024   -       Ok\r\n Skiing                                              -       Ok\r\n Slither                                      2492   R       Not playable. Requires Roller controller emulation.\r\n Slurpy                                      99061   -       Ok\r\n Smurf Paint & Play Workshop                  2697   -       Ok\r\n Smurf Rescue                                 2443   -       Ok\r\n Space Fury                                   2415   -       Ok\r\n Space Fury (alt)                                    -       Ok\r\n Space Invasion                                      -       Ok\r\n Space Panic                                  2447   -       Game often hangs. Freezes MEKA.\r\n Spectron                                    SE234   -       Ok\r\n Squish 'Em Sam                              2-003   -       Ok\r\n Star Fortress                                       -       Ok\r\n Star Trek - Strategic Operations Simulator   2680   SO      Ok\r\n Star Wars: The Arcade Game                   9940   -       Ok\r\n Strike it!                                          -       Ok\r\n Sub Roc                                      2614   -       Ok\r\n Super Action Baseball                        2491   S       Ok\r\n Super Action Football                        2421   S       Ok\r\n Super Action Football (alt)                         S       Ok\r\n Super Action Soccer                                 S       Ok\r\n Super Controller Tester                             S       Ok?\r\n Super Cross Force                           SE237   -       Ok\r\n Super DK!                                           -       Ok\r\n Super DK! (alt)                                     -       Ok\r\n Tank Wars                                   PG902   -       Ok\r\n Tapper                                       2616   -       Ok\r\n Tarzan                                       2632   -       Ok\r\n Telly turtle                                 2698   -       Ok\r\n The Dam Busters                              2686   -       Ok\r\n The Dukes Of Hazard                          2607   D       Input doesn't work due to missing Driving Controller emulation.\r\n The Heist                                           -       Ok\r\n The Yolk's On You                                   -       Ok\r\n Threshold                                  THQ903   -       Game often restarts.\r\n Tic Tac Toe                                         -       Ok\r\n Tic Tac Toe (alt)                                   -       Ok\r\n Time Pilot                                   2633   -       Ok\r\n Tomarc The Barbarian                        99025   -       Ok\r\n Tournament Tennis                           O6030   -       Ok\r\n Tunnels & Trolls (Demo) (ADAM)               2441   -       Ok\r\n Turbo                                        2430   D       Not playable. Game hangs at menu screen, possibly due to missing controller emulation.\r\n Tutankham                                    9840   -       Ok\r\n Up'n Down                                  009-21   -       Ok\r\n Venture                                      2417   -       Ok\r\n Victory                                      2446   R       Requires Roller Controller emulation\r\n Video Hustler [Proto]                               -       Ok\r\n War games                                    2632   R       Requires Roller Controller emulation\r\n War Room                                   2153CL   RO      Ok\r\n War Room (32k)                                      RO      Ok\r\n Wing War                                    O6209   -       Ok\r\n Winky Trap                                          -       Ok\r\n Wizard Of ID's Wizmath                    WML-900   -       Ok\r\n Word Feud                                   99060   -       Ok\r\n Zaxxon                                       2435   -       Ok\r\n Zenji                                               -       Ok\r\n-----------------------------------------------------------------------------\r\n Bad Dumps:\r\n    Buck Rogers - Planet Of Zoom                  2615   -       Bugs/resets/hangs periodically\r\n    Bump 'N' Jump (Mattel) [Proto]                7575   -       Freezes after loading (unfinished?)\r\n    Decathlon                                   VS-006   -\r\n    Illusions                                     2621   -\r\n    Learning With Leeper                       LLL-911   -\r\n    Pitfall!                                    VS-001   -       Various graphic bugs\r\n    Spy Hunter                                    2617   SO      A working dump exists\r\n    Super Cobra                                   9850   -       Bad Dump # 1\r\n    Super Cobra                                   9850   -       Bad Dump # 2\r\n-----------------------------------------------------------------------------\r\n 180 games tested, too many are not Ok\r\n-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/debugger.txt",
    "content": "-----------------------------------------------------------------------------\r\n MEKA - Debugger / Hacking tools\r\n-----------------------------------------------------------------------------\r\n Note: this documentation is yet incomplete.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 1. Debugger\r\n-----------------------------------------------------------------------------\r\n\r\nTo enable the debugger, set 'debug_mode' to 1 in the configuration file.\r\nElse, you can enable the debugger for a session by executing MEKA with the\r\n'-DEBUG' command-line parameter.\r\n\r\nIn debug mode, an additionnal menu is added to the top, with access to the\r\ndebugger and data dumping facilities. The debugger can also be switched on\r\nand off using the Scroll Lock key.\r\n\r\nYou can configure some part of the debugger from the configuration file,\r\nsearch for the following variables:\r\n\r\n  debug_mode                            (enable debug mode)\r\n  debugger_console_lines                (number of console lines)\r\n  debugger_disassembly_lines            (number of disassembly lines)\r\n  debugger_disassembly_display_labels   (enable label display)\r\n  debugger_log                          (enable log of debugger output)\r\n\r\nUse mouse wheel to scroll in disassembly.\r\n\r\nAll debugger output are logged by default.\r\nThe log is located in the 'DEBUG/DEBUGLOG.TXT' file.\r\n\r\n\r\nSymbols Loading\r\n---------------\r\n\r\nThe debugger support symbols loading in the following format:\r\n\r\n - NO$GMB format, as generated by the WLA DX linker (-s option):\r\n     YYYY:XXXX MyLabel\r\n\r\n - NO$GMB format with banking:\r\n     XXXX MyLabel\r\n\r\n - SJASM format:\r\n     MyLabel: equ XXXXXXXXh\r\n\r\n - TASM format:\r\n     MyLabel XXXX\r\n\r\nWhen a bank is specified in NO$GMB format, the label is associated to its ROM-space address.\r\nOtherwise a CPU-space address is used.\r\n\r\nThe filename must be the same as the ROM image filename, replaced by\r\nor post pended with the \".SYM\" extension.\r\n - eg: ROM is \"PsychoFox.sms\",\r\n    -> MEKA will look for symbols in \"PsychoFox.sym\" or \"PsychoFox.sms.sym\"\r\n\r\nIf you are using a tool that generate an unsupported symbol format please contact me.\r\n\r\nSymbols are replaced by their corresponding address in CPU space in the various debugger commands.\r\nIf you prefix a symbol name with the : character (eg: \":MyLabel\") it is replaced by its address in ROM space.\r\nThis is only functional if the bank number is available from the symbols format (the 'XXXX' in WLA DX output).\r\n\r\n\r\nCompletion\r\n----------\r\n\r\nPressing TAB in the debugger command line performs contextual completion.\r\nIf more than one item matches, possible matches are displayed.\r\n\r\n\r\nHistory\r\n-------\r\n\r\nCommand are logged into an history buffer.\r\nPressing Up/Down allows navigating in the history buffer.\r\nAdditionnally, the HI/HISTORY allows listing or searching for a given\r\nword in the history buffer.\r\n\r\n\r\nExpression evaluator\r\n--------------------\r\n\r\nMathematical expression can be evaluated by the debugger.\r\nSupported features are:\r\n\r\n - Values:\r\n   - Immediate hexadecimal integer\r\n     (eg: 1234, or $1234 or 0x1234)\r\n   - Immediate binary integer\r\n     (eg: %00101010)\r\n   - Immediate decimal integer\r\n     (eg: #256)\r\n   - Symbols gets replaced by their CPU address.\r\n     (eg: function_label)\r\n   - Symbols prefixed by : gets replaced by their ROM address.\r\n     (eg: :function_label)\r\n   - Z80 registers names gets replaced by their current value.\r\n     (eg: PC, SP, AF, A, BC, B, C, DE, D, E, HL, H, L, IX, IY)\r\n     Pay attention that some registers names are ambiguous with hexadecimal\r\n     constants ('A' is a 10 in hexadecimal). Z80 registers name are always\r\n     given priority over hexadecimal constants.\r\n     Uses the 'Ox' or '$' prefixes to resolve ambiguity.\r\n\r\n - Operators:\r\n   - Integer operators: + - / *\r\n     (eg: 1+2*3 returns 7)\r\n     (eg: SP-10)\r\n   - Binary operators: & | ^\r\n     (eg: 0xF0 | 0x0F returns 0xFF)\r\n   - Parenthesis: (), forcing priority\r\n     (eg: (1+2)*3 returns 9)\r\n\r\nAny separator among the set of ',' '.' or ' ' (space) is considered as ending the expression.\r\nThe remaining text will be fed to the next parameters of the current command.\r\n\r\n\tM HL+10\t\t\t; correct\r\n\tM HL + 10\t\t; incorrect (will provide 3 parameters to the \"M\" command)\r\n\r\n\r\nKnown problems\r\n--------------\r\n\r\n- Beware of clashes between Z80 registers names and hexadecimal constants.\r\n  'AF','BC','DE','A','B','C','D','E' by default refers to Z80 registers.\r\n  Uses $ or 0x hexadecimal prefixes to resolve ambiguities.\r\n\r\n- Reseting or loading save states may result in missing breakpoints for a few\r\n  Z80 instructions (unconfirmed? is this bug still valid?).\r\n\r\n- Execution breakpoints only works for the leading byte of the opcode.\r\n  eg:\r\n    1234 - C3 00 20 - JP $2000\r\n  Adding an X breakpoint at $1234 will work, but not at $1235 or $1236.\r\n  However, adding a R breakpoint will work.\r\n  So usually, you end just adding default RWX or RW breakpoints.\r\n\r\n\r\nDebugger commands summary\r\n-------------------------\r\n\r\n-- Flow:\r\n <CR>                           : Step into\r\n S                              : Step over\r\n SO                             : Step out (to next RET)\r\n C                              : Continue\r\n C addr                         : Continue up to <addr>\r\n J addr                         : Jump to <addr>\r\n-- Breakpoints:\r\n B [access] [bus] addr [=value] : Add breakpoint\r\n W [access] [bus] addr [=value] : Add watchpoint\r\n B LIST                         : List breakpoints\r\n B REMOVE id                    : Remove breakpoint\r\n B ENABLE id                    ; Enable breakpoint\r\n B DISABLE id                   : Disable breakpoint\r\n B CLEAR                        : Clear breakpoints\r\n-- Inspect/Modify:\r\n R                              : Dump Z80 registers\r\n P expr                         : Print evaluated expression\r\n M [addr] [cnt]                 : Memory dump at <addr>\r\n D [addr] [cnt]                 : Disassembly at <addr>\r\n STACK [cnt]                    : Stack dump\r\n TRACE [<cnt>|all|clear|regs]   : Trace past execution\r\n RMAP addr                      : Reverse map Z80 address\r\n VARS [name]                    : Display variables by name\r\n VARS @addr                     : Display variables by address\r\n SYM [name]                     : Find symbols by name\r\n SYM @addr                      : Find symbols by address\r\n SET register=value             : Set Z80 register\r\n CLOCK [RESET]                  : Display Z80 cycle counter\r\n-- Miscellaenous:\r\n MEMEDIT [lines] [cols]         : Spawn memory editor\r\n HISTORY [word]                 : Print/search history\r\n H,? [command]                  : Help\r\n\r\n\r\nDebugger command - H\r\n--------------------\r\nH/HELP: Online help\r\nUsage:\r\n H             ; Get general help\r\n H command     ; Get detailed help on a command\r\n\r\n\r\nDebugger command - S\r\n--------------------\r\nS: Step over\r\nUsage:\r\n S             ; Step over current instruction\r\nExamples:\r\n 0000: CALL $0100\r\n 0003: LD HL, $1FFF\r\n S             ; Resume execution after the call\r\n\r\n\r\nDebugger command - C\r\n--------------------\r\nC/CONT: Continue execution\r\nUsage:\r\n C             ; Continue\r\n C address     ; Continue up to reaching <address>\r\n\r\n\r\nDebugger command - CR\r\n---------------------\r\nCR/CONTRET: Continue to next RET instruction\r\n\r\n\r\nDebugger command - J\r\n--------------------\r\nJ/JUMP: Jump\r\nUsage:\r\n J address     ; Jump to <address>\r\nExamples:\r\n J 0           ; Jump back to $0000 (reset)\r\n J 1000        ; Jump to $1000\r\nNote:\r\n Equivalent to SET PC=address\r\n\r\n\r\nDebugger command - B\r\n--------------------\r\nB/BREAK: Manage breakpoints\r\nUsage:\r\n B address [..address2]         ; Add CPU breakpoint\r\n B [access] [bus] address [=xx] ; Add breakpoint\r\n B LIST                         ; List breakpoints\r\n B REMOVE id                    ; Remove breakpoint <id>\r\n B ENABLE id                    ; Enable breakpoint <id>\r\n B DISABLE id                   ; Disable breakpoint <id>\r\n B CLEAR                        ; Clear breakpoints\r\nParameters:\r\n address : breakpoint address, can be a range or label\r\n access  : access to trap, any from r/w/x (rwx)\r\n bus     : bus/event, one from cpu/io/vram/pal/rom/line (cpu)\r\n xx      ; byte to compare to, for conditionnal break\r\n id      : breakpoint identifier\r\nExamples:\r\n B 0038          ; break when CPU access $0038\r\n B w io 7f       ; break on IO write to $7F\r\n B rx e000..ffff ; break on CPU read/exec from $E000+\r\n B x =0,0,C9     ; break on CPU execution of NOP NOP RET\r\n B w vram 3f00.. ; break on VRAM write to SAT\r\n B w pram 0 =03  ; break on PRAM write of color 0 as $03\r\n B line #13      ; break on display line 13\r\n\r\nYou can add a description to breakpoints, by ending the\r\ncommand line with a string:\r\n B 0038 \"interrupt\"\r\n\r\nAs a shortcut:\r\n B nopnop\r\nIs equivalent to:\r\n B x=0,0 \"NOP NOP\"\r\n\r\n\r\nDebugger command - W\r\n--------------------\r\nW/WATCH: Manage watchpoints\r\nUsage:\r\n Same as B/BREAK.\r\n Watchpoints will display value but won't break.\r\nExamples:\r\n W r io dd      ; watch and log all IO read from DDh\r\n W w pal 0..    ; watch and log all palette write\r\n\r\n\r\nDebugger command - P\r\n--------------------\r\nP/PRINT: Print expression\r\nUsage:\r\n P expr\r\n P expr[,expr,...]\r\nExamples:\r\n P IX,IY       ; print IX and IY registers\r\n P 1200+34     ; print $1234\r\n P %00101010   ; print 42\r\n P HL+(BC*4)   ; print HL+BC*4\r\n P label       ; print label\r\n\r\n\r\nDebugger command - SET\r\n----------------------\r\nSET: Set Z80 register\r\nUsage:\r\n SET register=value [,...]\r\nParameters:\r\n register : Z80 register name\r\n value    : value to assign to register\r\nExamples:\r\n SET BC=$1234    ; set BC register to $1234\r\n SET DE=HL,HL=0  ; set DE=HL, then zero HL\r\n\r\n\r\nDebugger command - RMAP\r\n-----------------------\r\nRMAP: Reverse map Z80 address\r\nUsage:\r\n RMAP address\r\nParameters:\r\n address : address in Z80 space\r\nExamples:\r\n RMAP $8001      ; eg: print 'ROM $14001 (Page 5 +0001)'\r\n RMAP $E001      ; eg: print 'RAM $C001'\r\n\r\n\r\nDebugger command - CLOCK\r\n------------------------\r\nCLOCK: Display Z80 cycle accumulator\r\nUsage:\r\n CLOCK         ; Display cycle accumulator\r\n CLOCK R[ESET] ; Reset cycle accumulator\r\n\r\n\r\nDebugger command - VARS\r\n----------------------\r\nVARS: Display variables\r\n(Variables are symbols declared within a RAM location.)\r\nUsage:\r\n VARS [name]\r\n VARS @addr\r\nParameters:\r\n name : variable/symbol name to search for\r\n addr : variable/symbol address to search for\r\nExamples:\r\n VARS             ; display all variables\r\n VARS player      ; display variables matching 'player'\r\n VARS @HL         ; display variables at address HL\r\n\r\n\r\nDebugger command - SYM\r\n----------------------\r\nSYM/SYMBOLS: Find symbols\r\nUsage:\r\n SYM [name]\r\n SYM @addr\r\nParameters:\r\n name : symbol name to search for\r\n addr : symbol address to search for\r\nExamples:\r\n SYM vdp         ; search for symbol matching 'vdp'\r\n SYM @HL         ; search for symbol at address of HL\r\n\r\n\r\nDebugger command - M\r\n--------------------\r\nM/MEM: Dump memory\r\nUsage:\r\n M [address] [len]\r\nParameters:\r\n address : address to dump memory from (PC)\r\n len     : bytes to dump (128)\r\nExamples:\r\n M             ; dump 128 bytes at PC\r\n M HL BC       ; dump BC bytes at HL\r\n\r\n\r\nDebugger command - D\r\n--------------------\r\nD/DASM: Disassemble instructions\r\nUsage:\r\n D [address] [cnt]\r\nParameters:\r\n address : address to disassemble from (PC)\r\n cnt     : number of instruction to disassemble (10)\r\n\r\n\r\nDebugger command - STACK\r\n------------------------\r\nST/STACK: Dump stack\r\nUsage:\r\n ST [len]\r\nParameters:\r\n len     : bytes to dump (8)\r\nExamples:\r\n ST             ; dump 8 bytes at SP\r\nNotes:\r\n Each entry is displayed as a possible 8-bit of 16-bit value.\r\n Symbols are resolved.\r\n\r\n\r\nDebugger command - TRACE\r\n------------------------\r\nTR/TRACE: Trace past execution\r\nUsage:\r\n TR [cnt]\r\n TR all         ; trace all (since last clear\r\n TR clear       ; clear trace log\r\n TR regs        ; toggle dumping extra registers\r\nParameters:\r\n cnt            : number of previous instruction (16)\r\nNotes:\r\n If the number of instructions to trace is large, output is redirected to Debug/debuglog.txt\r\n and not displayed in the debugger view.\r\n\r\n\r\nDebugger command - R\r\n--------------------\r\nR/REGS: Dump Z80 registers\r\nUsage:\r\n R\r\n\r\n\r\nDebugger command - MEMEDIT\r\n--------------------------\r\nMEMEDIT: Spawn memory editor\r\nUsage:\r\n MEMEDIT [lines] [cols]\r\nParameters:\r\n lines : number of lines\r\n cols  : number of columns\r\n\r\n\r\nDebugger command - HISTORY\r\n--------------------------\r\nHI/HISTORY: Print/search history\r\nUsage:\r\n HISTORY        ; Print history\r\n HISTORY word   ; Search history\r\n\r\n\r\n-----------------------------------------------------------------------------\r\n 2. Palette\r\n-----------------------------------------------------------------------------\r\n\r\n ...\r\n\r\n-----------------------------------------------------------------------------\r\n 3. Tile Viewer\r\n-----------------------------------------------------------------------------\r\n\r\n ...\r\n\r\n-----------------------------------------------------------------------------\r\n 4. Tilemap Viewer\r\n-----------------------------------------------------------------------------\r\n\r\n ...\r\n\r\n-----------------------------------------------------------------------------\r\n 5. Technical Information\r\n-----------------------------------------------------------------------------\r\n\r\n ...\r\n\r\n-----------------------------------------------------------------------------\r\n 6. Memory Editor\r\n-----------------------------------------------------------------------------\r\n\r\n Allows viewing and writing to memory:\r\n - Z80 memory map\r\n - ROM\r\n - RAM\r\n - VRAM\r\n - VREG\r\n - PAL (if any)\r\n - SaveRAM (if any)\r\n\r\n Tips:\r\n - Use mouse wheel, arrow keys or cursor to navigate.\r\n - Using the address box, you can jump to a given address.\r\n - In some case, you may want to pause the game (F12) while editing,\r\n   in some other case you may want it running.\r\n - Z80 memory map is what the Z80 CPU sees and accesses thru its buses.\r\n   Refer to technical documentation about the machine memory map to know\r\n   how this works. Understand the difference:\r\n   - Writing to Z80 $FFFC-$FFFF trigger mapping + write to RAM.\r\n     But writing to RAM $FFFC-$FFFF only write to RAM.\r\n   - Writing to Z80 $0000-$3FFF is ignored (by most mappers).\r\n     But writing to ROM $0000-$3FFF works and modify loaded ROM image.\r\n - Beware that pressing \"BackSpace\" may reset the game. Use the \"Delete\"\r\n   key instead. (I should hack a way so that BackSpace is disabled\r\n   but other controller keys still enabled).\r\n\r\n-----------------------------------------------------------------------------\r\n 7. Data Dumping\r\n-----------------------------------------------------------------------------\r\n\r\n ...\r\n\r\n-----------------------------------------------------------------------------\r\n 8. Patching\r\n-----------------------------------------------------------------------------\r\n\r\n Refer to MEKA.PAT file.\r\n\r\n-----------------------------------------------------------------------------\r\n 8. Links\r\n-----------------------------------------------------------------------------\r\n\r\n SMS Power! Development\r\n http://www.smspower.org/dev/\r\n\r\n SMS Power! Development Forum\r\n http://www.smspower.org/forums/viewforum.php?f=3\r\n\r\n WLA DX\r\n http://users.tkk.fi/~vhelin/wla.html\r\n\r\n Maxim's \"Getting started with SMS programming\" pages\r\n http://www.smspower.org/maxim/howtoprogram\r\n\r\n-----------------------------------------------------------------------------\r\n 9. More ?\r\n-----------------------------------------------------------------------------\r\n\r\n Please suggest features you may want to help development/hacking activity!\r\n Please report bugs!\r\n\r\n I can also point out that in the absence of a given feature, you can always\r\n hack into MEKA source code and add custom code/printing/hacks to help you. :)\r\n\r\n The TODO.TXT file provided along with the source code list several notes\r\n and ideas related to future development of debugging/hacking features.\r\n\r\n-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/history.txt",
    "content": "\r\nThis is the \"developer\" version of CHANGES.TXT\r\nNot much difference, mainly:\r\n- Including some source-related comments.\r\n- Including pre-0.10 changelog.\r\n\r\nLines starting with ## are only pertinent on WIP releases, and should\r\nremoved when copying changes to CHANGES.TXT for a stable release.\r\nThey are usually of 2 kinds:\r\n- Fixes or addition to things changed during WIP.\r\n- Programmer/hacker centric information.\r\n\r\n MEKA 0.8x WIP Allegro 5\r\n -----------------------\r\n  - Updated from Allegro 4 (software rendering based) to Allegro 5.2.10 (with OpenGL/DirectX backends).\r\n    This required a lot of changes and rewrite in the codebase. It probably added new bugs,\r\n    and performances seems to vary depending on computer settings and video drivers. [Omar, Maxim]\r\n    Please do report if you have any issue/slowdown so we can fix them!\r\n  - Rewrote sound engine and fixed audio issues that many users had. [Omar]\r\n    The sound is also now functional under Linux and MacOS. [Omar]\r\n  - Changed default key mapping for Player 1 buttons to use Z/X. [Omar]\r\n  - Setup panel allows to select display driver and resolution. [Omar]\r\n  - Added Polish translation. [thr]\r\n  - Updated Dutch translation. [Mark van Tilburg]\r\n  - MacOSX:\r\n    - Preliminary MacOSX port. MEKA NEEDS A MAC MAINTENER! [Omar]\r\n    - Use OS compliant directories for storing configuration files. [Dajero] (#12)\r\n  - Emulation (Main):\r\n    - Z80: Fixed emulation of R register (fixes 'Bubble Bobble', 'Hong Kil Dong' among others) [Calindro]\r\n    - Z80: Fixed CPDR running fully and ignoring interrupts. [Calindro]\r\n    - Z80: Fixed HALT timing. [Calindro]\r\n    - VDP: Setting address via palette write preserve upper address bits. Fixes tests #4 and #15 of FluBBA's VDP Tester. [Omar]\r\n    - VDP: Writing to palette sets the read buffer. Fixes test #10 of FluBBA's VDP Tester. [Omar]\r\n  - Emulation (Audio):\r\n    - PSG: Added support for Game Gear stereo emulation! [Maxim]\r\n    - PSG: Emulate the PSG volumes \"ideally\" rather than matching some real systems' suboptimal output. [Maxim]\r\n    - Emu2413: Updated to latest version 1.5.9 (revision 813cff619f5f01c47bd5c0588c1fd8435530b125 in https://github.com/digital-sound-antiques/emu2413) [Maxim]\r\n      - Various emulation fixes and improvements\r\n    - Emu2413: Use the real YM2413 instrument ROM patches\r\n  - Emulation (Memory System, Mappers, Peripherals):\r\n    - Added support for variant of MSX-based Korean 8KB mapper used by 'Nemesis'. [Omar]\r\n    - Added support for '4 PAK All Action' mapper. [Omar]\r\n    - Added support for 'Janggun-ui Adeul' mapper. [Omar]\r\n    - Added support for Taiwanese DahJee/Jumbo SG-1000 II RAM extension adapter. [Omar]\r\n    - Added support for Sega Graphic Tablet v2.0 prototype hardware. [Maxim,Omar]\r\n    - Added support for Korean Hi-Com 3-in-1 and 8-in-1 mapper. [Omar]\r\n    - Added support for Korean xx-in-1 mapper at 0x0000,0x0100,0x0200,0x300 for: 'Super Multi Game - Super 75 in 1' and 'Super Game World 75'. [Omar]\r\n    - Added support for Korean xx-in-1 mapper at 0x2000 for: '128 Hap', 'Game Mo-eumjip 188 Hap'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0xBFFC for: 'Super Game 52 Hap', 'Super Game 180', 'Super Game 200'. [bsittler, Omar]\r\n    - Added support for Korean xx-in-1 mapper at 0xFFFE for: 'Super Game 45'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0xFFF3,0xFFFC for: 'Super Game 150', 'Super Game 270'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0x0000 (xored 0xFF) for 'Zemina 4-in-1 (Q-Bert, Sports 3, Gulkave, Pooyan)'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0xFFF0,0xFFFE,0xFFFF for: 'Mega Mode Super Game 30 [SMS-MD]'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0xFFF5,0xFFFE,0xFFFF for 'Jaemiissneun Game Mo-eumjip 42 Hap [SMS-MD]'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0xFFFA,0xFFFE,0xFFFF for 'Game Jiphap 30 Hap [SMS-MD]'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0x2000 for '11 Hap Gam-Boy'. [bsittler]\r\n    - Added support for Korean xx-in-1 mapper at 0x8000 for 'Zemina Best 88', 'Zemina Best 25' etc. [bsittler]\r\n    - Added support for MSX Generic 16 kb mapper for 'Wonder Kid [Proto]'. [bsittler]\r\n    - Added support for SC-3000 Survivors Multicart mapper. [Omar,Honestbob]\r\n    - Fixed 32K \"No Mapper\" mapper from forwarding 3-D Glasses writes. Fixes '3D Gunner'. [Omar]\r\n    - SMS/GG ROM images smaller than 48KB default to using no mapper. [Omar]\r\n    - Hardware reset leaves RAM cleared with $F0 patterns on Japanese SMS.\r\n      This allow 'Ali Baba' and 'Block Hole' to run properly. Better clearing patterns\r\n      could be implemented for other systems/countries after we've done more research. [Omar]\r\n    - Added support for mirrored VDP ports in $80..$BF range, as required by some\r\n      Korean games such as 'Pooyan', 'Sky Jaguar' or 'E.I.'. [Omar]\r\n    - Light Phaser: Adding per-game hacky light phaser function to reduce drift\r\n      between perceived cursor and what the game will end up using, particularly\r\n      useful for 'Missile Defense 3-D' and '3D Gunner'. [Omar]\r\n  - Emulation (SF-7000)\r\n    - Added support for extended DSK format (as .dsk or .sf7 extensions). [Nanard]\r\n      For future SF-7000 releases we will use this format as our legacy 163840 bytes .SF7 format\r\n      didn't convey enough information to reliably emulate all available software.\r\n  - Debugger:\r\n    - Added support for setting breakpoint from ROM addresses (perform reverse mapping to validate address). [Omar]\r\n    - Referring to a symbol using with the : prefix (in the form \":xxxx\") returns the ROM address instead of the CPU address. [Omar]\r\n    - Added STEPOUT command (\"Continue to next RET* instruction at same stack-frame level.\"). [Omar]\r\n    - Added STACK command (\"Dump stack\", with dual 8/16 bits display and with symbol resolving). [Omar]\r\n    - Added VARS command (\"Variables\") to display content pointed by symbols in RAM. [Omar]\r\n    - Added TRACE command to trace past execution. [Omar]\r\n    - Improved the range of disassembly before PC cursor when running loops. [Omar]\r\n    - Fixed CLOCK command display for period longer than 10 minutes. [Maxim]\r\n    - Added support for parsing the bank in NO&GMB/WLA symbol format. Symbols are turned into ROM addresses. [Omar]\r\n    - Added support for parsing SJASM symbol format. [Omar]\r\n    - Added support for parsing TASM symbol format. [Omar]\r\n    - Added a \"Reload Symbols\" menu option (useful when manually crafting symbols while reverse engineering). [Omar]\r\n    - Added shortcuts button in interface for \"Stop/Continue\", \"Step\", \"StepOver\", \"StepOut\", \"Stack\". [Omar]\r\n    - Added SDSC console support by writing to ports $FC/$FD when ROM has an SDSC tag. [Maxim]\r\n    - Disassembler: uses recorded Z80 execution history to allow semi-freely scrolling up and down in disassembly. [Omar]\r\n    - Disassembler: display symbols given their full ROM bank mapping (if bank information is provided by symbols file). [Omar]\r\n    - Disassembler: display symbols in 'RST xx' instructions. [Omar]\r\n    - Disassembler: opcodes shown in lower-case, increased spacing for readability. [Omar]\r\n    - Disassembler: display symbols+offset on JP/JR/CALL/RET/DJNZ instructions. [Omar]\r\n    - Disassembler: display symbols on IX/IY indexed instructions given the current value of IX/IY. [Omar]\r\n    - Disassembler: fixed issues with prefixed instructions. [Omar]\r\n    - Improved disassembler view centering, increased the track-back buffer, fixed issues with prefixed instructions. [Omar]\r\n    - Better support for 24-bits constants (for PRINT, etc.). [Omar]\r\n    - Debugger is always available at runtime. Obsoleted /DEBUG command-line parameter. [Omar]\r\n    - Debugger window can be resized. [Omar]\r\n  - Tools:\r\n    - CheatFinder: added a new cheat finder application. [Omar]\r\n      - Can search for 1-bit, 8-bit, 16-bit, 24-bit values.\r\n      - Can search in RAM,ROM,VRAM,VREG,PRAM,SRAM,Z80 spaces for maximum flexibility,\r\n        although for actual cheat-finding purpose RAM is likely to be more searched for.\r\n      - Reduce the match set by using ==,!=,<,>,<=,>= operators, compare with a constant\r\n        or the old value stored in each match memory location.\r\n      - Highlight matches in the memory editor for easier visibility.\r\n      - Undo button.\r\n    - TilemapViewer: support for legacy graphic mode 2 used by SG-1000 games. [Omar]\r\n    - TilemapViewer: support for 256x256 tilemap used in PAL/SECAM wide screen mode. [Omar]\r\n    - TileViewer: support for showing full 16 KB range of tiles in legacy graphic modes. [Omar]\r\n    - MemoryEditor: fixed editing of 93c46 EEPROM memory. [Omar]\r\n    - MemoryEditor: fixed display of address when number of columns is not 16. [Omar]\r\n    - Wav Logging: recording in Stereo. [Maxim]\r\n    - Technical Information: added YM2413 information [Maxim]\r\n    - VGM Logging: frame-accurate VGMs are now quantized to the start of VBlank, not line 0 [Maxim]\r\n  - GUI:\r\n    - Disabled F10 key to quit emulator (regular ALT+F4 or OS close works). [Omar]\r\n    - Now possible to resize the game window and some of the tools. [Omar]\r\n    - Now possible to change the font of the tools in the .CFG file. [Omar]\r\n    - Made \"Ocean\" the default theme and increased default GUI resolution. [Omar]\r\n    - Made \"SMS Power! theme more readable. [Omar]\r\n    - TextInput: support for text selection, hold SHIFT+Left/Right keys to select text. [Omar]\r\n    - TextInput: support for CTRL+Left/Right to jump to previous/next word. [Omar]\r\n    - TextInput: support for clipboard (CTRL+X,CTRL+C,CTRL+V) shortcuts, tied to OS clipboard. [Omar]\r\n    - Depth order of windows is preserved accross sessions. [Omar]\r\n    - Increased mouse horizontal range when using scrollbars. [Omar]\r\n    - Added 'game_window_scale' directive on configuration file to resize game window. [Omar]\r\n    - Discontinued ALT+P (=F12) and CTRL+X (=F10) shortcuts. [Omar]\r\n    - Added ALT+V shortcut to start/stop VGM logging. [Omar]\r\n    - Menu entries display their shortcuts. Tidied up some menu entries. [Omar]\r\n    - Pressing DEL key in a text input box delete the character ahead of cursor. [Omar]\r\n    - FileBrowser: search for known extension when opening ZIP file (instead of picking first). [Maxim]\r\n    - FileBrowser: holding CTRL key while using the mouse wheel fasten scrolling. [Omar]\r\n    - FileBrowser: returning to parent directory position cursor on last child. [Omar]\r\n    - FileBrowser: BackSpace key is shortcut to return to parent directory. [Omar]\r\n    - FileBrowser: display JP flag when a game is JP/KR or JP/TW in the database. [Omar]\r\n    - FileBrowser: alphabetical shortcuts ignore disk drivers under Windows. [Omar]\r\n    - 3-D Glasses mode doesn't halve framerate of the interface anymore. [Omar]\r\n  - Sources/Development:\r\n    - Now build with a C++ compiler, fixed all incompatible C constructs + lots of cleanup.\r\n      Codebase can now freely take advantage of all C++ compiler features. [Omar]\r\n    - Added a batch script 'tools/dist_bin_win32.bat' to create binary Win32 package. [Omar]\r\n    - Removed #ifdef-out code that was used by the MS-DOS version. [Omar]\r\n    - Removed code for the old OPL3 based YM2413 emulator. [Omar]\r\n    - Removed easter egg code for emulating the NES. [Omar]\r\n    - Removed easter egg mini-games and various other obsolete features. [Omar]\r\n    - Removed mekaw.txt and mekanix.txt documentation files (obsolete). [Omar]\r\n    - (Win32) Updated project to using Visual Studio 2017. [Maxim]\r\n    - (Win32) Grabbing dependencies via nuget. [Maxim]\r\n    - (Win32) Using precompiled header for faster compilation (MSVC). [Omar]\r\n  - Configuration file is created early on startup if missing. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n          SMS - 6f8e46cf - Alex Kidd in Miracle World [SMS-GG] (TW) --> Alex Kidd in Miracle World [HTH] [SMS-GG] (TW) (labeling HTH release, listing them under SMS)\r\n          SMS - 58d5fc48 - Blade Eagle 3-D [Proto]              --> Blade Eagle 3-D [Proto 0] (later proto found)\r\n          SMS - c4bb1676 - E-SWAT [A]                           --> E-SWAT [v0]\r\n          SMS - c10fce39 - E-SWAT [B]                           --> E-SWAT [v1]\r\n          SMS - b7fe0a9d - King's Quest - Quest for t.. [Proto] --> King's Quest - Quest for the Crown [Proto 1] (earlier proto found)\r\n          SMS - 7e9d87fc - Monopoly [Proto]                     --> Monopoly [Proto 0] (later proto found)\r\n          SMS - d1a7b1aa - Olympic Gold (KR, BR)                --> Olympic Gold [v0]\r\n          SMS - 6a5a1e39 - Olympic Gold                         --> Olympic Gold [v1]\r\n          SMS - 327a0b4c - Paperboy (US)                        --> Paperboy [v1] (US, BR)\r\n          SMS - 07301f83 - Phantasy Star [Megadrive] (JP)       --> Phantasy Star Fukkokuban [SMS-MD] (JP) (standardizing 'SMS-MD' labeling)\r\n          SMS - 80eb1fff - Summer Games [Proto]                 --> Summer Games [Proto 1]\r\n          SMS - 55bf81a0 - Super Monaco GP                      --> Super Monaco GP [v0]\r\n          SMS - 3ef12baa - Super Monaco GP (US)                 --> Super Monaco GP [v1] (US)\r\n          SMS - 912d92af - Wimbledon                            --> Wimbledon [v1]\r\n          SMS - 4aaad0d6 - World Grand Prix (EU)                --> World Grand Prix [v0] (also in IT, DE)\r\n          SMS - 7b369892 - World Grand Prix (US)                --> World Grand Prix [v2] (also in BR, KR)\r\n          GG  - 1d17d2a0 - Aa Harimanada (JP)                   --> Aah! Harimanada (JP)\r\n          GG  - a6bf865e - Beavis and Butt-Head (MTV's) (EU)    --> Beavis and Butt-Head (MTV's) (US, EU)\r\n          GG  - 3858f14f - Beavis and Butt-Head (MTV's) (US)    --> Beavis and Butt-Head (MTV's) [Proto]\r\n          GG  - f3ca6676 - Columns (JP)                         --> Columns [v0]\r\n          GG  - 83fa26d9 - Columns                              --> Columns [v2]\r\n          GG  - 9a8b2c16 - Doraemon Nora No Suke No Yabou (JP)  --> GG Doraemon Nora No Suke No Yabou (JP)\r\n          GG  - 2e01ba6c - Joe Montana Football                 --> Joe Montana Football [v0]\r\n          GG  - 4a98678b - Joe Montana Football (JP)            --> Joe Montana Football [v1] (JP, BR)\r\n          GG  - a8ef36a7 - Junction                             --> Junction (JP)\r\n          GG  - 23f9150a - Kawasaki Superbike Challenge         --> Kawasaki Superbikes (EU) (now dumped US version)\r\n          GG  - c1756bee - Pete Sampras Tennis (EU, US)         --> Pete Sampras Tennis (EU) (now dumped US version)\r\n          GG  - a45fffb7 - Riddick Bowe Boxing                  --> Riddick Bowe Boxing (JP)\r\n          GG  - de25e2d8 - Sports Illustrated - Championship F..--> Sports Illustrated - Championship Football & Baseball [BAD] (was bad dump)\r\n          GG  - 5b5de94d - Sports Trivia - Championship Edition --> Sports Trivia - Championship Edition [Proto] (from old Image dump stash)\r\n          GG  - 661faeff - Super Monaco GP II (Ayrton...) (JP)  --> Super Monaco GP II (Ayrton Senna's) [v0] (JP) (discovered a v1)\r\n          GG  - ca0e11cc - Tesserae                             --> Tesserae [BAD] (corret dump is bf696f94)\r\n          GG  - e678f264 - Yogi Bear in Yogi Bears Goldrush..   --> Yogi Bear in Yogi Bear's Goldrush [Proto]\r\n          GG  - f397f041 - Zoop (US)                            --> Zoop [Proto] (US)\r\n          SG1 - 26f947d1 - Champion Boxing [cart]               --> Champion Boxing [v0]\r\n          SG1 - f8b2ac1d - Champion Boxing [card]               --> Champion Boxing [v1]\r\n          SG1 - 868419b5 - Champion Golf [cart]                 --> Champion Golf [v0]\r\n          SG1 - 5a904122 - Champion Golf [card]                 --> Champion Golf [v1]\r\n          SG1 - 5eb48a20 - Congo Bongo [v1]                     --> Congo Bongo [v0] (made a mistake originally ordering the versions. see thread on SMS Power! forum)\r\n          SG1 - 5a24c7cf - Congo Bongo [v0]                     --> Congo Bongo [v1]\r\n          SG1 - f7eb94c5 - Congo Bongo [v0] (TW)                --> Congo Bongo [v1] (TW)\r\n          OMV - 90160849 - 007 James Bond                       --> 007 James Bond [v2.7] (version v2.6 found)\r\n          OMV - 76d6c64d - 007 James Bond (TW)                  --> 007 James Bond [v2.7] (TW)\r\n          OMV - d5fdb4a3 - Space Armor [v0]                     --> Space Armor [v2.0] [v1] (earlier build found replacing [v0], v2.0 is found on title screen but doesn't differenciate both v20 builds)\r\n          OMV - ac4f0a5c - Space Armor [v1]                     --> Space Armor [v2.0] [v2]\r\n          SC3 - 22f4f92a - Nihonshi Nenpyou (JP)                --> Nihonshi Nenpyou [BAD] (JP) (was bad dump, correct dump confirmed multiple times)\r\n\r\n\r\n MEKA 0.74 WIP xxxxxxxx\r\n ----------------------\r\n  - (Win32) Updated project file to Visual Studio 2008 format + compilation fixes.\r\n  - (Win32) Updated Allegro library to 4.2.3 (using precompiled binary from 'allegro-msvc9-4.2.3').\r\n  - (Win32) Updated LibPNG library to 1.2.8 (precompiled binary package included in repository).\r\n  - (Win32) Including minimal DirectX 7.0 package (precompiled binary package 'dx70_min' included in repository)\r\n     because newer DirectX SDK tends to cause problem with 4.2.x Allegro branches.\r\n  - SC-3000:\r\n    - Fixed the ':' (colon) key not working on Sega Keyboard emulation under certain host keyboard/OS configuration. [Omar]\r\n  - GUI:\r\n    - Added Taiwanese flag (for DB and File Browser). [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n          SMS - 84665648 - Great Soccer (JP) [Hack]             --> Great Soccer (TW)\r\n          SMS - 656d1a3e - Hokuto no Ken [BAD] (CH)             --> Hokuto no Ken (TW) [Hack] (the \"bad\" data is on the original cart, but this version has additional modifications)\r\n          SMS - 69538469 - Monopoly [A]                         --> Monopoly (US)\r\n          SMS - 026d94a4 - Monopoly [B]                         --> Monopoly (EU)\r\n          SMS - 311d2863 - Prince of Persia [SMS-GG] [A]        --> Prince of Persia [SMS-GG] (US)\r\n          SMS - 45f058d6 - Prince of Persia [SMS-GG] [B]        --> Prince of Persia [SMS-GG] (EU)\r\n          SMS - 01686d67 - Suho Cheonsa (KR)                    --> Suho Jeonsa (KR)\r\n          SG1 - 868419b5 - Champion Golf [A]                    --> Champion Golf [cart]\r\n          SG1 - 5a904122 - Champion Golf [B]                    --> Champion Golf [card]\r\n          SG1 - fdc095bc - Doki Doki Penguin Land (HK)          --> Doki Doki Penguin Land (TW)\r\n          SG1 - 60f30138 - Dragon Wang [B]                      --> Dragon Wang [v0]\r\n          SG1 - 7c7d4397 - Dragon Wang (TW)                     --> Dragon Wang [v0] [chinese logo] (TW) (because a second Taiwanese version exists)\r\n          SG1 - 99c3de21 - Dragon Wang [A]                      --> Dragon Wang [v1]\r\n          SG1 - bd24d27b - Flicky                               --> Flicky [v0]\r\n          SG1 - 191ffe0a - GP World [A]                         --> GP World [v1]\r\n          SG1 - 191ffe0a - GP World [B]                         --> GP World [v0]\r\n          SG1 - 6d909857 - Mahjong                              --> Mahjong [small 1983]\r\n          SG1 - 8572d73a - Monaco GP [24k]                      --> Monaco GP [24k] [v0] [40k map]\r\n          SG1 - da2d57f3 - Monaco GP [32k]                      --> Monaco GP [32k] [v1] (provision for newly found [v2] build).\r\n          SG1 - 37fca2eb - Pitfall II ~The Lost Caverns~ [A]    --> Pitfall II ~The Lost Caverns~ [v0] (dumps and versionning finally confirmed)\r\n          SG1 - 3db74761 - Pitfall II ~The Lost Caverns~ [B]    --> Pitfall II ~The Lost Caverns~ [v1]\r\n          SG1 - 160535c5 - Wonder Boy [A]                       --> Wonder Boy [v0]\r\n          OMV - 90160849 - James Bond 007                       --> 007 James Bond\r\n          GG  - f85a8ce8 - 5 in 1 Fun Pak                       --> 5 in One Fun Pak\r\n          GG  - a6bf865e - Beavis and Butt-Head (MTV's)         --> Beavis and Butt-Head (MTV's)\r\n          GG  - 3858f14f - Beavis and Butt-head (MTV's) (US)    --> Beavis and Butt-head (MTV's) (US)\r\n          GG  - 03d28eab - Crayon Shin-chan - Taiketsu! Tankam..--> Crayon Shin-chan - Taiketsu! Kantamu Panic!! (JP) (embarassing typo)\r\n          GG  - 7ec95282 - Madoh Monogatari A [...] Bake~shon   --> Madoh Monogatari A - Doki Doki Vacation (JP)\r\n          GG  - 4e279baa - PGA TOUR Golf 2                      --> PGA TOUR Golf II\r\n          GG  - 786dd67b - Skweek (JP)                          --> Skweek [BAD] (JP)\r\n          GG  - 88618afa - Tails' Sky Patrol (JP)               --> Tails' Skypatrol (JP)\r\n          GG  - e678f264 - Yogi Bear [Proto]                    --> Yogi Bear in Yogi Bears Goldrush [Proto]\r\n    Other smaller changes not recorded, please refer to meka.nam SVN history for exact changes.\r\n\r\n\r\n MEKA 0.73 WIP 20100530\r\n ----------------------\r\n  - Updated MEKA license, data are now licensed under the same term as sources.\r\n    The license is now unrestrictive BSD-like. [Omar]\r\n  - Removed \"k\" and associated donation rambling from the documentation.\r\n    Donations are still welcome, at your own discretion.\r\n  - Emulation:\r\n    - Added support for \"no bank switching\" mapper. Used by Korean games such\r\n      as \"FA Tetris\" and \"Flash Point\" which write to $fffe-$ffff range for\r\n      its RAM usage but do not expect bank-switching. [Omar]\r\n    - Added support for Korean 8KB banks mapper. Used by Korean games ported\r\n      from MSX such as \"Penguin Adventure\", \"Street Master\" or \"Won-Si-In\". [Omar]\r\n  - GUI:\r\n    - Fixed Light Phaser and Terebi Oekaki cursor shape when switching from\r\n      32-bits GUI mode to 16-bits game only mode. [Omar]\r\n    - File browser: fixed positionning of BAD and HACK icons, which aren't\r\n      overlays anymore. [Omar]\r\n    - Added Canadian flag (for DB and File Browser). [Omar]\r\n    - Fixed crash when empty gradient range are specified in theme file. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n          SMS - b3768a7a - Bonkers Wax Up! (BR)                 --> Bonkers Wax Up! (Disney's) (BR)\r\n          SMS - 1b10a951 - Bram Stoker's Dracula                --> Dracula (Bram Stoker's)\r\n          SMS - c0e25d62 - California Games II                  --> California Games II [50 Hz]\r\n          SMS - 46340c41 - Cheese Cat-astrophe                  --> Cheese Cat-Astrophe - Starring Speedy Gonzales\r\n          SMS - 89b79e77 - Dodgeball King (KR)                  --> Dallyeora Pigu-Wang (KR)\r\n          SMS - b8b141f9 - Fantasy Zone II                      --> Fantasy Zone II - The Tears of Opa-Opa\r\n          SMS - c722fb42 - Fantasy Zone II (JP)                 --> Fantasy Zone II - Opa-Opa no Namida (JP)\r\n          SMS - 45c50294 - Jogos de Verão II                    --> California Games II [50-60 Hz] (also found in Korea).\r\n          SMS - 5b5f9106 - Nekyuu Kousien (JP)                  --> Nekkyuu Koushien (JP)\r\n          SMS - 0e333b6e - Miracle Warriors - Seal of the Dar.. --> Miracle Warriors - Seal of The Dark Lord (casing on 'The')\r\n          SMS - be57a9a5 - Pacmania                             --> Pac-Mania (the other way, sorry! It seems like the official name of the game)\r\n          SMS - 294e0759 - Paperboy                             --> Paperboy [v0] (scoring bug)\r\n          SMS - 327a0b4c - Paperboy (US)                        --> Paperboy [v1] (also found in Brasil)\r\n          SMS - 97d03541 - Sangokushi 3 (KR)                    --> Samgukji III (KR), Japanese Name \"Sangokushi III\".\r\n          SMS - e1fff1bb - Shinobi (JP)                         --> Shinobi [v0] (also found in Brasil in Game Box Serie Lutas compilation)\r\n          SMS - 0c6fac4e - Shinobi                              --> Shinobi [v1]\r\n          SMS - c93bd0e9 - Slap Shot [B]                        --> Slap Shot [v0]\r\n          SMS - d33b296a - Slap Shot [A]                        --> Slap Shot [v1]\r\n          SMS - 702c3e98 - Slap Shot (US)                       --> Slap Shot [v2] (US)\r\n          SMS - 93ca8152 - T2 - The Arcade Game                 --> T2: The Arcade Game\r\n          SMS - 11ce074c - Taz in Escape From Mars              --> Taz in Escape from Mars\r\n          SMS - ac56104f - Terminator 2 - Judgment Day          --> Terminator 2: Judgment Day\r\n          SMS - bf7b7285 - Tom and Jerry - The Movie            --> Tom and Jerry: The Movie\r\n          SMS - 0c2fc2de - Tom and Jerry - The Movie [Proto]    --> Tom and Jerry: The Movie [Proto]\r\n          SMS - 20f40cae - Vampire                              --> Master of Darkness / Vampire [Proto]\r\n          GG  - f85a8ce8 - 5 in 1 Fun Pak                       --> 5-in-1 FunPak\r\n          GG  - 8d8bfdc4 - Baku Baku Animal (US)                --> Baku Baku (US)\r\n          GG  - 10ac9374 - Baku Baku Animal (EU)                --> Baku Baku (EU)\r\n          GG  - a6bf865e - Beavis and Butt-head                 --> Beavis and Butt-head (MTV's)\r\n          GG  - 325b1797 - Berlin no Kabe - The Berlin Wall (JP)--> Berlin no Kabe - The BerlinWall (JP) (clearly spelled without space)\r\n          GG  - bfceba5f - Bonkers Wax Up!                      --> Bonkers Wax Up! (Disney's)\r\n          GG  - 69ebe5fa - Bram Stoker's Dracula                --> Dracula (Bram Stoker's)\r\n          GG  - 2c758fc8 - Cool Spot                            --> Cool Spot (US)\r\n          GG  - 03d28eab - Crayon Shin Chan - Taiketsu! T.. (JP)--> Crayon Shin-chan - Taiketsu! Tankam Panic!!\r\n          GG  - 4457e7c0 - Donald Duck no Yottsu no Himitsu (JP)--> Donald Duck no Yottsu no Hihou (JP)\r\n          GG  - 19e1cf2b - Dragon Crystal - Tsurani no M.. (JP) --> Dragon Crystal - Tsurani no Meikyuu (JP)\r\n          GG  - 152f0dcc - Drop Zone                            --> Dropzone (Archer MacLean's)\r\n          GG  - 5d3f23a9 - Earthworm Jim                        --> Earthworm Jim (US)\r\n          GG  - 2b60873e - Ecco the Dolphin                     --> Ecco the Dolphin [BAD]\r\n          GG  - d0a93e00 - F1                                   --> Formula One / F1 (alternative names)\r\n          GG  - d69097e8 - Fantasy Zone Gear                    --> Fantasy Zone / Fantasy Zone Gear - Opa Opa Jr. no Bouken\r\n          GG  - 449787e2 - Fatal Fury Special                   --> Fatal Fury Special (US)\r\n          GG  - 751dad4c - From TV animation - Slam Dunk.. (JP) --> Slam Dunk - Shouri-e no Starting 5 (From TV animation) (JP)\r\n          GG  - 695cc120 - GG Portrait - Pai Chan (JP)          --> GG Portrait - Pai Chen (JP)\r\n          GG  - 4cf97801 - Godzilla - Kaiju Dai-Shingeki (JP)   --> Godzilla - Kaijuu Daishingeki (JP)\r\n          GG  - 398f2358 - Kuni Chan's Game Paradise (JP)       --> Kuni Chan no Game Tengoku (JP)\r\n          GG  - f3774c65 - Kuni Chan's Game Paradise 2 (JP)     --> Kuni Chan no Game Tengoku Part 2 (JP)\r\n          GG  - 42389270 - Hyokkori Hyoutan Jima (JP)           --> Hyokkori Hyoutan Jima - Hyoutan Jima no Daikouka (JP)\r\n          GG  - 9fb5c155 - James Pond II - Codename: Robocod    --> James Pond II - Codename: Robocod (US)\r\n          GG  - 30c09f31 - Jungle Book, The (Walt Disney'..(US) --> Jungle Book, The (Walt Disney's) (US) (US version do not mention 'Classic'. Alternate name have only 'Disney's').\r\n          GG  - 87b8b612 - McDonald's - Donald no Magical World --> Donald no Magical World (Ronald in the Magical World) (JP) (Japanese only release, Western name is unused)\r\n          GG  - 75c71ebf - Madden NFL '95                       --> Madden NFL 95\r\n          GG  - 00c34d94 - Madoh Monogatari I - Mittsu no..(JP) --> Madoh Monogatari I - Mittsu no Madoukyuu (JP)\r\n          GG  - 0a634d79 - Madoh Monogatari III - K.. [v0] (JP) --> Madoh Monogatari III - Kyuukyoku Joou-sama [v0] (JP)\r\n          GG  - 568f4825 - Madoh Monogatari III - K.. [v1] (JP) --> Madoh Monogatari III - Kyuukyoku Joou-sama [v1] (JP)\r\n          GG  - 7ec95282 - Madoh Monogatari A - Dokidoki.. (JP) --> Madoh Monogatari A - Doki Doki Bake~shon (JP)\r\n          GG  - 8f82a6b9 - Magic Knight Ray Earth (JP)          --> Magic Knight Rayearth (JP)\r\n          GG  - 1c2c2b04 - Magic Knight Ray Earth 2 ~mak.. (JP) --> Magic Knight Rayearth 2 ~making of magic knight~\r\n          GG  - 6e1cc23c - Magical Taruruto-kun (JP)            --> Magical Taruruuto-kun (JP)\r\n          GG  - 2e4ec17b - Megami Tensei Gaiden Last Bible (JP) --> Megami Tensei Gaiden: Last Bible (JP)\r\n          GG  - 4ec30806 - Megami Tensei Gaiden Last Bibl..(JP) --> Megami Tensei Gaiden: Last Bible Special (JP)\r\n          GG  - 4d5d15fb - Moldorian (JP)                       --> Moldorian ~Hikari to Yami no Shisutaa~ (JP)\r\n          GG  - dbff0461 - Mortal Kombat (JP)                   --> Mortal Kombat - Shinken Kourin Densetsu (JP)\r\n          GG  - 54ab42a4 - Nazo Puyo Aruru no Ru (JP)           --> Nazo Puyo Aruru no Ruu (JP)\r\n          GG  - 4c874466 - Nazo Puyo Aruru no Ru [Editor.. (JP) --> Nazo Puyo Aruru no Ruu [Editor Proto] (JP)\r\n          GG  - 3679be80 - Neko Daisuki! (JP)                   --> Neko Dai Suki! (JP)\r\n          GG  - c3056e15 - Ninku (JP)                           --> Ninkuu (JP)\r\n          GG  - 06247dd2 - Ninku 2 ~Tenkuryu-e no Michi~ (JP)   --> Ninkuu 2 ~Tenkuuryuu-e no Michi~ (JP)\r\n          GG  - 9140f239 - Ninku Gaiden - Hiroyuki Daika.. (JP) --> Ninkuu Gaiden - Hiroyuki Daikatsugeki\r\n          GG  - 19030108 - NBA Action                           --> NBA Action - Starring David Robinson\r\n          GG  - 4680c7aa - NHL All Stars                        --> NHL All-Star Hockey\r\n          GG  - a2f9c7af - Olympic Gold [SMS-GG] [B]            --> Olympic Gold [v0] [SMS-GG]\r\n          GG  - 1d93246e - Olympic Gold [SMS-GG] [A]            --> Olympic Gold [v1] [SMS-GG]\r\n          GG  - d58cb27c - Out Run                              --> Out Run (JP)\r\n          GG  - f037ec00 - Out Run Europa [SMS-GG]              --> Out Run Europa [SMS-GG] (US)\r\n          GG  - a16c5e58 - Pac-Man                              --> Pac-Man (JP)\r\n          GG  - b42d8430 - Pet Club Inu Daisuki! (JP)           --> Pet Club Inu Dai Suki! (JP) (coherent with Neko Dai Suki!)\r\n          GG  - 3ef66810 - Popeye's Beach Volleyball (JP)       --> Popeye Beach Volley Ball (JP)\r\n          GG  - d173a06f - Puzlow Kids / Puyo Puyo              --> Puyo Puyo (Puzle Kids) (JP) (Japanese only release, Western name is unused)\r\n          GG  - 96045f76 - Road Rash                            --> Road Rash (US)\r\n          GG  - 445d7cd2 - Royal Stone ~Hikarishi Toki n.. (JP) --> Royal Stone ~Hirakareshi Toki no Tobira~ (JP)\r\n          GG  - fe7374d2 - Sailor Moon S (JP)                   --> Bishoujo Senshi Sailor Moon S (JP)\r\n          GG  - 2ae8c75f - Shanghai II (JP)                     --> Shanghai II [v0] (JP)\r\n          GG  - 9c5c7f53 - Shikinjou (JP)                       --> Shikinjo (JP) (official transcription)\r\n          GG  - 0f3e3840 - Sokoban World (JP)                   --> Soukoban (JP)\r\n          GG  - d23a2a93 - Sonic Triple Trouble                 --> Sonic The Hedgehog Triple Trouble\r\n          GG  - 80156323 - Star Trek The Next Generation - Th.. --> Star Trek: The Next Generation - The Advanced Holodeck Tutorial\r\n          GG  - 1ebfa5ca - Strider Returns                      --> Strider Returns (Journey from Darkness)\r\n          GG  - 2ea26930 - Surf Ninjas                          --> Surf Ninjas [BAD] (confirmed correct dump)\r\n          GG  - 9479c83a - T2 - The Arcade Game                 --> T2: The Arcade Game\r\n          GG  - cf9c607c - Taisen Mahjong HaoPai (JP)           --> Taisen Mahjong Hao-Pai (JP)\r\n          GG  - 20527530 - Taisen Mahjong HaoPai 2 (JP)         --> Taisen Mahjong Hao-Pai 2 (JP)\r\n          GG  - dd1d2ebf - Tama & Friends - 3chome Koen.. (JP)  --> Tama & Friends - 3 Choume Kouen Tamalympic (JP)\r\n          GG  - eebad66b - Taz in Escape From Mars              --> Taz in Escape from Mars\r\n          GG  - 1bd15773 - Terminator 2 - Judgment Day          --> Terminator 2: Judgment Day\r\n          GG  - a1453efa - Tom and Jerry - The Movie (JP)       --> Tom and Jerry: The Movie\r\n          GG  - 5cd33ff2 - Tom and Jerry - The Movie            --> Tom and Jerry: The Movie (US)\r\n          GG  - 7ec64025 - Vampire - Master of Darkness         --> Vampire - Master of Darkness (US)\r\n          GG  - 9977fcb3 - Wonder Boy                           --> Wonder Boy (JP)\r\n          GG  - d9ce3f4c - Yaiba Adventures (JP)                --> Kenyuu Densetsu Yaiba (JP)\r\n          GG  - 88ebbf9e - Yuu Yuu Hakusho (JP)                 --> Yu Yu Hakusho - Horobishi Mono no Gyakushuu (JP)\r\n          GG  - 46ae9159 - Yuu Yuu Hakusho II (JP)              --> Yu Yu Hakusho II - Gekitou! Nanakyou no Tatakai (JP)\r\n          SG  - 37fca2eb - Pitfall II [A]                       --> Pitfall II ~The Lost Caverns~ [A]\r\n          SG  - 3db74761 - Pitfall II [B]                       --> Pitfall II ~The Lost Caverns~ [B]\r\n          SG  - 5a917e06 - Shinnyushain Tooru Kun (Konami no)   --> Shinnyuushain Tooru-Kun (Konami no)\r\n          OMV - 77db4704 - Q*Bert                               --> Q*bert\r\n\r\n\r\n MEKA 0.73 WIP 20080619\r\n ----------------------\r\n  - Localization:\r\n    - Updated Dutch localization [Mark van Tilburg]\r\n  - SC-3000:\r\n    - Fixed the ;/+/RAD key not working on Sega Keyboard emulation under\r\n      certain host keyboard/OS configuration. Thanks Jacko. [Omar]\r\n    - Fixed crash in the X86 assembly implementation of the 32KB RAM mapper\r\n      writer when the upper 16 bits were not cleared by the Z80 emulator. [Omar]\r\n  - Debugger:\r\n    - Added \"SYM @addr\" command to search for symbols given an address. [Omar]\r\n    - Added \"RMAP addr\" command to reverse map of a Z80 address and display\r\n      the source of data based on machine state (mapper registers, etc).\r\n      eg:\r\n        RMAP $8001      ; eg: print 'ROM $14001 (Page 5 +0001)'\r\n        RMAP $E001      ; eg: print 'RAM $C001'\r\n      The feature doesn't work 100% in all mappers & bus mirroring cases,\r\n      but should be ok with the standard SMS/GG mapper. [Omar]\r\n    - Duplicate commands are automatically removed from history. [Omar]\r\n    - Increased default height of the debugger. [Omar]\r\n    - Changed watch point per-frame flood limit from 100 to 50. Will expose in\r\n      configuration file if requested. [Omar]\r\n    - Fixed crash when loading symbols with debugger disabled. [Djbass,Omar]\r\n    - Fixed labels showing one instruction early in \"DASM\" command. [Omar]\r\n    - Added breakpoint '!' mark in disassembly window. [Omar]\r\n  - GUI:\r\n    - File browser: country flag now displayed even on BIOS, Prototypes\r\n      or Homebrew images. [Omar]\r\n    - Inputs configuration: right-click on input source selection goes\r\n      backward, in addition to regular left-click to go forward. [Omar]\r\n  - Miscellaenous:\r\n    - Added \"Capture\" menu with screen capture menu access and options. [Maxim]\r\n    - Added \"Capture All\" mode, capturing all emulation frames to disk. [Maxim]\r\n    - Added \"Include GUI\" capture option. Disable to only capture game screen\r\n      when MEKA GUI is enabled. [Maxim]\r\n    - Renamed \"Automatically crop and align screen captures\" option to\r\n      more explicit \"Crop and align screen captures to 8x8 boundaries\".\r\n      Previous name was sounding too \"cool\" and was sometimes activated\r\n      by innocent users who then got their capture all cropped. [Omar]\r\n    - Added \"screenshots_crop_scrolling_column\" option in configuration\r\n      file (default to enabled), to disable cropping the empty left-most\r\n      column in horizontally scrolling games. [Omar]\r\n  - Project:\r\n    - (Win32) Fixed standard libraries used by debug builds (using unusual\r\n      combination led to various problems). Fixed various link warnings.\r\n      Fixed shared directories between DLL and No DLL builds. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n          SMS - d91b340d - Action Fighter (JP)                  --> Action Fighter [v1] (also released in Germany and Italia)\r\n          SMS - 3658f3e0 - Action Fighter                       --> Action Fighetr [v2]\r\n          SMS - f4b3a7bd - Ariel - The Little Mermaid (BR)      --> Ariel - The Little Mermaid (Disney's) (BR)\r\n          SMS - e2fcb6f3 - Super Wonder Boy (JP)                --> Wonder Boy [v0] (also released in Italia)\r\n          SMS - 73705c02 - Wonder Boy                           --> Wonder Boy [v1]\r\n          GG  - 3e549b7a - Aerial Assault                       --> Aerial Assault [v0]\r\n          GG  - ffe4ed47 - Alien Syndrome                       --> Alien Syndrome (JP)\r\n          GG  - 97e3a18c - Ariel - The Little Mermaid           --> Ariel - The Little Mermaid (Disney's)\r\n          GG  - e123d9b8 - Fray (JP)                            --> Fray ~Shugyou hen~ (JP)\r\n          GG  - a93e8b0f - Griffin                              --> Griffin (JP)\r\n          GG  - 75e273eb - Madden '96                           --> Madden 96 [BAD]\r\n          GG  - 36ebcd6d - Majors Pro Baseball                  --> Majors Pro Baseball, The\r\n          GG  - f1732ffe - TaleSpin                             --> TaleSpin (Disney's)\r\n          GG  - 7ec64025 - Vampire: Master of Darkness          --> Vampire - Master of Darkness\r\n\r\n\r\n MEKA 0.72\r\n ---------\r\n  Includes all 0.72 WIP below, minus lines starting with hash characters\r\n  (those lines refer to fixes relative to changes in a WIP).\r\n\r\n\r\n MEKA 0.72 WIP 20070512\r\n ----------------------\r\n  - ColecoVision:\r\n    - Removed detection of supposed 128-bytes headers and 512-bytes footers\r\n      (from some old soft/copiers?), due to many false detections,\r\n      particularly on homebrew ROM images (the code was introduced in 2001\r\n      when Dig Dug and Pac-Man prototypes were released with such header,\r\n      but ROM images now circulating are without the header). [Omar]\r\n\r\n\r\n MEKA 0.72 WIP 20070508\r\n ----------------------\r\n  - Ports:\r\n    - Preliminary MacOSX port. [Proppy]\r\n      Compile and run under a x86-based MacOSX system. Missing sound (due\r\n      to Seal) and debugger (unknown problem to resolve).\r\n      Looking for someone who wish to improve and maintain this port.\r\n  - Blitter/Video:\r\n    - Fixed HQ2X stretched blitter when target output was not 16-bits. [Omar]\r\n#   - Fixed TV Mode blitters broken since since switching to hi-color.\r\n      Implementation is slower than previously, but it works well. [Omar]\r\n    - Removed obsolete \"scanlines\" blitter, in favor of \"tvmode\". [Omar]\r\n    - Stretching works on all blitters. [Omar]\r\n    - Video depth, Vsync, Triple Buffering and Page flipping are now global\r\n      video settings, removed from each specific blitter. Greatly simplify\r\n      configuration and tweaking. [Omar]\r\n    - Triple buffering doesn't interfere with the refresh is not supported\r\n      by the current settings (eg: windowed mode), making it safe and more\r\n      simple to always leave it enabled. [Omar]\r\n  - CPU:\r\n    - Z80: Fixed RETI behavior (same as RETN, copying IFF2 to IFF1).\r\n      Fixes pausing in SMS Robocop 3 during legal screens/introduction,\r\n      probably other infrequent cases. [FluBBa, Omar]\r\n    - Z80: Accepting NMI doesn't copy IFF1 over IFF2, as suggested\r\n      by Sean Young's \"The Undocumented Z80 Documented\". [Omar]\r\n  - ColecoVision:\r\n    - Fixed emulation of pending NMI, pending flag is cleared when\r\n      reading VDP status. Fixes \"Rock 'N Bolt\" among other.\r\n      Thanks to the anonymous poster on SMS Power! forums. [Omar]\r\n    - Note that the compatibility list for ColecoVision titles is\r\n      severly outdated. At some point, James Carter worked on a new,\r\n      more accurate list, but I lost all contact with him.\r\n  - NES:\r\n    - Fixed video rendering, broken when switching to hi-color modes. [Omar]\r\n    - Added PRAM support in Memory Editor. [Omar]\r\n    - Added 8 palette switching in Tile Viewer. [Omar]\r\n    - Note: NES emulation is humor legacy code and won't be supported.\r\n  - GUI:\r\n    - Sorted default themes, removed non Sega 8-bit related themes.\r\n      Now embedding background pictures in regular binary distribution.\r\n      CALL FOR NEW OR IMPROVED THEMES SUBMISSION! Please contribute.\r\n\r\n\r\n MEKA 0.72 WIP 20070426\r\n ----------------------\r\n  - CPU:\r\n    - Z80: Fixed cases were address arithmetic would not wrap in the\r\n      16-bit address space, effectively crashing the emulator (those cases\r\n      were mostly happening on corrupted data, but it also legit Z80 code,\r\n      and in any case we don't want the emulator to crash). [Omar]\r\n  - Tilemap viewer:\r\n##  - Fixed leftover of white rectangle when mouse hover last line. [Omar]\r\n  - Debugger:\r\n    - Added \"B nopnop\" shortcut to break on two successives NOP instructions.\r\n      This is basically equivalent to \"B x =0,0\". [Omar]\r\n  - Miscellaenous:\r\n    - Increased max length of directory/filenames. [Musuruan]\r\n    - Added \"Automatically crop and align screen captures\" option.\r\n      This option aligns screen captures on the nearest visible tile,\r\n      helping to simplify the process of creating game maps by pasting\r\n      captures next to each other. [Omar]\r\n      Note: May not work properly on game using scanline based effects.\r\n##- Added and modified entries in the checksum and compatibility lists. [Omar]\r\n##  Some particular renaming includes:\r\n          SMS - 65d7e4e0 - Fantasy Zone                         --> Fantasy Zone [v2]\r\n          SMS - 60c19645 - Zillion                              --> Zillion [v0]\r\n          SMS - 5718762c - Zillion (US)                         --> Zillion [v1] (US)\r\n          GG  - 7a41c1dc - Aladdin                              --> Aladdin (Disney's)\r\n          GG  - 770e95e1 - Aladdin (JP)                         --> Aladdin (Disney's) (JP)\r\n          GG  - 4457e7c0 - Deep Duck Trouble / Donald Duck no.. --> Donald Duck no Yottsu no Himitsu (JP) (was Japanese dump)\r\n          GG  - 36aaf536 - Evander Holyfield Boxing             --> Evander Holyfield's \"Real Deal\" Boxing\r\n          GG  - 8c048325 - Indiana Jones and the Last Crusade   --> Indiana Jones and the Last Crusade [BAD]\r\n          GG  - 4a98678b - Joe Montana Football                 --> Joe Montana Football (JP)\r\n          GG  - 00c34d94 - Madou Monogatari I - Mittsu no.. (JP)--> Madoh Monogatari I - Mittsu no Madokyuu (JP)\r\n          GG  - 12eb2287 - Madou Monogatari II - Aruru 16.. (JP)--> Madou Monogatari II - Aruru 16-sai (JP)\r\n          GG  - 0a634d79 - Madou Monogatari III - Kyukyok.. (JP)--> Madou Monogatari III - Kyuukyoku Joo-sama [v0] (JP)\r\n          GG  - 7ec95282 - Madou Monogatari A - Dokidoki-.. (JP)--> Madoh Monogatari A - Dokidoki-Bake Shon\r\n          GG  - afcc7828 - Psychic World                        --> Psychic World (JP)\r\n          GG  - 2ae8c75f - Shanghai 2 (JP)                      --> Shanghai II (JP)\r\n          GG  - 4d1f4699 - Shining Force Gaiden (JP)            --> Shining Force Gaiden ~Ensei Jashin no Kuni e~ (JP)\r\n          GG  - 30374681 - Shining Force Gaiden II (JP)         --> Shining Force Gaiden II ~Jashin no Mezame~ (JP)\r\n          GG  - 6019fe5e - Shining Force Gaiden Final Con.. (JP)--> Shining Force Gaiden ~Final Conflict~ (JP)\r\n          GG  - 742a372b - Spider-Man and the X-Men in Arcade'..--> Spider-Man / X-Men: Arcade's Revenge\r\n          GG  - f1732ffe - Tale Spin                            --> TaleSpin\r\n          SG1 - 545fc9bb - Ashizawa Hachidan no Tsumeshogi (JP) --> Serizawa Hachidan no Tsumeshogi (JP)\r\n          SG1 - 6d909857 - Sega Mah-Jong (JP)                   --> Mahjong (Sega) (JP)\r\n          SG1 - e7e0f0e3 - Home Mah-Jong (JP)                   --> Home Mahjong [v1] (JP)\r\n\r\n\r\n MEKA 0.72 WIP 20061217\r\n ----------------------\r\n  - Updated k.\r\n  - Emulation:\r\n    - Fixed data corruption/overflow in VDP emulation when seeking and\r\n      writing to an invalid palette address. Thanks Maxim. [Omar]\r\n    - VDP palette write do not mask out current VDP address, so performing\r\n      the (unprobable) set address/access palette/access VRAM sequence will\r\n      keep address in the full 16KB range. [Omar]\r\n    - Fixed VDP line interrupts not properly running in overscan area in\r\n      224 lines mode. Fixes bottom of the screen in Charles Mac Donald's\r\n      BB2K6 demo. [Omar]\r\n  - Video:\r\n    - Changed default fullscreen blitter configuration in the hope of getting\r\n      something more compatible (640x480 by default), as so many people have\r\n      problems with fullscreen modes.\r\n    - Got rid of \"parallel\" blitter that displayed both odd and even frame\r\n      next to each other. Seems useless now. Could be brought back if some\r\n      four-eyed person request it. [Omar]\r\n  - Debugger:\r\n    - Added CLOCK command, to display/reset a Z80 cycle counter.\r\n      Very simple but can be helpful to time Z80 routines. [Omar]\r\n    - (Win32) Forward debugging log to Windows debugging stream via\r\n      OutputDebugString(), so running MEKA from Microsoft Visual studio\r\n      will display log in the 'Output' window. [Omar]\r\n##- Project:\r\n    - (Win32) Added new targets supporting shared standard libraries. [Omar]\r\n    - Updated SOURCES.TXT documentation. [Omar]\r\n##- GUI:\r\n##  - Fixed background picture not loading on startup. [Omar]\r\n    - Removed closing fadeout since the current implementation is way\r\n      inefficient and cannot garantee proper speed. [Omar]\r\n##- Added and modified entries in the checksum and compatibility lists. [Omar]\r\n##  Some particular renaming includes:\r\n          SMS - e5ff50d8 - Back to the Future II                --> Back to the Future Part II\r\n          SMS - 2d48c1d3 - Back to the Future III               --> Back to the Future Part III\r\n          SMS - b9db4282 - Castle of Illusion (US)              --> Castle of Illusion - Starring Mickey Mouse [v0]\r\n          SMS - 953f42e1 - Castle of Illusion                   --> Castle of Illusion - Starring Mickey Mouse [v1]\r\n          SMS - 59840fd6 - Castle of Illusion [SMS-GG]          --> Castle of Illusion - Starring Mickey Mouse [SMS-GG]\r\n          SMS - 9942b69b - Castle of Illusion [SMS-GG] (JP)     --> Castle of Illusion - Starring Mickey Mouse [SMS-GG] (JP)\r\n          SMS - 42fc3a6e - Deep Duck Trouble                    --> Deep Duck Trouble - Starring Donald Duck\r\n          SMS - 695a9a15 - Jungle Book, The                     --> Jungle Book, The (Walt Disney's Classic)\r\n          SMS - 24e97200 - Land of Illusion                     --> Land of Illusion - Starring Mickey Mouse\r\n          SMS - 6350e649 - Legend of Illusion (BR)              --> Legend of Illusion - Starring Mickey Mouse (BR)\r\n          SMS - c352c7eb - Lion King, The                       --> Lion King, The (Disney's)\r\n          SMS - 1de2c2d0 - Strategic Defense Initiative (JP)    --> SDI (JP)\r\n          GG  - bb4f23ff - Adventures of Batman and Robin       --> Adventures of Batman & Robin, The\r\n          GG  - 90100884 - Jungle Book, The                     --> Jungle Book, The (Walt Disney's Classic)\r\n          GG  - 30c09f31 - Jungle Book, The (US)                --> Jungle Book, The (Walt Disney's Classic) (US)\r\n          GG  - 52dbf3e1 - Land of Illusion                     --> Land of Illusion - Starring Mickey Mouse\r\n          GG  - 0117c3df - Land of Illusion (JP)                --> Mickey Mouse no Mahou no Crystal (JP)\r\n          GG  - 0cd9c20b - Lion King, The                       --> Lion King, The (Disney's) (EU)\r\n          GG  - 9808d7b3 - Lion King, The (US)                  --> Lion King, The (Disney's) (US)\r\n          GG  - cc90c723 - Pocket Jong Sou (JP)                 --> Pocket Jansou (JP)\r\n          GG  - 445d7cd2 - Royal Stone (JP)                     --> Royal Stone ~Hikarishi Toki no Tobira~ (JP)\r\n          GG  - 95efd52b - Ryu Kyu (JP)                         --> Ryuu Kyuu (JP)\r\n          GG  - 09f9ed60 - Shadam Crusader (JP)                 --> Shadam Crusader ~Harukanaru Oukoku~ (JP)\r\n          SG1 - 545fc9bb - Ashizawa's Hatchidan Tsumeshogi (JP) --> Ashizawa Hachidan no Tsumeshogi (JP)\r\n          SG1 - 5970a12b - Champion Baseball                    --> Champion Baseball [16k]\r\n          SG1 - 09196fc5 - N-Sub (1988)                         --> N-Sub [16k] (1988)\r\n          SC3 - 622010e1 - Sega Music Editor                    --> Music\r\n          SC3 - b67ea1c4 - Sega Music Editor                    --> Music [BAD]\r\n          SC3 - 2ec28526 - Sega Music Editor (JP)               --> Music (JP)\r\n          SC3 - ae4f92cf - Uranai Angel Cuty (JP)               --> Uranai Angel Cutie (JP)\r\n\r\n\r\n MEKA 0.72 WIP 20051203\r\n ----------------------\r\n##- GUI:\r\n##  - Fixed bug with window closing button widget. [Omar]\r\n##  - Fixed bug when quitting using the menu, configuration files were\r\n##    not saved. Thanks Jacko. [Omar]\r\n##  - (Un*x) Fixed bug where menus would not clear themselves. [Omar]\r\n##    (This was due to Allegro.h defining TRUE as -1 and a 1 value being\r\n##    hardcoded in some part of the code).\r\n\r\n\r\n MEKA 0.72 WIP 20051120\r\n ----------------------\r\n  - (Win32) Updated Allegro library from WIP 4.1.18 to 4.2.0, including\r\n    various fixes/improvements:\r\n        http://www.talula.demon.co.uk/allegro/onlinedocs/en/changes.html\r\n  - Sound:\r\n    - Added support for VGM 1.10 header type. [Omar]\r\n  - GUI:\r\n##  - Added support for horizontal scrollbars. [Omar]\r\n##  - Fixed scrollbars non refreshing when scrolling with keyboard. [Omar]\r\n    - Added link to debugger documentation in HELP menu. [Omar]\r\n  - Development:\r\n    - Debugger:\r\n      - Fixed various command-line parsing bugs. [Omar]\r\n      - Added conditionnal breakpoints. [Omar]\r\n        eg:\r\n          BREAK r C000.. =01,02,03,04   ; break on read of 01020304 in RAM\r\n          BREAK x =C9                   ; break on CPU execution of RET\r\n          BREAK x =0,0                  ; break on CPU execution of NOP NOP\r\n          BREAK w pram 0 =03            ; break on PRAM write of color 0 as red\r\n      - Added display line event breakpoints/watchpoints. [Omar]\r\n        Useful for debugging line interrupts.\r\n        eg:\r\n          BREAK line #13                ; break on display line 13\r\n    - Tilemap viewer:\r\n##    - Added support for manually selecting map address. [Omar]\r\n##    - Added (partial) support for overscan video modes (used by CodeMasters\r\n##      games). The bottom of the 32x32 tilemap is not yet shown thought. [Omar]\r\n##    - Removed drawing of horizontal screen border lines on raster effects,\r\n##      was indeed very confusing to understand. [Omar]\r\n##    - Support for top rows horizontal scroll lock bit. [Omar]\r\n  - Miscellaenous:\r\n    - Various fixes.\r\n    - (UN*X) Renamed main executable to 'meka' (instead of 'meka.exe').\r\n##- Added and modified entries in the checksum and compatibility lists. [Omar]\r\n##  Some particular renaming includes:\r\n      SMS - 0e21e6cf - Astro Flash (JP)                     --> Astro Flash [Hack] (JP)\r\n      SMS - 5d08e823 - Fushigi no Oshiro Pit Pot (JP)       --> Fushigi no Oshiro Pit Pot [Hack] (JP)\r\n      SMS - a4ac35d8 - Galaxy Force [50 / 60 Hz]            --> Galaxy Force\r\n      SMS - 6c827520 - Galaxy Force [60 Hz]                 --> Galaxy Force (US)\r\n      SMS - dabcc054 - Ghost house (JP)                     --> Ghost House [Hack] (JP)\r\n      SMS - c1e699db - Great Baseball [JP] (JP)             --> Great Baseball [JP] [Hack] (JP)\r\n      SMS - 84665648 - Great Soccer (JP)                    --> Great Soccer [Hack] (JP)\r\n      SMS - 87b9ecb8 - Satellite 7 (JP)                     --> Satellite 7 [Hack] (JP)\r\n      SMS - bcd91d78 - Seishun Scandal (JP)                 --> Seishun Scandal [Hack] (JP)\r\n      SMS - a71bc542 - Spy vs Spy (JP)                      --> Spy vs Spy [Hack] (JP)\r\n      SMS - 95cbf3dd - Super Tennis (JP)                    --> Great Tennis / Super Tennis (JP) (note: this one is tricky. Official game name is \"Great Tennis\" but title screen says \"Super Tennis\").\r\n      SMS - 9dfa67ee - Teddy Boy Blues (JP)                 --> Teddy Boy Blues [Hack] (JP)\r\n      GG  - f6af4b6b - Dynamite Headdy                      --> Dynamite Headdy (JP) (note: US/EU version is another dump)\r\n\r\n\r\n MEKA 0.72 WIP 20050918\r\n ----------------------\r\n  - Miscellaenous:\r\n##  - Fixed screenshots being fully transparent. [Omar]\r\n    - Updated various tidbits in the configuration file. [Omar]\r\n  - Development:\r\n    - Added tilemap viewer. [Omar]\r\n      - Shows tilemap, hovering or clicking a tile shows specific info\r\n        about it, allows filtering BG/FG, disabling tile flipping, display\r\n        of scrolling box, with or without raster effects, manual selection\r\n        of tilemap address, etc.\r\n    - Cleaned Technical Information Viewer content, renamed a few fields\r\n      to their official names, removed redundant information. It's not\r\n      yet all clean. [Omar]\r\n\r\n\r\n MEKA 0.72 WIP 20050910\r\n ----------------------\r\n  - Development:\r\n    - Debugger:\r\n      - Added line history. Navigate history by pressing Up/Down.\r\n        List or search in history using HISTORY (HI) command. [Omar]\r\n##- Fixed various bugs: scrollbar display during theme switch,\r\n##  memory editor scrollbar crashing, etc.\r\n  - Sources/Project\r\n    - (Win32) Now linking to zlib.lib instead of zlibs.lib (name for standard\r\n       static build of ZLIB). [Omar]\r\n\r\n\r\n MEKA 0.72 WIP 20050904\r\n ----------------------\r\n  - Video:\r\n    - Upgraded everything to hi-color video modes and got rid of old,\r\n      8-bit indexed video modes. This is a major change in MEKA core.\r\n      Some of the benefits are:\r\n      - No more snow and/or color flickering on video card drivers\r\n        which disliked palette changes.\r\n      - Better integration with desktop (usually run faster).\r\n      - Getting possible to use various kind of graphics filters.\r\n      - No more hassle with color limitation for the programmer\r\n        (meaning more features implemented for the end-user).\r\n      - Finally possible to show all Game Gear colors at once,\r\n        and to implement LCD screen persistence (not yet done).\r\n      Some of the features above goes hand to hand with the blitter\r\n      system, which will be improved soon. [Omar]\r\n  - GUI:\r\n    - KeyPad Enter key now works on input boxes. [Omar]\r\n    - Added shortcut CTRL-F4: closes current window. [Omar]\r\n    - Added shortcut CTRL-TAB: cycles thru windows taking inputs. [Omar]\r\n    - Reworked theme (skin) system from stratch: [Omar]\r\n      - Changed MEKA.THM file format.\r\n      - Using explicit names for variables.\r\n      - Added more variables, making the skin system a little more\r\n        complicated but also more configurable.\r\n      - Using de-facto standard of specifying colors in #RRGGBB format.\r\n      - Rewrote most code since it was all legacy from old MEKA 0.10.\r\n  - Miscellaenous:\r\n    - (Win32) Removed flickering from initialization message console. [Maxim]\r\n  - Development:\r\n    - Made '$' default prefix for hexadecimal values in various places. [Omar]\r\n    - Datadump: [Ambil, Omar]\r\n      - Fixed \"palette\" dumping. Blue and green components were inverted.\r\n        Replaced dumping of target host RGB values by actual SMS/GG components.\r\n      - Added sprite pattern base address in \"sprites\" dumping.\r\n    - Memory Editor:\r\n      - Added viewing and editing of VDP registers (VREG). [Omar]\r\n      - Added configuration file directive for resizing window. [Omar]\r\n      - Fixed cursor position when inputing an address on last page. [Omar]\r\n    - Debugger:\r\n      - REGS (R) command in debugger now display shadow registers as well. [Omar]\r\n      - Added cursor before current instruction in disassembly. [Omar]\r\n      - Added access to shadow registers in expression evaluator. [Omar]\r\n        eg:\r\n          PRINT AF',BC',DE',HL'\r\n      - Added SET command to modify Z80 registers. [Omar]\r\n        eg:\r\n          SET BC=$1234    ; set BC register to $1234\r\n          SET DE=HL,HL=0  ; set DE=HL, then zero HL\r\n      - Added MEMEDIT command to spawn a new memory editor. [Omar]\r\n  - Sources/Project:\r\n    - Removed password encryption from MEKA datafile (became useless). [Omar]\r\n    - Fixed a bunch of warnings on higher warning levels. [Omar]\r\n    - Hacked a lot of old GUI code (box, widgets, menus among others), cleaned\r\n      and renamed various structures, replaced several usage of indexes by\r\n      pointers, added const qualifiers, rewrote parts of various applets,\r\n      got rid of some old obsolete code, etc. Hopefully broke nothing. [Omar]\r\n    - (Win32) Fixed MSVC project to reference LIBPNGDIR.\r\n    - (Win32) Including statically compiled libpng.lib in package. [Omar]\r\n    - (UN*X) No more need to manually edit .ASM files to compile. [Omar]\r\n  - Updated various tidbits of documentation. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n      GG  - 9f64c2bb - Ichidanto-R (JP)                     --> Ichidant~R (Puzzle & Action)\r\n      GG  - 09151743 - Tanto-R (JP)                         --> Tant~R (Puzzle & Action)\r\n      GG  - 3d8d0dd6 - World Series Baseball [A]            --> World Series Baseball [v0]\r\n      GG  - bb38cfd7 - World Series Baseball [B]            --> World Series Baseball [v1]\r\n\r\n\r\n MEKA 0.71\r\n ---------\r\n  Includes all 0.71 WIP below, minus lines starting with hash characters\r\n  (those lines refer to fixes relative to changes in a WIP).\r\n\r\n\r\n MEKA 0.71 WIP 20050625\r\n ----------------------\r\n  - Sources/Project\r\n     - (Linux,DOS) Added 'BUILD' switch in Makefile to select between release\r\n        and debug builds.\r\n\r\n\r\n MEKA 0.71 WIP 20050624\r\n ----------------------\r\n  - Now that MEKA is open-source, welcoming other developpers!\r\n    - New contributor: Robert Raper (DjRobX)\r\n    - New contributor: Maxim Stephin (MaxSt)\r\n    Names between brackets refers to the person(s) involved in a change.\r\n  - Blitter/Video:\r\n    - Added triple buffering support on fullscreen blitters. [DjRobX]\r\n      Made triple buffering the default for appliable video modes. It might\r\n      or not work on all configuration. Please report if any problem arise.\r\n    - Added max stretch support on fullscreen blitters. [DjRobX]\r\n      This is currently only available on normal and HQ2X filter.\r\n      Integer/ratio stretch not yet supported, so it is recommended to use\r\n      a resolution multiple of the emulated system screen size.\r\n    - Added support for internally converting the 8-bit video buffer to\r\n      another video depth and blitting that. [DjRobX]\r\n    - Integrated Maxim Stephin's HQ2X graphics filter, and added a dedicated\r\n      blitter. Only 16-bits output is supported as of yet. [MaxSt,DjRobX]\r\n  - Updated various tidbits of documentation. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n      GG  - 7b7717b8 - Big War / Daisenryaku G (JP)         --> Taisen-gata Daisenryaku G (JP)\r\n\r\n  Note that DjRobX's video/blitter changes were integrated but some features\r\n  may not be compatible with all others, and some need improvements. You are\r\n  welcome to experiment different configuration settings in MEKA.BLT but not\r\n  everything may work properly. The preset \"HQ2X\" blitter should works, though.\r\n\r\n  The current blitter system makes it not trivial to do everything we want,\r\n  it is too limited in configuration, and was first made with MS-DOS and low\r\n  end computers in mind. As of next versions, I will work on reoverhauling the\r\n  system, trying to better fits needs of the 21st century (resizing, multiple\r\n  depth, hi-color, windowed modes without borders, non 4:3 ratio screens,\r\n  different refresh rates...) and improve ease of setupping.\r\n  Expect many changes in this area (hopefully). [Omar]\r\n\r\n\r\n MEKA 0.71 WIP 20050501\r\n ----------------------\r\n  - GUI:\r\n##   - Fixed text input widget insert mode, could not insert any character,\r\n       and it broke memory editor (bug added in a 0.71 WIP) [Omar]\r\n  - Development:\r\n##   - Fixed replacement of 8-bit CPU registers variables (low and high\r\n##     nibbles were inverted) [Proppy]\r\n     - Fixed display of CPU flags (only bit 0 was properly interpreted,\r\n       because of a typo). Added display of undocumented flags bits 3\r\n       and 5 (partially emulated). [Omar]\r\n     - Made it that debugger log to file is immediately flushed. This allows\r\n       reading the log file in live while the debugger is running. [Omar]\r\n     - Added REGS (R) command to dump Z80 registers to the log console. [Omar]\r\n     - Added animation displaying weither CPU is running or not. [Omar]\r\n     - Fixed behavior of step/step over/continue when executing while being\r\n       located on a breakpoint. [Omar]\r\n     - Fixed behavior of step over an infinite loop. [Omar]\r\n  - Fixed loading of corrupted or incorrectly sized ROM images that would\r\n    sometimes made the engine crash. [Omar]\r\n  - Sources/Project\r\n     - (Linux) Updated Makefile and some sources tidbits for proper compilation.\r\n       [Omar,Belegdol,Proppy]\r\n     - (Linux,DOS) Object directories are now created automatically. [Omar]\r\n     - (Linux,DOS) Removed \"smscheck\" tool building from Makefile. Has nothing\r\n       to do with MEKA. [Omar]\r\n     - (Win32) Make it that build date/time stamp in build.c is updated when\r\n       rebuilding the solution. Removed buildupd.exe executable from sources. [Omar]\r\n     - (DOS) I'm stopping to maintain the MS-DOS port. A maintener is welcome. [Omar]\r\n\r\n\r\n MEKA 0.71 WIP 20050418\r\n ----------------------\r\n  - (Win32) Added a \"setup.bat\" command file to run the interactive setup.\r\n    Seems like few people were aware of the command-line option. [Omar]\r\n  - (Win32) The interactive setup now offers to enable/disable the debugger,\r\n    so you don't have to manually enable it. [Omar]\r\n  - (Win32) Updated Allegro library from WIP 4.1.12 to 4.1.18, which includes\r\n    various fixes/improvements:\r\n        http://www.talula.demon.co.uk/allegro/onlinedocs/en/changes.html\r\n  - (Win32) Fixed crash on early aborting (eg: command line error) due to non\r\n    properly stopping joystick polling thread. [Omar]\r\n  - Fixed input box widget missing keys on skipped frames. [Omar]\r\n    This made key inputs very annoying on certain configuration, and\r\n    especially with 3-D glasses auto-frame-skipping enabled.\r\n  - Fixed a problem losing focus while dragging GUI windows with certain kind\r\n    of widgets (happened on tile viewer & memory editor, among other). [Omar]\r\n  - Development:\r\n     - Updated debugger documentation. [Omar]\r\n     - Added symbol loading in NO$GMB format, as generated by the commonly\r\n       used WLA DX linker (-s parameter). [Omar]\r\n     - Added label/symbol viewing in Z80 disassembly window. [Omar]\r\n     - Relative offsets are now resolved in Z80 disassembly window. [Omar]\r\n     - Added expression evaluator. [Omar]\r\n       Supports integer operators +,-,*,/, binary operators &,|,^,\r\n       parenthesis, symbols and CPU registers replacement.\r\n       Yet missing: unary operators -,!,~.\r\n       All commands uses the expression evaluator to get their numeric\r\n       parameters, so you can use it everywhere.\r\n       eg:\r\n         B function    ; break at given 'function' symbol\r\n         M my_data     ; memory dump from 'my_data' symbol\r\n     - Added PRINT (P) command to evaluate and print expressions. [Omar]\r\n       eg:\r\n         P IX,IY       ; print IX and IY registers\r\n         P 1200+34     ; print $1234\r\n         P %00101010   ; print 42\r\n         P HL+(BC*4)   ; print HL+BC*4\r\n         P label       ; print label\r\n     - Added contextual command line completion. [Omar]\r\n       Press TAB to complete current input with matching command/symbols.\r\n       eg:\r\n         b[tab]        ; -> BREAK\r\n         b[tab]la[tab] ; -> BREAK label\r\n     - Added SYMBOLS (SYM) command to list and search for a symbol. [Omar]\r\n     - Changed breakpoint/watchpoint range syntax to '..' to avoid any\r\n       syntaxical ambiguity with substraction (eg: B 1000..2000). [Omar]\r\n     - Added \"B ENABLE/DISABLE ALL\" shortcuts to enable/disable all\r\n       breakpoints at once. [Omar]\r\n     - Added \"B CLEAR DISABLED\" shortcut to clear disabled breakpoints. [Omar]\r\n     - Added \"Reload ROM\" functionnality in the debug menu, for quicker reload.\r\n     - Palette viewer now shows color entry data while hovering colors. [Omar]\r\n  - Added and modified entries in the checksum and compatibility lists. [Omar]\r\n    Some particular renaming includes:\r\n      SMS - 60c19645 - Akai Koudan Zillion (JP)             --> Zillion / Akai Koudan Zillion  (note: this ROM was released in both Japan and Europe)\r\n      SMS - a1710f13 - Lucky Dime Caper, The                --> Lucky Dime Caper, The - Starring Donald Duck\r\n      SMS - 5718762c - Zillion                              --> Zillion (US)\r\n      GG  - a49e9033 - NBA JAM                              --> NBA JAM (JP)\r\n\r\n\r\n MEKA 0.70                 Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n  - Released source code.\r\n    Added SOURCES.TXT file with some information for programmers.\r\n  - Registration key is a thing of the past. It never served a real purpose\r\n    other than identifying donators. All donators are publicly listed at:\r\n        http://www.smspower.org/contrib.htm\r\n    Big thanks to all of them for their great and useful support!\r\n    I'll keep sending news/e-mails to donators.\r\n    MEKA is now officially not having a registration procedure anymore, but\r\n    your donations are still greatly welcome and are helping me to cover a\r\n    part of my never-ending Sega 8-bit expenses, including buying cartridges\r\n    for dumping and preservation purpose.\r\n    I updated documentation to reflect this, and changed occurences of the\r\n    \"registration\" word by \"donation\", as it was always meant to be anyway.\r\n  - In SMS mode, fixed color filling when VDP rendering is disabled.\r\n    Previously disabled parts where filled with black, instead of the current\r\n    border color. No commercial game exhibited the problem. Chris Covell's\r\n    port of Aleste 2 from GG to SMS did.\r\n  - Disabling background display now shows a yellow-ish color instead of the\r\n    black/border color, to help sprite ripping. Sorry it's not FF00FF pink,\r\n    but I am currently lacking free palette entries, and anyway, a screen full\r\n    of FF00FF pink would damage your eyes in a matter of seconds. :)\r\n  - Development:\r\n    - Added new full-featured breakpoints and watchpoints!\r\n      - Manage multiple breakpoints/watchpoints. Add/remove/enable/disable.\r\n      - Break and watch on CPU (rwx), IO (rw), VRAM (rw) and PRAM (w) buses.\r\n      - Break and watch on specific access (read/write/execute).\r\n      - Break and watch on single address or whole range.\r\n      - Add description to breakpoints/watchpoints (this is not very useful\r\n        right now, but it will be come handy in later version).\r\n      - Previous \"B\" command changed to \"S\" (step over).\r\n      - Previous \"B xxxx\" command (one-time breakpoint) is still accessible\r\n        using the \"C\" (continue) command.\r\n    - Added detailed help for each command.\r\n      (eg: \"HELP B\" to get help on breakpoints).\r\n    - Added DEBUGGER.TXT file with help and summary of debugging features.\r\n    - Instruction flow disassembly now attempt to display instructions before\r\n      the current one, based on some magical voodoo technique of mine.\r\n      Don't expect it to work in all cases - it is theorically impossible to\r\n      do with variable-sized instructions anyway - but it can be improved.\r\n      This feature helps figuring out what's being executed contextually.\r\n    - The current instruction is now highlighted.\r\n    - ROM edition in the memory viewer was not taken into account without\r\n      a hard reset in region 0x0400-0x3FFF. Fixed.\r\n    - Fixed savestate saving/loading which didn't restore scanline number\r\n      properly, affecting debugging using those features.\r\n    - Tile viewer now display tile starting address.\r\n    - Tile viewer now update information while mouse hovering.\r\n    - Added optional length parameter to \"MEM\" and \"DASM\" commands.\r\n    - Fixed ASCII display of memory in \"MEM\" command.\r\n    - Added \"debugger_console_lines\" and \"debugger_disassembly_lines\"\r\n      variables in configuration file, allowing to change debugger size.\r\n      Combine with a high-resolution MEKA desktop, and you can't be unhappy.\r\n    - Added debugger session logging to file \"debug/debuglog.txt\".\r\n      Can be disabled by clearing \"debugger_log\" in configuration file.\r\n    - Fixed a bug using the memory editor to write to RAM in Coleco Vision mode.\r\n    - Hacked a way so that you can affect controller inputs data while debugging\r\n      (press a direction, it immediately apply on the emulated system state).\r\n\r\n  - When used in the interface, analog peripherals supported by the mouse now\r\n    only perform their action if the mouse has focus on the game window.\r\n    This prevent accidental in-game shooting when using tools or debugging.\r\n    Of course, you should not use the interface if you only intend to play.\r\n  - Fixed /LOG command line parameter (broken recently).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Redumped more games, sorted more versionning/country confusion.\r\n    To avoid certain confusion, all Game Gear games originally running\r\n    in Master System mode were moved back in the Game Gear section.\r\n    This makes the list consistant with actual cartridge releases.\r\n    Some particular renaming includes:\r\n      SMS - 17a40e29 - Alex Kidd in Miracle World (US)      --> Alex Kidd in Miracle World [v0] (US)\r\n      SMS - aed9aac4 - Alex Kidd in Miracle World           --> Alex Kidd in Miracle World [v1] (note: this was released in both US and Europe)\r\n      SMS - 08c9ec91 - Alex Kidd in Miracle World (JP)      --> Alex Kidd no Miracle World (JP)\r\n      SMS - 0df8597f - Basket Ball Nightmare                --> Basketball Nightmare\r\n      SMS - e421e466 - Borgman (JP)                         --> Chouon Senshi Borgman (JP)\r\n      SMS - 11645549 - Solomon no Kagi (JP)                 --> Solomon no Kagi - Oujo Rihita no Namida (JP)\r\n      SG  - 0b4bca74 - Border Line (JP)                     --> Borderline\r\n      SG  - 922c5468 - Souko Ban (JP)                       --> Soukoban (JP)\r\n      SG  - 1ae94122 - Star Jacker [old] (JP)               --> Star Jacker [v0] (JP)\r\n      SG  - 7f25deca - Star Jacker [new] (JP)               --> Star Jacker [v1]\r\n      GG  - fe12a92f - Densetsu no Houguku (JP)             --> Mickey Mouse Densetsu no Oukoku (JP) (terrible typo)\r\n      GG  - 937fd52b - Kaito Saint Tail (JP)                --> Kaitou Saint Tail (JP)\r\n      GG  - dfa805a0 - Hanou no Toukyuuji Dodge Danpei (JP) --> Honoo no Toukyuuji Dodge Danpei (JP)\r\n\r\n\r\n  [Sources]\r\n  - Scrapped back all Arnosan shame crap.\r\n  - Added per-line color setting to textbox widget.\r\n  - Messed with the terrible box/widget code that vaguely ressemble to something\r\n    related to focus handling. I needed some change to support hovering in the\r\n    tile viewer... hope I did not break anything...\r\n\r\n\r\n MEKArnosan 0.69b         Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Mekarnosan special release, dedicated to Mr Arnosan, idol among the idols!\r\n\r\n\r\n MEKA 0.69b               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n  - [DOS/UN*X] Fixed ZIP file support which was accidently disabled\r\n    in version 0.69.\r\n  - Improved auto frame-skipper precision by a minor amount.\r\n    (on another hand, it still manage to skip frames badly).\r\n  - Disabled keys 0 to 9 to set a save state slot directly.\r\n    Those conflicted with some existing and future features.\r\n    Hope that noone will be annoyed!\r\n  - Added ALT-ENTER hotkey to switch between fullscreen and windowed drivers.\r\n    It works in both GUI and Game mode, although the setting is not saved in\r\n    Game mode (due to the way the MEKA.BLT file works now).\r\n  - Added an option to allows pressing opposite directions on the joypad.\r\n    Although standard SG/SMS/GG controllers do not allow that, certain\r\n    type of controllers (or a modified or broken one) may allow it.\r\n    This serve the purpose of demonstrating a bug in \"Wonder Boy in Monster\r\n    Land\", where pressing Left and Right on the same time confuses the game.\r\n    It is also useful in the case some creative genius SMS programmer would\r\n    want to take advantage of that weird feature to do unusual things for a\r\n    soon-to-be released SMS software.\r\n  - Fixed priority of Sega Keyboard (SK-1100) emulation, so that not colliding\r\n    hotkeys are still available while SK-1100 is enabled.\r\n  - Memory Editor now share inputs focus with game. It makes hacking easier.\r\n    Of course you can always pause (F12) or remap controls if needed.\r\n  - Fixed state of debugger window (bug introduced in 0.69).\r\n  - Updated translations:\r\n    - Dutch translation (by Mark van Tilburg).\r\n    - Swedish translation (by Henrik Sankala).\r\n    - Redneck translation (by some redneck in UK).\r\n\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - 31ffd7c3 - Castelo Rá Tim Bum (BR)              --> Castelo Rá-Tim-Bum (BR)\r\n      SMS - b137007a - Desert Speedtrap                     --> Desert Speedtrap - Starring Road Runner and Wile E. Coyote\r\n      SMS - 7abc70e9 - Party Games / Family Games (JP)      --> Family Games (Party Games) (JP)\r\n      GG  - 7174b802 - Baku Baku Animal (JP)                --> Baku Baku Animal - Sekai Shiikugakari Senshu-ken (JP)\r\n      GG  - 03d28eab - Crayon Shin Chan (JP)                --> Crayon Shin Chan - Taiketsu! Tankam Panic!! (JP)\r\n      GG  - ec808026 - Desert Speedtrap                     --> Desert Speedtrap - Starring Road Runner and Wile E. Coyote\r\n      GG  - c2e111ac - Desert Speedtrap (US)                --> Desert Speedtrap - Starring Road Runner and Wile E. Coyote (US)\r\n      GG  - a1a19135 - GG League '94 (JP)                   --> Pro Yakyuu GG League '94 (JP)\r\n      GG  - 4cf97801 - Godzilla (JP)                        --> Godzilla - Kaiju Dai-Shingeki (JP)\r\n      GG  - 86c32e5b - NBA Jam TE                           --> NBA JAM Tournament Edition\r\n      GG  - 751dad4c - Slam Dunk (JP)                       --> From TV animation - Slam Dunk - Shouri-e no Starting 5 (JP)\r\n      GG  - dd1d2ebf - Tamalympic (JP)                      --> Tama & Friends - 3chome Koen Tamalympic (JP)\r\n    And an awful typo saying \"Carmen Sandegio\" instead of \"Carmen Sandiego\".\r\n\r\n\r\n MEKA 0.69                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n  - Updated k.\r\n  - Updated documentation.\r\n  - Added a Memory Editor, long awaited by programmers, hackers and cheaters!\r\n    It allows reading and writing to Z80 memory map, ROM, RAM, VRAM, Palette\r\n    and Battery Backed RAM. Although it is not yet full-featured, it is\r\n    already very possible to create your own Pro Action Replay codes, and\r\n    perform various real-time hacks.\r\n    Please share your questions and hacks on SMS Power forums:\r\n        http://www.smspower.org/forum\r\n    This tool is the result of joint work with my beloved girlfriend, who\r\n    submitted a first version of it that she developped.\r\n  - Added support for loading and saving pictures in PNG format. PNG is now\r\n    the default format for screenshots, instead of the badly outdated PCX.\r\n    (thanks to libpng).\r\n  - Screenshots are now saved in the \"Screenshots/\" subdirectory.\r\n  - Tweaked some themes, reordered them, removed a few. Themes backgrounds\r\n    are now in PNG format. Please be sure to download the new picture pack at:\r\n        http://www.smspower.org/meka/themes\r\n  - [Windows] Added a message console that shows up on startup and magically\r\n    disappear before you have time to read anything. If any problem occurs,\r\n    the console will actually stay to let you read it.\r\n  - [Windows] Fixed runtime application icon that wasn't showing.\r\n  - [Windows] Removed command line parameters uppercase conversion (eg: when\r\n    ran from Windows explorer). This inconveniently created uppercase output\r\n    filenames for savestates, screen captures, etc. This was MS-DOS legacy.\r\n  - Slighty optimized VRAM accesses emulation.\r\n  - Incremented message buffer size to cope with SMS Chip-8 Interpreter 1.1\r\n    11k embedded comment. There is still buffer overflows in the code and\r\n    I'm not trying to fix most of them now, so this is just a work-around.\r\n  - Various other fixes and code tweaking.\r\n\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - 655fb1f4 - Bank Panic                           --> Bank Panic\r\n      SMS - b4dfb825 - Bank Panic                           --> Bank Panic [BAD]\r\n      SMS - 102d5fea - James Pond 2 - Codename Robocod      --> James Pond II - Codename: Robocod\r\n      SMS - e8ea842c - Marksman Shooting / Trap Shooting    --> Marksman Shooting & Trap Shooting\r\n      SMS - 00bef1d7 - Phantasy Star                        --> Phantasy Star [v3]\r\n      SMS - 07301f83 - Phantasy Star [Saturn]               --> Phantasy Star [Saturn]\r\n      GG  - c01293b0 - Devilish                             --> Devilish (US)\r\n      GG  - 06247dd2 - Ninku 2 (JP)                         --> Ninku 2 ~Tenkuryu-e no Michi~ (JP)\r\n      GG  - 00c34d94 - Madou Monogatari I (JP)              --> Madou Monogatari I - Mittsu no Madokyu (JP)\r\n      GG  - 0a634d79 - Madou Monogatari II (JP)             --> Madou Monogatari II - Aruru 16-sai (JP)\r\n      GG  - 12eb2287 - Madou Monogatari III (JP)            --> Madou Monogatari III - Kyukyoku Joo-sama (JP)\r\n      GG  - 7ec95282 - Madou Monogatari A                   --> Madou Monogatari A - Dokidoki-Bake Shon (JP)\r\n      GG  - c169c344 - X-Men - Gamesmaster's Legacy         --> X-Men - GamesMaster's Legacy\r\n\r\n    Use SMS Checker for your ROM renaming needs!\r\n        http://www.smspower.org/maxim/smschecker\r\n\r\n\r\n MEKA 0.68b               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n As an experiment, I have enabled vsync in all default blitters and enabled\r\n it by default in the GUI. Blitters are still a bit complicated to configure\r\n so few people seems to actually tweak them or even enable the \"smooth\"\r\n blitter. Does it works better for you?\r\n I'll be working on synchronisation and blitter improvement (stretching...)\r\n in the future.\r\n\r\n// Frameskipper and FPS computation changes makes this a test build.\r\n// MEKA now requires at least a Pentium CPU, due to usage of the RDTSC\r\n// instruction. I doubt that anyone still used a 486 anyway.\r\n// If nothing if broken due to those changes, I will be working on a new way\r\n// to perform throttling and frameskipping.\r\n\r\n//  - Tweaked the auto-frameskipper a little. Notify me if you notice any new\r\n//    problem. The auto-frameskipper still eats most CPU and isn't very good.\r\n//    Removed asynchronous events for FPS computation, the less they are, the\r\n//    more happy is the CPU.\r\n  - Removed the 2-byte tolerance in overdump detection. Overdumps with two\r\n    slighty different half will be added in the database and marked as bad.\r\n  - Emulation:\r\n     - Fixed a major bug in the driver system, which resulted in corrupted\r\n       savestates in F-16 Fighter / F-16 Fighting Falcon (the savestate\r\n       system recognized them as SG-1000 games and so saved only part of RAM).\r\n       Previous ingame states for the game are unrecoverable :(\r\n     - Removed immediate palette update when CRAM is written in a legacy\r\n       video mode (the palette isn't updated on a SMS). It only affected\r\n       F-16 Fighter / F-16 Fighting Falcon, but in a non game-visible way.\r\n     - Tweaked heuristical SMS/GG mapper detection.\r\n     - Fixed SMS/GG scanline counter emulation which was ignoring TV type\r\n       (NTSC or PAL/SECAM) override directive from the database.\r\n       (eg: one game would be forced to PAL/SECAM mode, but scanline counter\r\n        emulation still mimic an NTSC system if it is the user selection).\r\n  - Fixed mouse button mapping in the Input Configuration applet.\r\n  - Fixed file browser showing Japanese names after loading SMS Woody Pop\r\n    or GG Pop Breaker (why those games only? because they both have a default\r\n    country information in the DB, as they only works on Japanese systems).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      GG  - Ganbare Golby! (JP)             --> Ganbare Gorby! (JP)\r\n\r\n\r\n MEKA 0.68                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n Please report any problems you encounter.\r\n Suggestions are always welcome.\r\n\r\n  - Updated MEKA.NAM database with a new format.\r\n    The new format is more robust, includes CRC32, additionnal flags, and\r\n    allows specifiying multiple countries for a same ROM file.\r\n    In addition, while the MEKA database is being repopulated with entries\r\n    in the new format, a high amount of verifications are being done on a\r\n    case by case basis (redump, verified name based on original game media,\r\n    box and manual, analysis of different versions of a same game, etc...).\r\n    I have already redumped more than a hundred games. This will unsure\r\n    having a near-perfect database after the transition. Old formatted\r\n    entries are kept during the transition period.\r\n  - SMS-mode Game Gear games are now autodetected and forced to run into\r\n    SMS mode even with a .GG extension. This is because those games are\r\n    often spread with a .GG extension, although there is no way in software\r\n    to distinguish between a native GG game and one running in SMS mode,\r\n    since the selection is done via a connected pin in the cartridge itself.\r\n  - Updated file browser:\r\n      - Added dedicated icons to known bad dumps, BIOS images, unofficial\r\n        hacks, homebrew programs (also incorrectly called \"public domain\"),\r\n        prototypes and unofficial translation. A translation is defined as\r\n        a hack whose primary purpose is to alter the language of a game.\r\n        How do you like my icons?\r\n      - Added European, German, Italian, New-Zealand, Portuguese, Spanish,\r\n        Swedish and United-Kingdom flags. All flags are now displayed with\r\n        a border, because some themes may choose a window color matching\r\n        some flags.\r\n      - The \"Load Names\" feature is now faster and does not verbose any\r\n        data to the message box while loading all files.\r\n      - Made file browser window bigger by default.\r\n      - Removed the auto-generated MEKA.VFN file, which was crap anyway.\r\n        Instead, added a new auto-generated MEKA.FDB file, which store\r\n        association between user ROM file names and MEKA DataBase entries.\r\n  - Emulation:\r\n      - Emulated VDP 315-5124 behavior of using register 5 bit 0 and\r\n        register 6 bits 0-1 as masks on sprite x/tile attributes address\r\n        and tile index. No known game relies on this feature, but it is\r\n        good for the sake of accuracy and for developpers to check against\r\n        this particularity in their code (it is often a coding mistake).\r\n        VDP 315-5124 must be selected for that.\r\n  - Updated TECH.TXT with SMS controller pinouts, simple SMS/DB-9 controller\r\n    adapter instructions from Gary Pierce, and GNU/Linux notes.\r\n  - Various other fixes and code tweaking.\r\n\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n      - Naming and database field usage convention has been changed,\r\n        based on the new format.\r\n        - \"Title (The)\" now becomes \"Title, The\".\r\n        - Unless specified by the game title, \"Name: Subtitle\" now\r\n          becomes formatted \"Name - Subtitle\".\r\n        - A few other things related to versionning/country.\r\n      - Replaced all instances of \"Tectoy\" by \"Tec Toy\".\r\n      - Added some missing accents.\r\n      - Added many missing subtitles.\r\n      - Added many new product numbers.\r\n    Some particular renaming includes:\r\n      SMS - Alex Kidd BMX Trial (JP)        --> BMX Trial - Alex Kidd (JP)\r\n      SMS - Ninja Gaiden [B]                --> Ninja Gaiden\r\n      SMS - Ninja Gaiden [A]                --> Ninja Gaiden [Proto]\r\n      SMS - Putt & Putter [B]               --> Putt & Putter\r\n      SMS - Putt & Putter [A]               --> Putt & Putter [Proto]\r\n      SMS - Smash TV                        --> Super Smash T.V.\r\n      SMS - World Games [B]                 --> World Games\r\n      SMS - World Games [A]                 --> World Games [Proto]\r\n      GG  - GG Portrait: Akira (JP)         --> GG Portrait - Yuuki Akira (JP)\r\n      GG  - Halley Wars                     --> Halley Wars (JP)\r\n      GG  - Ninku Gaiden 2 (JP)             --> Ninku 2 (JP)\r\n      GG  - Pet Club Neko Dai Suki (JP)     --> Neko Daisuki! (JP)\r\n      GG  - Pet Club Inu Dai Suki (JP)      --> Pet Club Inu Daisuki! (JP)\r\n      GG  - Putt & Putter                   --> Putt & Putter (JP)\r\n      GG  - Shinkinjoh (JP)                 --> Shikinjou (JP)\r\n      GG  - Tempo JR                        --> Tempo Jr.\r\n      GG  - Winter Olympics                 --> Winter Olympics (JP)\r\n    The list above doesn't include ALL renaming, but only those I felt are\r\n    the most important to be propagated. Many other renaming were done.\r\n\r\n [Private Changes]\r\n  - Rewrote DB system.\r\n  - Rewrote VLFN system.\r\n  - Cleaned file browser.\r\n  - Rebuild datafile with new data.\r\n\r\n\r\n MEKA 0.67                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n  - Updated documentation.\r\n  - Tweaked the auto-frame skipper. Please let me know if you notice any\r\n    improvement or new problem.\r\n  - The analog Paddle Control is now usable using a digital keyboard or\r\n    joystick input, although it is HIGHLY recommended to use a mouse.\r\n    Playing with a keyboard or joystick may be sometimes frustrating and\r\n    does not allows fast movements.\r\n  - Updated debugging mode:\r\n      - Scrapped old, buggy, and unusable MS-DOS only text mode debugger.\r\n      - Added new debugger, well integrated into the GUI and functionnal\r\n        with all versions of MEKA. It is a primitive debugger, but it can\r\n        be helpful and it is definitively better than nothing.\r\n        Supports step-into, step-over, breakpoint, jump, disassembly and\r\n        memory dump. Expression are not evaluated and syntax is primitive.\r\n        Enable with the /DEBUG command line parameter.\r\n      - [Windows] Data dumping facilities are now working.\r\n  - Updated patching system (see MEKA.PAT file):\r\n      - Updated syntax.\r\n      - Support for long awaited RAM patches!\r\n        One of the side effect to that is that you can now apply\r\n        PRO ACTION REPLAY codes easily. This feature is unfortunately\r\n        not backuped by a full-featured interface and cheats database,\r\n        but is helpful and better than nothing - while waiting for\r\n        advanced cheating functionnalites to be added in the future.\r\n      - Support for CRC32 to specify the game to apply patches on,\r\n        as well as using MEKA proprietary checksum format.\r\n      - Putting * in the CRC field will apply a patch to all games.\r\n      - Minor bug fixes.\r\n  - Inputs:\r\n      - [Windows] Fixed joystick sliders support (DirectInput < 8.00\r\n        usually reports the fourth and fifth axis of a joystick as\r\n        being sliders, which is a weird little known behavior).\r\n      - File browser now takes exclusive inputs so the emulated game\r\n        is not affected by keypresses.\r\n  - Fixed file browser \"Load Names\" feature. It was broken in version 0.66,\r\n    and sometimes (not always) went into an infinite loop in earlier version.\r\n  - [Windows] Command line parameters help is now displayed in a message box.\r\n  - Closing a box now automatically focus the next one in focus order.\r\n  - Various other fixes.\r\n  - Updated Dutch translation (by Mark van Tilburg).\r\n\r\n  - Added and modified entries in the checksum and compatibility lists,\r\n    on the road to perfection. Added many missing (J) flags in the Game Gear\r\n    compatibility list. Added a few missing accents.\r\n    Some particular renaming includes:\r\n      SMS - Back to the Future 2            --> Back to the Future II\r\n      SMS - Back to the Future 3            --> Back to the Future III\r\n      SMS - Blade Eagle 3D                  --> Blade Eagle 3-D\r\n      SMS - California Games 2              --> California Games II\r\n      SMS - Chuck Rock 2                    --> Chuck Rock II: Son of Chuck\r\n      SMS - Ecco 2: the Tides of Time       --> Ecco: The Tides of Time\r\n      SMS - Fantazy Zone 2                  --> Fantazy Zone II\r\n      SMS - Fantasy Zone 3: the Maze        --> Fantasy Zone: The Maze\r\n      SMS - Golvellius                      --> Golvellius: Valley of Doom\r\n      SMS - High School Kimengumi           --> High School! Kimengumi\r\n      SMS - Jogos de Verao 2                --> Jogos de Verão II\r\n      SMS - Maze Hunter 3D                  --> Maze Hunter 3-D\r\n      SMS - Missile Defense 3D              --> Missile Defense 3-D\r\n      SMS - Out Run 3D                      --> Out Run 3-D\r\n      SMS - Pac-Mania                       --> Pacmania\r\n      SMS - Poseidon Wars 3D                --> Poseidon Wars 3-D\r\n      SMS - Rambo: First Blood Part 2       --> Rambo: First Blood Part II\r\n      SMS - Secret Commando                 --> Secret Command\r\n      SMS - Space Harrier 3D [Export]       --> Space Harrier 3-D\r\n      SMS - Sport Pad Football              --> Sports Pad Football\r\n      SMS - Sport Pad Soccer                --> Sports Pad Soccer\r\n      SMS - Super Monaco GP 2               --> Super Monaco GP II (Ayrton's Senna)\r\n      SMS - Turma da Mônica em o Resgate    --> Turma da Mônica em: O Resgate\r\n      SMS - Wonder Boy in Monster Land [A]  --> Wonder Boy in Monster Land\r\n      SMS - Wonder Boy in Monster Land [B]  --> Wonder Boy in Monster Land [Hack]\r\n      SMS - Wonder Boy in Monster Land [C]  --> Super Wonder Boy Monster Land / World [Japan]\r\n      SMS - World Cup '92 (Tecmo)           --> World Cup '93 (Tecmo) (Proto)\r\n      SMS - Wimbledon 2                     --> Wimbledon II\r\n      SMS - Winter Olympic '94              --> Winter Olympics\r\n      SMS - Ys: Vanished Omen               --> Y's: The Vanished Omens\r\n      SMS - Ys: Vanished Omen [Japan]       --> Ys [Japan]\r\n      SMS - Zaxxon 3D [Export]              --> Zaxxon 3-D\r\n      SMS - Zillion 2 [Export]              --> Zillion II: The Tri Formation\r\n      GG  - Chuck Rock 2                    --> Chuck Rock II: Son of Chuck\r\n      GG  - Desert Speedtrap                --> Desert Speedtrap [USA]\r\n      GG  - Ecco 2: the Tides of Time       --> Ecco: The Tides of Time\r\n      GG  - Gun Star Heroes [Japan]         --> Gunstar Heroes [Japan]\r\n      GG  - Super Monaco GP 2               --> Super Monaco GP II (Ayrton's Senna)\r\n      SG  - Championship Lode Runner [B]    --> Championship Lode Runner\r\n      SG  - Hang On 2                       --> Hang On II\r\n      SG  - Hyper Sports                    --> Hyper Sports (Konami no)\r\n      SG  - Pitfall 2                       --> Pitfall II\r\n      SG  - Rockn' Bolt                     --> Rock n' Bolt\r\n      SG  - Shinnyushain TooruKun           --> Shinnyushain Tooru Kun (Konami no)\r\n      SG  - Sindbad Mystery [A]             --> Sindbad Mystery\r\n\r\n    Please use SMS Checker for your ROM renaming needs!\r\n    http://www.smspower.org/maxim/smschecker\r\n\r\n [Private Changes]\r\n  - Added the /_DEBUG_INFOS parameter.\r\n  - Worked on sound engine. Stripped out a few unused code in sasound.c.\r\n  - Added GUI textbox and inputbox widgets.\r\n  - Updated save state format to 0x0C (added CRC32).\r\n  - Various code cleaning.\r\n\r\n\r\n MEKA 0.66                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n Blitting & synchronisation are still very bad in many cases. This is my\r\n top priority but I still cannot find a good solution to improve it and\r\n please everyone (slow and fast computers). I can't sleep! :(\r\n Use the \"smooth\" blitter if possible.\r\n\r\n  - Updated default blitters (MEKA.BLT).\r\n  - Video mode is not reinitialized anymore when switching blitters with\r\n    the same resolution/refresh rate. This saves a bit of time.\r\n  - [Windows] Fixed page flipping, for those using it (see MEKA.BLT file).\r\n  - [Windows] Sega 3-D Glasses support is now properly working in MEKAW!\r\n    If you build the simple 3-D Glasses to COM adapter (as described in\r\n    the TECH.TXT file), it is possible to plug original 3-D glasses and\r\n    enjoy 3-D games as they were meant to be played - and additionnally,\r\n    damage your eyes due to intense flickering :)\r\n    Best results are achieved by enabling page flipping or vsync.\r\n  - [DOS] Sega 3-D Glasses support now also works under a Windows 95/98\r\n    command prompt.\r\n  - Increased maximum number of joystick buttons to 32 (instead of 16).\r\n  - Partly fixed incorrect joystick axis reporting. It was a problem for\r\n    many people, and made it impossible or difficult to configure joysticks\r\n    using the interface. One extended joystick axis may be missing now,\r\n    until I can find a solution to this other problem.\r\n  - Tile viewer can now be configured to displayed all 512 tiles, instead\r\n    of the first 448 only. The bottom tiles looks awful with most SMS/GG\r\n    games but some games use this area so it's good to see them.\r\n  - Tile viewer now allows to select all 15 colors to display tiles in\r\n    TMS9918 video modes (used by SG-1000, SC-3000, Coleco Vision, etc.).\r\n  - Loading a ROM now display the full name in the message box.\r\n  - [Windows] Upgraded MSVC compiler from version 5.0 to 7.1 (might bring\r\n    a small improvement on performance). Removed ZLIB.DLL from the\r\n    distribution and statically linked it to the executable.\r\n  - [Windows] Fixed mekaw.cfg saving location. It was saving in a wrong\r\n    place in some cases (depending how you run it).\r\n  - Updated Danish translation (by Mark Klemp).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - Asterix [A]                     --> Asterix [V0]\r\n      SMS - Asterix [B]                     --> Asterix [V1]\r\n      SMS - Chuck Rock 2 [A]                --> Chuck Rock 2 [Europe]\r\n      SMS - Chuck Rock 2 [B] [Brasil]       --> Chuck Rock 2 [Brasil]\r\n      SMS - Golfamania [1990]               --> Golfamania\r\n      SMS - Golfamania [1989]               --> Golfamania (Proto)\r\n      SMS - James Pond 2: Robocod           --> James Pond 2: Codename Robocod\r\n      SMS - Lemmings [A]                    --> Lemmings\r\n      SMS - Lemmings [B]                    --> Lemmings (Proto)\r\n      SMS - Mortal Kombat 2                 --> Mortal Kombat II\r\n      SMS - Pit Fighter [A]                 --> Pit Fighter [Europe]\r\n      SMS - Pit Fighter [B] [Brasil]        --> Pit Fighter [Brasil]\r\n      SMS - Rainbow Island [A]              --> Rainbow Island [Europe]\r\n      SMS - Rainbow Island [B] [Brasil]     --> Rainbow Island [Brasil]\r\n      SMS - Seishyun Scandal [Japan]        --> Seishun Scandal [Japan]\r\n      SMS - Taz-Mania [A]                   --> Taz-Mania\r\n      SMS - Taz-Mania [B]                   --> Taz-Mania (Proto)\r\n      SMS - Tom and Jerry: the Movie [A]    --> Tom and Jerry: The Movie\r\n      SMS - Tom and Jerry: the Movie [B]    --> Tom and Jerry: The Movie (Proto)\r\n      SMS - Ultima IV [A]                   --> Ultima IV\r\n      SMS - Ultima IV [B]                   --> Ultima IV (Proto)\r\n      SMS - Wonder Boy 3: the Dragon's Trap --> Wonder Boy III: The Dragon's Trap (Proto)\r\n      SMS - Woody Pop [Japan]               --> Woody Pop: Shinjinrui no Block Kuzushi [Japan]\r\n      GG  - Lemmings [A]                    --> Lemmings\r\n      GG  - Lemmings [B]                    --> Lemmings (Proto)\r\n      GG  - Monster World 2 [Japan]         --> Monster World II\r\n      GG  - Mortal Kombat 2                 --> Mortal Kombat II\r\n      GG  - Wonder Boy 3: the Dragon's Trap --> Wonder Boy III: The Dragon's Trap (Proto)\r\n    Please use SMS Checker for your ROM renaming needs!\r\n    http://www.smspower.org/maxim/smschecker\r\n\r\n [Sources Changes]\r\n  - Updated project files, Makefile, etc.\r\n  - Various modifications to the video & blitter system.\r\n  - Various modifications to the GUI (added t_frame, etc.).\r\n\r\n\r\n MEKA 0.65c               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed Z80 interruption timing.\r\n    I have tested several \"sensitive\" games and nothing should have been\r\n    broke, but please e-mail me if you notice anything unusual.\r\n    In addition, the fix allowed to remove the need for a custom parameter\r\n    in MEKA.NAM for 5 more games.\r\n  - Fixed MEKA.PAT which added a bug to pausing in Wonder Boy III [SMS].\r\n    The bug was a leftover of one of my working session, and I forgot to\r\n    remove it before releasing the official distribution of version 0.65b.\r\n  - Fixed user inputs during the next frame after loading a savestate.\r\n    Previously, they were reseted on savestate loading, meaning that your\r\n    inputs were ignored on the first 1/60th second after loading. Although\r\n    this is not dramatic in most cases, in a few it made savestates unusable\r\n    because the player would die on loading without being able to react.\r\n    Now you have that missing 1/60th second.\r\n  - Attempted to fix the occasionnal crash on shutdown. I don't know if it\r\n    happens anymore or not.\r\n  - Updated Swedish translation (by Henrik Sankala).\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Some particular renaming includes:\r\n      SMS - Double Target [Japan]   --> Double Target Cynthia no Nemuri [Japan]\r\n      SMS - Formula 1               --> F1\r\n      SMS - Machine Gun Joe [Japan] --> Comical Machine Gun Joe [Japan]\r\n      SMS - Pit Pot [Japan]         --> Fushigi no Oshiro Pit Pot [Japan]\r\n      SMS - Sonic the Hedgehog [A]  --> Sonic the Hedgehog [V0]\r\n      SMS - Sonic the Hedgehog [B]  --> Sonic the Hedgehog [V1]\r\n      SMS - Transbot                --> TransBot\r\n      GG  - Columns                 --> Columns [Japan]\r\n      GG  - Formula 1               --> F1\r\n      GG  - Pengo                   --> Pengo [Japan]\r\n      GG  - Jungle Book             --> Jungle Book [USA]\r\n      GG  - Woody Pop               --> Woody Pop [V0]\r\n    Please use SMS Checker for your ROM renaming needs!\r\n    http://www.smspower.org/maxim/smschecker/smschecker.htm\r\n\r\n\r\n MEKA 0.65b               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Updated k.\r\n  - Fixed TV Mode which was accidentaly broken in version 0.65 (due to\r\n    recent palette system rewrite). Sorry for the inconvenience. I also\r\n    took the occasion to slighty optimize it.\r\n  - Fixed still screens corruption in Game Gear version of \"Bart vs. the\r\n    Space Mutants\". It was affected by a timing issue introduced in a\r\n    previous version. The fix (using a MEKA.NAM feature) is temporary until\r\n    a better one can be found.\r\n  - [Win] Added a simple first-run setup screen, to select soundcard,\r\n    sample rate and language. Additionally, you can show the setup screen\r\n    on startup by passing the -SETUP command line parameter to MEKA.\r\n  - Added \"cabinet_mode\" setting in MEKA.INP, to invert ESCAPE and F10 keys.\r\n    Arcade/emulation cabinet owners often have ESCAPE mapped to a key they\r\n    want to use to quit. This feature is a quick addition until full key\r\n    redefinition is supported.\r\n  - Added auto-repetition on keys F6/F8 (savestate selection).\r\n  - Added support for mouse wheel in file browser and documentation viewer.\r\n  - Fixed state saving crash that could happen when sound is completely\r\n    disabled and no FM emulator was selected.\r\n  - Started migrating from my own general purpose C library to standard\r\n    C library (LibC) for various functions.  This should provides speed\r\n    improvements in the initialization process.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n  - Various minor changes. Can you stop them all?\r\n  - [Unix] Fixed configuration file saving.\r\n\r\n  [Sources Changes]\r\n  - Toyed with Z80 core and added interrupt logging facilities.\r\n    This can be useful for debugging purpose when you can replicate the\r\n    same execution.\r\n\r\n\r\n MEKA 0.65                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Rewrote palette system in the attempt of reducing palette changes\r\n    even more. As some people noticed, on some computer, the Windows\r\n    version had terrible slowdown and incorrect colors at some occasion\r\n    and especially in Game Gear games.\r\n    This is due to some DirectX video drivers which force waiting for\r\n    a screen refresh before each palette change. Problem is that some\r\n    drivers does that and some other do not. Palette changes in MEKA\r\n    are now better grouped so that the wait should not affect gameplay\r\n    in most cases.\r\n    Please report if you notice any palette related problem in this version.\r\n    Windows users, note that you can still get color flickering in some\r\n    video modes. But overally, things should be much better.\r\n  - Rewrote hardware sprite collision emulation for video modes 1, 2 and 3\r\n    (used by SG-1000/SC-3000/SF-7000/Coleco Vision software, mainly).\r\n    Sprite collision are now processed line per line, for a very accurate\r\n    result - at the cost of a slighty slower emulation. Although machines\r\n    using those video modes usually can't poll for the current line, some\r\n    software can manually do a similar job, making this precise value useful.\r\n    This fixes \"Froggy\" and \"Gold Miner\" (SF-7000), and maybe more.\r\n    Please report if you notice any collision related problem in this version.\r\n  - Fixed SMS/GG scanline counter to return accurate values.\r\n  - PAL/SECAM modes now have 313 lines instead of 312.\r\n  - Fixed \"Daffy Duck in Hollywood\" (SMS) which in some cases had\r\n    incorrect scrolling on the level score screen.\r\n  - Fixed palette switching in \"F-16 Fighter\" / \"F-16 Fighting Falcon\",\r\n    colors were incorrect during one single frame after the title screen.\r\n    This bug was introduced in a previous release.\r\n  - [Windows] Fixed screen capture (did crash with some DirectX drivers\r\n    in version 0.64c).\r\n  - Added Chinese flag in the file loader and associated the early dump\r\n    of Hokuto no Ken with it.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n    Fixed a few inconsistent entries.\r\n    Some particular renaming includes:\r\n      Chase H.Q.        --> Taito Chase H.Q.        (official name)\r\n      Story of Mio      --> Hoshi Wo Sagashite...   (official name)\r\n      Hokuto no Ken [B] --> Hokuto no Ken\r\n      Hokuto no Ken [A] --> Hokuto no Ken [China]\r\n  - Updated documentation.\r\n  - [UN*X] Released a quick & dirty GNU/Linux build, codenamed \"MEKANIX\".\r\n    It is not perfect and I do not plan to completely support it, but I hope\r\n    it can be useful to some people (some asked for it).\r\n    Please read MEKANIX.TXT if you want to use it.\r\n\r\n  [Sources Changes]\r\n  - Started updating several files to meet a standardized coding style\r\n    accross the project. Various changes and clean-ups.\r\n\r\n\r\n MEKA 0.64c               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed the bug that would sometimes shut down sound when resetting\r\n    or loading a savestate in full-screen mode.\r\n  - Fixed the bug that would not save battery backed memory when switching\r\n    the virtual machine Off (thanks Ian Hodgkinson for the precise report!).\r\n  - Fixed Light Phaser border limit when left column is blanked. In some\r\n    cases, the limit was enabled where it should not have.\r\n  - Light Phaser is now usable inside of the GUI, although this is obviously\r\n    not recommended since you can move the game window accidentally.\r\n  - Redumped and verified plenty more cartridges. Added and modified entries\r\n    to the checksum and compatibility lists, including new alternate dumps.\r\n    Some particular renaming includes:\r\n      James Bond 007: The Duel [B] --> James Bond 007: The Duel\r\n      James Bond 007: The Duel [A] --> James Bond 007: The Duel [Brasil]\r\n      Paperboy [B]                 --> Paperboy\r\n      Paperboy [A]                 --> Paperboy [USA]\r\n    Also modified compatibility list to be coherent with checksum list\r\n    regarding alternate version naming.\r\n  - MEKA now switch back to interface if fullscreen video mode cannot be set,\r\n    instead of quitting.\r\n  - Virtual machine picture positionning in the GUI now takes account of the\r\n    resolution (in GUI another resolution than default 640x480 is used).\r\n  - Updated history section of the documentation.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n  - [Windows] Fixed some of the screen corruptions when another application\r\n    is getting the focus or writing to the screen (untested).\r\n  - Added SG-1000 games to the multiplayer games list file (MULTI.TXT).\r\n  - Updated Danish translation (by Marc Klemp).\r\n  - Added CPU state dumping feature in debug mode.\r\n\r\n\r\n MEKA 0.64b               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added patches to be able to run SMS BIOS images (Alex Kidd in Miracle\r\n    World, Hang On / Safari Hunt, Sonic the Hedgehog...) as standard games.\r\n  - Fixed an amazingly stupid problem that's been around since years, which\r\n    was that Game Gear colors were considered as 9-bits instead of 12-bits.\r\n    Colors are now more precise, and you can notice a clear difference by\r\n    looking at the ground in FIFA International Soccer.\r\n    Thanks goes to Carleton Handley (the FIFA programmer on Game Gear) for\r\n    clearly pointing that out to me.\r\n  - Fixed VDP IE1 bit controls on Z80 IRQ Line.\r\n  - Fixed top of the screen in video mode 3, and optimized its refresh.\r\n    (used by Cabbage Patch Kids Picture Show and Smurf Paint & Play Workshop)\r\n  - Added Danish translation (by Marc Klemp).\r\n  - Patches write commands (in MEKA.PAT) now support multiple bytes in\r\n    a single line.\r\n  - Added and modified entries in the checksum and compatibility lists.\r\n  - Added \"Skydrop\" theme by Peter Deas (need to uncomment it in MEKA.THM).\r\n\r\n\r\n MEKA 0.64                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n Important changes were applied to the sound engine. As always, please\r\n contact me if notice something unusual, if you have any comment or doubt.\r\n\r\n PSG fixes that were applied in version 0.63 are apparently causing a bug\r\n to Out Run (SMS) running in FM mode. I searched but was unable to fix it\r\n as of yet. :(\r\n\r\n  - Cleaned and modified various part of the sound engine.\r\n    Please report if you notice anything unusual.\r\n  - [Windows] Disabled access to hardware YM-2413 emulation using OPL\r\n    under Windows 2000 and XP, avoiding crashes in certain cases... Well,\r\n    this time it should works :-)\r\n  - [Windows] FM Sound through OPL is now muted when switching to other\r\n    applications. PSG can not muted yet due to a technical constraint.\r\n  - Fixed muting of OPL on pause and quit (previously you were sometimes\r\n    able to hear very low hanging notes with a very high volume).\r\n  - Implemented software YM-2413 emulator by Mitsutaka Okazaki.\r\n    Although hardware YM-2413 emulation using OPL sounds cooler, this\r\n    emulator seems more faithful to the original chipset. It also works\r\n    on all systems, including Windows 2000 and XP. The downside is that\r\n    doing software synthesis takes a lot of time, and thus a fast computer\r\n    is recommended (at least 600 Mhz) to play MEKA with software YM-2413\r\n    emulation.\r\n  - Implemented a new software PSG emulator by Maxim (with modifications).\r\n    PSG emulation is pretty straightforward, but this emulator takes\r\n    account of several Maxim finds, such as the real sequence of pseudo\r\n    random numbers, as generated by the noise channel.\r\n  - Added refresh rate settings to GUI and Blitters. An advanced user\r\n    can now setup a video mode at 60 Hz with vsync enabled and auto frame\r\n    skipping disabled, for a smooth video refresh.\r\n  - Fixed PSG output that was previously too low and unsigned.\r\n  - [Windows] Attempted to fix some crashes subsequent to freeing a ROM.\r\n  - Added entries to the checksum and compatibility lists.\r\n  - Updated documentation.\r\n\r\n\r\n MEKA 0.63b               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - [Windows] Disabled access to hardware YM-2413 emulation using OPL\r\n    under Windows 2000 and XP, avoiding crashes in certain cases.\r\n  - Removed rare PSG debugging messages that were accidentally left.\r\n  - Fixed timing of the {LD,CP,IN,OT}[ID]R transfer/comparaison Z80 opcodes,\r\n    which were made too slow by 8 cycles in version 0.63.\r\n    \"The Castle\" (SG-1000) was affected.\r\n  - Fixed Sega Keyboard mapping for the \"Yen\" key on Japanese keyboard\r\n    (untested). Note that the mapping for certain specials keys seems not\r\n    to be right yet using the Windows version.\r\n  - Performed some minor calling optimizations.\r\n  - Updated Dutch, Deutsch, Italian, Spanish and Swedish translations\r\n    with missing messages. (Thanks to their respective mainteners!)\r\n\r\n\r\n MEKA 0.63                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Implemented a cyclic color allocation algorythm, reducing palette\r\n    changes even more in some games. Users with videocard/drivers having\r\n    problems changing palette can expect less slowdown in Game Gear games.\r\n  - Tested every single Master System games, and wrote a multiplayer games\r\n    list out of them. It is included in the emulator (MULTI.TXT).\r\n  - Added 21 missing undocumented Z80 opcodes in the ED instruction set,\r\n    including the wonderful OUT (A), 0.\r\n  - Fixed PSG emulation. The holding note after text boxes shows in\r\n    \"Alex Kidd in Miracle World\" is no more, and noise channel writes were\r\n    fixed (as used by CodeMasters games: Micro Machines drums now sounds\r\n    correctly, etc...). Thanks to the great Maxim for his informations!\r\n  - Fixed Light Phaser shooting position for when left column blanking is\r\n    enabled (a bug leaked in since a few version).\r\n  - Fixed 64-bytes ROM footer detection.\r\n  - Fixed a bug affecting Hardware Reset and ROM reloading on SG-1000/SC-3000\r\n    and Colecovision emulation. As far as I know, only \"Pac-Man\" (Coleco)\r\n    was affected after an Hardware Reset, but other ROMs could as well.\r\n    Thanks to James Carter for the bug report.\r\n  - Fixed a two-years-old bug that may lead MEKA to crash when loading\r\n    a savestate that was previously used under the debugger.\r\n  - Fixed Sega Keyboard mapping for the unusual \"Pi\" / \"Ro\" key, so\r\n    Japanese users can use it at its standard mapping location.\r\n    Thanks to Yujiro for the bug report.\r\n  - FPS Counter is now enabled/disabled by pressing Alt+F, instead of\r\n    keeping F pressed.\r\n  - [Windows] Fixed time display.\r\n  - Updated to newer GCC version, hopefully little improving performances.\r\n  - Added and modified entries to the checksum and compatibility lists.\r\n    Some interesting ones I could rename after redumping:\r\n      Alex Kidd in Miracle World [A] --> Alex Kidd in Miracle World [Export]\r\n      Alex Kidd in Miracle World [B] --> Alex Kidd in Miracle World [USA]\r\n\r\n\r\n MEKA 0.62c               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various fixes.\r\n  - Released Windows version.\r\n  - Added \"compatibility list\" and \"changes list\" items in the help menu,\r\n    allowing you to open them with the internal text viewer.\r\n  - Due to improving computer speed, default blitters now all have vsync\r\n    enabled, for smoother screen refresh. It is of course still and always\r\n    possible to disable vsync manually (see MEKA.BLT file).\r\n\r\n\r\n MEKA 0.62b               Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Sorry for the huge delay in such a minor update. I've tweaked the Z80\r\n    core a bit again to fix a little bug that I introduced myself and which\r\n    puzzled me for a while. I took the occasion also to upgrade to Marat's\r\n    latest debugger (now showing inline interrupt informations).\r\n  - Battery backed RAM is now scanned so unnecessary pages are not saved\r\n    in the .SAV file (this was previously already done, but only inside\r\n    of save states).\r\n  - Added new entries to the checksum and compatibility lists.\r\n  - Updated Spanish localisation.\r\n\r\n\r\n MEKA 0.62                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Compatibility notes:\r\n  - Sonic Blast [GG] minor glitches on title screen in non Japanese mode\r\n    has been confirmed to appear on a real Game Gear, so the game is now\r\n    marked as perfectly working.\r\n  - Thanks to the new 93c46 EEPROM emulator, Game Gear perfect compatibility\r\n    has now increased to 98.09% (counting like FreezeSMS does, that gives us\r\n    a whooping 150.00% :)\r\n  - Statistics: as far as I know, out of the 7 Game Gear games marked as\r\n    NON-WORKING, 5 games requires a simulation of LCD blurry persistance to\r\n    show up without flickering, 1 may be severly broken (not possible to\r\n    complete the game), and 1 is minorly broken.\r\n\r\n As always, please report if you find out anything you feel as not emulated\r\n PERFECTLY: even a single suspicious pixel, etc.. Thank you!\r\n\r\n  - Rewrote 93c46 EEPROM emulation from stratch, it now works and saves\r\n    data properly. This fixes the following Game Gear games:\r\n      - Majors Pro Baseball\r\n      - Nomo's World Series Baseball (J)\r\n      - Pro Yakyuu GG League (J)\r\n      - World Series Baseball [A]\r\n      - World Series Baseball [B]\r\n      - World Series Baseball 95\r\n  - Emulated onboard 64 kb RAM chip of Ernie Els Golf (GG).\r\n  - For the sake of accuracy, started to implement emulation of the four\r\n    slighty different VDP chipsets used in Master System 1/2, Game Gear and\r\n    Megadrive (compatibility mode). They all have subtle differences, causing\r\n    some games not to work perfectly on all of them.\r\n  - Fixed glitches in Ys (Japanese version), using 315-5124 VDP emulation.\r\n  - Fixed bugs in Z80 emulation, letting the Game Over screen for Rambo III\r\n    to appears normally - and this required many many hours of work! (thanks\r\n    to Jonas Persson for reporting the bug). Also changed behavior of EI\r\n    instruction, fixing Double Dragon for Game Gear (again).\r\n  - Fixed VDP refresh disable emulation for Game Gear.\r\n  - Fixed YM-2413 state restoring when loading a save with FM playing.\r\n  - Now store YM-2413 state initialization in VGM files.\r\n  - If available, store Japanese game name (in romanji form) in VGM files.\r\n  - Fixed shifted instruction offset in debugger.\r\n  - Updated TECH.TXT with instructions about how to build a DB-9 adapter\r\n    to connect SMS Joypads on your PC.\r\n  - Added full French (by Overture 1928) and Swedish (by Henrik Sankala)\r\n    localisations. Complete Italian localisation (by Andra Ballandino).\r\n  - Fixed minor display bug in the Inputs configuration tool.\r\n\r\n\r\n MEKA 0.61                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n This version may or not have minor glitches on certain games (like, a single\r\n pixel or a single blinking row at the top or the bottom of the screen).\r\n Please report those glitches if you notice any. Thanks!\r\n\r\n  - Moved 104 messages to MEKA.MSG, allowing for full localization of\r\n    the menus. 99% of MEKA is now localizable. Updated the following\r\n    languages: English, German, Redneck, Dutch, Portuguese and Spanish.\r\n  - Improved Z80 core (timing and interrupt emulation bug).\r\n  - Fixed Rise of the Robots (GG), MEKA being the first emulator to play\r\n    it without glitches (and even without, it sucks! :)\r\n  - Fixed most or all (?) glitches in Formula 1 (SMS) two-players mode\r\n    (maybe not the right way yet).\r\n  - Fixed Double Dragon (GG) which was not working since an update of\r\n    the Z80 core (from fMSX) several version ago.\r\n  - Country changes now immediately takes effects (no need to reset).\r\n  - Tweaking interrupt emulation for SG-1000/SC-3000/SF-7000 and Coleco\r\n    Vision drivers. Those changes should not affect anything.\r\n  - Fixed 'Parallel' video blitter, odd frames were not updated when\r\n    using the blitter with software 3-D Glasses mode enabled.\r\n  - Fixed crash of SF-7000 driver when loading a corrupted floppy disk.\r\n  - Fixed YM-2413 logging in VGM files (Register & Value were reversed!)\r\n  - Updated SDSC Header support for version 1.01 (adding Author field).\r\n  - Added Golden Axe theme by Death Adder. (uncomment to use in GUI)\r\n  - Updated to Allegro WIP 3.9.39 and reapplied all custom patchs.\r\n    Changed SideWinder autodetection process a bit. Hope it works!\r\n  - Reduced executable.\r\n\r\n\r\n MEKA 0.60                 Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Improved timing in Z80 core.\r\n  - Fixed voices that weren't ok (Alex Kidd: the Lost Stars..).\r\n    Voices in many many games were tested, finally marked them as 'Ok' in\r\n    the compatibility list.\r\n  - Due to timing improvments, now Space Harrier [50 Hz version] has correct\r\n    glitches (like on a real system) when running in NTSC mode. It is now\r\n    configured to automatically use PAL/SECAM by default.\r\n  - Removed the need of specific IPeriod setting for some Codemasters\r\n    games, meaning that they will now run even if you delete MEKA.NAM.\r\n  - Added sample accurate VGM logging, allowing to log voices. The option\r\n    was previously grayed, it is activated now that all voices are Ok.\r\n  - Updated to VGM version 1.01, to include original TV type information\r\n    (NTSC or PAL/SECAM) in the file, allowing to play at a different rate.\r\n  - Fixed minor sprite masking bug affecting scrolling games in certain\r\n    conditions. Evander Holyfield Boxing (Game Gear) was affected.\r\n  - Added support for Coleco Vision header/footer in order to load the\r\n    newly released \"Pac Man\" and \"Dig Dug\" ROMs from CGE 2001.\r\n  - Fixed a minor bug when loading an in-game savestate from the BIOS.\r\n  - Fixed file loader sorting so that if present, \"..\" is always on top.\r\n  - Added/fixed entrys to the checksum and compatibility lists.\r\n  - Added two Sonic themes by H Hog. (uncomment to use in GUI)\r\n\r\n\r\n MEKA 0.59b                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed vertical scanline counter emulation.\r\n  - Fixed a minor hardware collision bug introduced in version 0.59.\r\n  - Fixed usage of '%' in ROM comment field.\r\n  - Changed message logging (with /LOG) to avoid cutting text in the file\r\n    when it doesn't fit on the GUI message box.\r\n\r\n\r\n MEKA 0.59                 Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various changes to the sound engine:\r\n     - Fixed PSG Periodic Noise emulation (bass in some Marble Madness tunes,\r\n       Daffy Duck in Hollywood, and few other games). Thanks Ziria and Maxim!\r\n     - Added PAL/SECAM machines accurate base clock for PSG wave generation\r\n       (pitch is around 1% off from NTSC machines).\r\n     - Added VGM logging. VGM (for Video Game Music) is a new file format\r\n       recently developed on S8-Dev with collaboration of Dave, Maxim and\r\n       some other people. Maxim has wrote a WinAMP plugin already.\r\n       Check out the newly created Music Section on SMS Power at\r\n       http://www.smspower.org/music !\r\n     - Added PSG registers to the technical information window.\r\n  - Fixed a very weird bug introduced in version 0.58, where a certain sprite\r\n    configuration and positionning could screws up the whole emulator! This\r\n    caused problems in Terminator 2: The Judgment Day and Ghouls'n Ghosts.\r\n  - Added Korean mapper (9) emulation, as used by Dodgeball King.\r\n  - Added Italian messages translations (by Andrea Ballandino).\r\n  - Added German messages translations (by Tilman Hesse).\r\n  - Fixed some Português messages.\r\n  - Fixed/added accentued characters in some Brazilian game names.\r\n  - Added new \"Mario Must Die\" theme, with a nice handdrawn picture :-)\r\n  - Added new entrys to the checksum and compatibility lists.\r\n  - Fixed and improved various minor things.\r\n\r\n\r\n MEKA 0.58c                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed the missing soundcard selection menu in some cases.\r\n  - Added printing of SDSC Header informations when found. The SDSC Header\r\n    has been defined and created by the SMS Power developement team (based\r\n    on Eric Quinn's idea) for homebrewn programs.\r\n  - Drawn Latin-Extended characters (Unicode 0080-00FF) in the big font.\r\n    Accents are now usable everywhere in MEKA. Be sure to use accents from\r\n    the Latin-Extended table (usually used by Windows programs, not DOS ones).\r\n  - Added Spanish messages translations (by Antonio J. Bazalo).\r\n  - Added Português messages translations (by Rodrigo C. Rubio).\r\n  - Added \"WIP\" (Work In Progress) parameter in language definition, to\r\n    disable warnings and informations when the language is uncomplete.\r\n  - Squashed one very minor flag bug in the browser when a ROM had an\r\n    number after a space, at the end of its filename.\r\n\r\n\r\n MEKA 0.58b                Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed various minor bugs.\r\n  - Fixed two scrolling emulation bugs in video mode 5. They did not\r\n    affect any game, but for the sake of accuracy, better fixing them!\r\n  - Added Dutch messages translations (by Mark van Tilburg) and Redneck\r\n    messages translations (by Maxim, using Dialectizer). Fry mah hide!\r\n  - Added /LOAD command line parameter, to start directly with a savestate\r\n    loaded (so you can make yourself batchfile loading a certain state.)\r\n  - Added several new entrys to the checksum and compatibility lists, and\r\n    fixed some existing ones. Added an USA flag and set the flag to all\r\n    SMS games only released in USA (Alf, King's Quest, Montezuma's Revenge).\r\n  - Added one new happy theme from the french movie \"Amélie Poulain\".\r\n\r\n\r\n MEKA 0.58                 Emulation: 98%     Speed: 57%     Features: 80%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Again, please report if you notice any bug/glitche with any game, that is\r\n not mentionned in the compatibility list. The VDP fix applied in this\r\n version is also a massive compatibility test, and I would like to know\r\n if it has any unexpected behavior on other games. So play, play, play! :)\r\n\r\n  - Added PSG sound logging to WAV files, accessible from the Sound menu.\r\n  - Rewrote messaging system, added localization support.\r\n    Moved all messages to an external file, MEKA.MSG. You can now change\r\n    80% of the texts used in MEKA, and translate it to the language of your\r\n    choice. I am however NOT YET sure about how accents will work, since it\r\n    depends on the font used.\r\n    This feature required a pass on all existing code and so took plenty\r\n    of time to do (10+ hours), I might have screwed a few messages during\r\n    the change, so be sure to send me an e-mail if you notice anything\r\n    unusual.\r\n  - Implemented a VDP quirk found in Master System 2 but not Master System 1\r\n    or Game Gear, discovered by Charles Mac Donald (thanks Charles!). This\r\n    one fixes Cosmic Spacehead *BUT* might screws up few other games. I did\r\n    a bit of testing but couldn't do them all again, so please report if you\r\n    notice anything unusual with another game.\r\n  - Improved hardware sprite collision accuracy, fixed a bug in some\r\n    cases where it was previously framerate dependant, and rewrote the\r\n    whole code in assembly.\r\n  - Changed initializations messages and some other messages.\r\n  - Fixed an incorrect numbers of TV lines in PAL/SECAM TV emulation (due\r\n    to a typo - thanks goes to cgfm2 for pointing me this stupid error!),\r\n    allowing removal of a few custom MEKA.NAM parameters (Daffy Duck in\r\n    Hollywood..).\r\n  - Fixed the annoying bug that caused crashes on startup under DOS when\r\n    sound was enabled.\r\n  - Fixed a minor bug in Codemaster mapper emulation, that affected the\r\n    checksum check of 'Drop Zone' (although the game worked).\r\n  - Fixed crash when using a patch defined in MEKA.PAT that write outside\r\n    of any existing data.\r\n  - Added (very) quick and (very) dirty frame-per-frame advance by pressing\r\n    ALT-F12. In fact, it will unpause the game then pause it back next frame.\r\n  - Updated Colecovision compatibility list and added some product IDs,\r\n    thanks to Tincho DJ.\r\n    The current state with Colecovision games is: a mess :(\r\n    Someone will lots of Colecovision knowledge would be very helpful\r\n    to help sorting out all bad dumps, testing games and redumping others.\r\n\r\n\r\n MEKA 0.57b                Emulation: 97%     Speed: 57%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Lots of fixes, for a total of twenty working hours.\r\n Please also note in documentation that *I HAVE MOVED HOUSE*, that is\r\n in case you planned to send something.\r\n\r\n  - Various minor fixes and improvements.\r\n  - Fixed startup delay (and sometimes crash) when autodetecting Sidewinders.\r\n  - Fixed and improved the new dynamic palette handler, avoiding palettes\r\n    overflow on some Game Gear games such as Sonic & Tails 2 / Triple Trouble,\r\n    Sonic 1 or Deep Duck Trouble. The fourth level of Sonic 1 is however\r\n    not yet perfect when both air and water are shown on screen.\r\n    Thanks to ICEknight for pointing the bug out.\r\n  - Made various clean and corrections to the main sound engine structure.\r\n    It should not have broken anything, but please report if you notice\r\n    something unusual. Noticable changes are that:\r\n     - MEKA refuse to start if sound initialization has failed.\r\n     - Sound is now muted while certain long operations are being processed.\r\n     - Sound card type is not lost if you only disable sound.\r\n     - An incorrect BLASTER environnement variable is now reported.\r\n  - Added an algorithm to automatically detect certain mappers and select\r\n    them when the ROM is unknown.\r\n  - Fixed vertical scrolling emulation in certain special cases.\r\n  - Fixed zoomed sprites in SMS/GG video mode. They were accidentally\r\n    screwed up by a typo (!) in previous version, and affected Virtua\r\n    Fighter Mini.\r\n  - Fixed a bug with checksum handling. In some cases, ROMs with only a\r\n    few different bytes were previously not recognized as different.\r\n  - Fixed usage of the ';' key in the input system (now usable), previously\r\n    the character was considered as beginning a comment in MEKA.INP.\r\n  - Fullscreen messages are now correctly displayed when the current emulated\r\n    system uses a resolution higher than your fullscreen resolution.\r\n  - Fixed debugger breakpoint when loading a save state.\r\n  - Added some new entrys to the checksum and compatibility lists,\r\n    and fixed few existing ones. Added a french flag, currently used\r\n    for games translated in french.\r\n\r\n\r\n MEKA 0.57                 Emulation: 97%     Speed: 57%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Note: I made lots of little sources changes in this version. Things have\r\n been tested, but in case you notice anything unusual, please contact me.\r\n\r\n  - Rewrote dynamic palette handler, minimizing actual hardware palette\r\n    changes, reducing snow and generally reducing flickering when games\r\n    were abusing of palette changes (like the \"Happy Birthday\" demo, or\r\n    some Game Gear games). Due to that change, Palette and Tile viewers\r\n    are now slighty slower than before, but since they are not used for\r\n    playing, it is fine.\r\n  - Rewrote hardware sprites collision emulation a more accurate way,\r\n    fixing Cheese Catastrophe (SMS) bonus catching. There was an easy\r\n    way to get it to work, but technically speaking, it was not the\r\n    right one. Instead I emulated the feature a better way so that\r\n    theorically, any tricky uses of it should be working. Speed might\r\n    have dropped of about 1 FPS on slow computers.\r\n    (Thanks to nop.nop for the bug report.)\r\n  - Added data dumping facilities for developers and hackers.\r\n    You can now dump the following to a file:\r\n      - RAM (raw or text hex/ascii)\r\n      - VRAM (raw or text hex/ascii)\r\n      - Palette (raw or text colors definitions)\r\n      - Sprites (raw or text sprites definition)\r\n      - VDP Regs (raw or text binary/hex)\r\n      - OnBoard Memory (raw or text hew/ascii)\r\n    Those functionnalities are available by starting MEKA with /DEBUG.\r\n  - Added Sega Keyboard (SK-1100) hardware detection emulation. You can\r\n    know use the emulated keyboard to play SG-1000 (and early SMS) games\r\n    supporting it.\r\n  - Added a 'none' value for joypad driver, to disable any kind of\r\n    detection (as it may be slow on some computers). See MEKA.INP.\r\n  - Battery backed RAM optional pages are now not saved when their\r\n    content is null.\r\n  - Optimized the technical information viewer that was previously\r\n    too slow. Also made cosmetic changes to the informations shown.\r\n  - Fixed error message that said MEKA was unable to write SaveRAM\r\n    to write, while it did correctly.\r\n  - Fixed savestate loading bug in some very specific cases when using\r\n    a custom mapper.\r\n  - Fixed sprite drawing in overscan video mode.\r\n  - The selected tile in the tile viewer is now refreshed if modified.\r\n  - Fixed PSG volume bug, where volumes 14 and 15 were actually the same.\r\n    (thanks to Martin Konrad for noticing it)\r\n  - Changed the 'palette_bright' option to a 'palette' option that can\r\n    be either 'muted' or 'bright', the later being now the default, since\r\n    many people suggested that it was better than the old default one.\r\n    Also added a switch in the GUI options box to change it dynamically.\r\n  - VSync is now automatically avoided if a speed faster than 70 hz is\r\n    being used. So you can use a blitter with VSync enabled and still\r\n    profit of accelerations if you want them sometimes (skip intros, etc..).\r\n  - Partially rewrote popup menu code. Also hacked a bit to fixed the bug\r\n    when more than 32 themes were enabled on the same time.\r\n  - Added the usual amount of new themes and new database entries.\r\n  - Added some new comments to the configuration file.\r\n  - Converted all ASM code to NASM format, for better portability.\r\n  - Ported MEKA to Windows. Cool.\r\n//  - Added NES emulation:\r\n//    - Scanline based PPU emulation, H/V Mirroring, Sprites.\r\n//    - Mappers 0, 1, 2, 3 emulation. Enough to play the classics.\r\n//    - Basic input emulation.\r\n//    - SaveRAM emulation.\r\n//    - Savestates are supported as well, with mappers dependent\r\n//      informations being saved.\r\n\r\n\r\n MEKA 0.56                 Emulation: 97%     Speed: 57%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added Sega Super Control Station emulation, codename SF-7000.\r\n    The SF-7000 is a rare addon for the Sega Computer 3000, providing it\r\n    with a 3\" Floppy Disk Drive, 64 kbytes of RAM, a parallel printer port\r\n    and a RS-232C port. The later two are only partially emulated as anyway\r\n    there is no way to use the emulated connection (ex: for printing) yet.\r\n    Many thanks goes to Marc Le Douarain for his help and dumps of his old\r\n    disks, and Ulrich Cordes for the FDC-765 emulation (see documentation).\r\n\r\n    I added in the documentation a paragraph about how to use SC-3000 and\r\n    SF-7000 Basic software, as it is needed to load programs for the later.\r\n    Also, I am still looking for a real SF-7000 and any softwares!\r\n\r\n  - Added sprite flickering emulation in video mode 5 (SMS/GG), and\r\n    interfaced so you can now enable it if you feel like playing shooters\r\n    with invisible bullets. It is available in the VIDEO->FLICKERING menu.\r\n  - MEKA is now ignoring those rarely present 64 bytes footers.\r\n  - Fixed Ninja Gaiden (GG version) hand on intermission animation.\r\n  - Fixed PAUSE button which was broken in version 0.55b.\r\n  - Fixed blinking sides when a program was using text mode (Sega Basic, ..)\r\n    with a border color different than black.\r\n  - Fixed Sega Keyboard letters color.\r\n  - Fixed /LOG command line option which was ignoring the given filename.\r\n  - Added and fixed entrys in the compatibility and checksum lists.\r\n  - Various minor changes - changed messages, fixed typos..\r\n\r\n\r\n MEKA 0.55b                Emulation: 97%     Speed: 57%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added configurable mouse speed values in the MEKA.INP file.\r\n  - Fixed mouse under Windows NT / Windows 2000.\r\n\r\n\r\n MEKA 0.55                 Emulation: 97%     Speed: 57%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added builtin documentation, accessible from the \"HELP\" menu.\r\n  - Entirely revamped the input system. I originally fixed Paddle Control\r\n    emulation then noticed the problem I was having with Super Racing was\r\n    due to a bug in the original game. I did not feel like adding a cheap\r\n    hack and beside it was time to clean it up, I just needed a reason :)\r\n    Inputs related changes you will notice are:\r\n\r\n      - Added configuration tool, showing small pictures of peripherals\r\n        being used (hope you like the pictures, as I spent a long time\r\n        drawing them). This tool allows you to see currently available inputs\r\n        sources, enable/disable them, and change their key/buttons mapping.\r\n        No more dealing with obscure scancodes numbers (finally).\r\n        To keep going with the MEKA tradition, every configuration bit is\r\n        stored in a human-readable and manually editable file: MEKA.INP.\r\n        You can access most of the functionnalities from under the interface\r\n        but experienced users might want to check this file out. The new\r\n        input system is high-level oriented and allows you to do many nice\r\n        things like playing with two pads on the same time or mapping pause\r\n        to a mouse button. Whatever you feel.\r\n      - Any joypad/joystick corresponding to the driver selected in MEKA.INP\r\n        should be automatically enabled on starting, and available for use.\r\n      - Renamed left occurences of peripherals that were incorrectly named\r\n        (Paddle Controller -> Paddle Control, Light Gun -> Light Phaser)\r\n      - Improved Paddle Control emulation so that they will work in Japanese\r\n        mode, and allowing Super Racing to detect a paddle when plugged on,\r\n        instead of the regular joypad.\r\n      - Fixed a precision bug in Paddle Control 2 emulation.\r\n      - Added support for a second Sport Pad / Trackball.\r\n      - Added digital input source emulation with the mouse, so basically\r\n        you can play any joypad game with a mouse now. Expect being really\r\n        frustrated with most games, but it is actually very cool for shooters\r\n        and games where you do not have to do 'long' movements. Try R-Type.\r\n\r\n  - Added 3-D Glasses emulation, with both software and hardware modes:\r\n      - Software mode let you play 3-D games by showing only\r\n        images of a choosen side (left or right).\r\n      - Hardware mode supports REAL Sega 3-D Glasses connected on\r\n        your PC through the communication port! See TECH.TXT for more\r\n        informations about how to build a Sega 3-D Glasses adapter\r\n        and enjoy a new dimension of videogaming :-)\r\n        Warning: 3-D Glasses support through the COM port is still not\r\n        in perfect stage, meaning that you may experience flickering.\r\n        A blitter with VSync enabled is *strongly* recommended.\r\n        Also stop playing every 30 minutes eyes you'll become blind :)\r\n\r\n//  - Added CodeMasters cartridge mapper emulation (for both Master System\r\n//    and Game Gear modes).\r\n//  - Added emulation for overscan video mode, and dynamic screen resizing\r\n//    while the game is running.\r\n  - Tweaked VDP code for potentially more accurate side effect emulation.\r\n  - Fixed sprite collisions in certain cases. The following Colecovision\r\n    games are now perfectly playable:\r\n      - Carnival (Bonus Level is ok)\r\n      - Jumpman Junior (Ladders on level 3 are ok).\r\n      - Pitfall 2 (No false hit on the third screen).\r\n      - Venture.\r\n    Thanks goes to the one who sent me a long e-mail about collision\r\n    detection some months ago, but which I unfortunately lost and was\r\n    then unable to answer. E-mail me if you are still around :)\r\n  - Fixed hard pausing. You can now safely take screenshots after pausing\r\n    with a message shown on the screen, as it will not be shown in the shot.\r\n  - Fixed loading of very small ROMs, which affected Tic Tac Toe on\r\n    Colecovision, and maybe your very own demos programs.\r\n  - Implemented Antiriad's hack to Allegro - used in Raine - to permit\r\n    usage of Sidewinders while their driver is loaded (not tested). Thanks!\r\n  - Fixed the Eagle blitter which was not centered and showed garbage\r\n    in some machines. Also fixed the default Eagle blitter configuration\r\n    which limited speed to 30 FPS even on a very fast system. What a loss!\r\n    By the way, Eagle does in fact looks nice with a few games. Try R-Type.\r\n  - Slighty optimized memory accesses and tile refresh.\r\n  - Changed the key to save screenshots from F12 to PrintScreen. If you\r\n    are using Windows, be sure to configure the properties of your DOS box\r\n    to enable the use of the PrintScreen key if you want to make screenshots.\r\n  - Added F12 shortcut to hard pause emulation.\r\n  - Added access to enabling/disable GUI Vertical Sync in the options box.\r\n  - Fixed a bug that prevented Battery Backed RAM or EEPROM to be saved when\r\n    freeing ROM.\r\n  - Added a technical document (TECH.TXT) with basis informations about\r\n    the systems, as well as the schematic for the 3-D Glasses adapter.\r\n  - Reduced default FM writing delay, that should speed up the two games\r\n    over-abusing of FM writes. Try R-Type title screen.\r\n  - Added various name and checksum entrys, and corrected many existing ones.\r\n    Should have noted out all Game Gear games running in Master System mode,\r\n    fixed some Colecovision names and date, and generally improved accuracy.\r\n    Thanks goes to Maxim and Luke2 for their precious help! :)\r\n  - Added Korean flag in the file loader and associated Super Tetris with it.\r\n    There are still several Korean games to dump, however.\r\n  - Fixed leap year calculation (for display of dates).\r\n  - Fixed a crashing bug when passing too many parameters on command line.\r\n  - Added the usual bunch of new GUI themes, and more pictures are available\r\n    from the homepage.\r\n  - Plenty of minor fixes here and here.\r\n\r\n\r\n MEKA 0.54b                Emulation: 97%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Made some very minor fixes.\r\n  - Added two new themes (Deep Purple and Deep Brown).\r\n\r\n\r\n MEKA 0.54                 Emulation: 97%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Updated to the documentation, improved many parts and added new things.\r\n    Please read it!\r\n  - Fixed invalid vertical sprite wrapping in video mode 2 (bug introduced\r\n    in version 0.51, slighty affecting The Castle and maybe other games).\r\n  - Added PSG wave synthesis sound rate setting in the configuration file.\r\n    Rate is no more fixed to a weird value like in all previous versions,\r\n    avoiding the clicks and noise with certains soundcards. You can also\r\n    change the rate to the default values of 11025, 22050 and 44100 Hz from\r\n    the GUI pop-up menus.\r\n  - Added separate PSG channel enabling/disabling. Mainly useful for\r\n    musicians who want to listen to different channels separately, but\r\n    it is also very fun to disable some channels and play games with\r\n    somewhat new musics :)\r\n  - Fixed FM bug when hard pausing and unpausing in some games.\r\n  - Addams Family, Operation Wolf and Sonic Blast now automatically run in\r\n    PAL/Secam mode when NTSC is selected, due to the games having bugs in\r\n    NTSC mode.\r\n  - Fixed the badly positionned line of Hang On in Hang On / Safari Hunt.\r\n  - If brutally forced to close (like when switching to a blitter using an\r\n    invalid resolution), MEKA now switch back to its starting directory.\r\n  - Added screenshot filename template to the configuration file. You can\r\n    now configure weither you want padding, short or long filenames, etc..\r\n    Also changed screenshot numbering starting value from 0 to 1.\r\n  - Added \"integer stretched\" display of the themes background pictures\r\n    (see MEKA.THM).\r\n  - Added new themes, some of them using nice background pictures you are\r\n    invited to download at http://www.smspower.org/meka/themes.\r\n\r\n\r\n MEKA 0.53c                Emulation: 97%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Game Gear compatibility rate is now of 95.80%. It is the only unperfect\r\n system and that's mainly due to the lack of LCD screen persistence of\r\n vision emulation.\r\n\r\n  - Kishin Douji Zenki very minor graphic bug was a bug in the game itself,\r\n    not in MEKA. Thanks goes to Adol brothers for their help on this one.\r\n  - Added a patch to fix a bug in Walter Payton Football (in the game itself)\r\n    preventing it to works on machines with a FM Chipset.\r\n  - Fixed Wanted patch, I had accidentally commented a line out.\r\n  - Fixed California Games 2 minor graphic bug when selecting the top left\r\n    entry of the menu (screwed in version 0.52). Thanks Pieter!\r\n  - Added new entrys to checksum and compatibility list.\r\n\r\n\r\n MEKA 0.53b                Emulation: 96%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n I finally figured out what was the problem of the major slow down in\r\n some video modes when page flipping was enabled. Actually using page\r\n flipping need to force vertical synchronisation in most video modes, so\r\n enabling them both will make the program synchronise twice per frame to\r\n the vertical refresh, causing speed to be limited to about 30/35 FPS.\r\n The default blitter definition files now have Page Flipping modes enabled\r\n by mode, replacing the obsolote VSync modes.\r\n\r\n  - Fixed a bug preventing files to appear in the file browser under DOS.\r\n  - Added all known Colecovision dumps to the checksum/names list.\r\n    Names are based on Cowering's GoodColeco utility.\r\n  - Game name is now dynamically updated under the GUI is a country change\r\n    affect the current name.\r\n  - Fixed \"Rise of the Robots\" by forcing NTSC mode when it is not enabled.\r\n  - Added a patch to fix a bug in Wanted (in the game itself) preventing it\r\n    to works on machines with a FM Chipset.\r\n  - Fixed a bug sometimes happening where disabling background layer\r\n    display wouldn't work.\r\n  - Added 5 new themes (commented by default).\r\n\r\n\r\n MEKA 0.53                 Emulation: 96%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Master System compatibility rate has now reached the perfect 100.00%\r\n assuming out of the 373 tested ROMs none was broken in a recent version.\r\n Something major have changed in this version and which might screw just\r\n about any game. So if you find anything unusual that might be a bug,\r\n please report it to me. As soon as possible I'll spend a week trying\r\n all games again.\r\n\r\n Enabling page flipping is known to cut down the speed by a factor of two.\r\n This is obviously a bug as page flipping should not affect performances\r\n so at the moment I suggest avoiding it and enabling VSync instead.\r\n\r\n As a side news, I have ported MEKA to FreeBSD/NetBSD. It probably compiles\r\n under Linux also, and whenever I can get my hands on a computer running\r\n Windows applications at a correct speed, a Windows port will be worked on.\r\n\r\n [RC3]\r\n  - Fixed temporary sound bug when loading savestates in certains cases.\r\n  - Added border surrounding selected tile in tile viewer.\r\n\r\n [RC2]\r\n  - Added TV Type switch to change between NTSC and PAL/SECAM.\r\n  - Improved tile viewer so that a click on a tile shows its number and\r\n    the tile itself. Might be useful for developers and ROM hackers.\r\n  - Improved file browser: added a \"Reload Directory\" button and a\r\n    \"Load Names\" button to load full game names for all files.\r\n  - Fixed GP Rider (GG) road corruption.\r\n  - Fixed NBA Action (GG) abnormal flickering.\r\n  - Fixed NBA Jam TE (GG, previously unknown bug) and Surfs Ninja (GG).\r\n  - Fixed reset key in Sega Keyboard emulation.\r\n  - Fixed Gear Game communication port emulation somewhat broken in\r\n    previous version and which affected Pac Attack.\r\n  - Fixed secret games left side of the screen bug in fullscreen mode.\r\n\r\n [RC1]\r\n  - Fixed Y's (Japanese).\r\n  - Improved auto frame skipper synchronization to the choosen speed.\r\n  - Added full TV Oekaki Graphic Board and Pen emulation, using mouse.\r\n    Button 1 simulate a pen press and button 2 simulates the pen being away\r\n    of the graphic board - when it is away you can use standard inputs. Now\r\n    you will be able to draw with the emulator ^_^\r\n    Thanks to Toshi for sending out the Graphic Board.\r\n  - Compiled with the newest patched Seal Audio Library, improving overall\r\n    sound quality (16-bit mode was somewhat useless in previous versions),\r\n    and ALLOWING SOUND TO WORK ON SOUND BLASTER 128 SOUND CARDS, finally.\r\n    A big thanks goes to whoever patched Seal for that.\r\n    (I guess it is someone to the MAME team, but I am not sure.)\r\n  - File browser now go in the root of drive if current directory is invalid.\r\n  - Removed a broken line in the MEKA.NAM file causing Back to the Future 3\r\n    to show a black screen.\r\n  - Added even more new entrys in the compatibility and checksum lists.\r\n\r\n  [Sources Changes]\r\n  - Command line handling now ignore case (for Unix version).\r\n  - Moved all sources for Marat Z80 Core to Z80MARAT/ directory.\r\n  - Fixed a lot of minor things for Unix/Windows portability.\r\n  - Revamped Eagle handling in makefile/#define. Now MEKA compiles\r\n    correctly without Eagle enabled.\r\n  - Rewrote UPDBUILD tool in C. No more Pascal needed to recompile.\r\n  - Added CONFIG_J.C/.H and CONFIG_V.C/.H with big drivers tables.\r\n  - Rewrote directory reading for file browser.\r\n  - Improved Makefile on various points.\r\n\r\n\r\n MEKA 0.52                 Emulation: 96%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Compatibility rates as of version 0.52:\r\n\r\n  Master System: 99.72%\r\n    (not perfect because of the Japanese version of Ys).\r\n  Sega Game 1000: 100.00%\r\n  Sega Computer 3000: 100.00%\r\n    (excluding emulation of optional peripherals such as the Sega Printer)\r\n  Game Gear: 95.03%\r\n    (excluding gear-to-gear emulation used by certains two players games)\r\n\r\n  - Fixed the minor glitches in:\r\n   - Back to the Future 2\r\n     (black section flickering between the road and status bar)\r\n   - Gangster Town\r\n     (little line of skyblue pixels on the top of the car in the first scene)\r\n   - Operation Wolf\r\n     (minor graphic glitches on the top of the bottom bar when shooting)\r\n\r\n Tested Wonderboy in Monsterworld on a real system and confirmed the minor\r\n glitch when the menu is vertically scrolling is a bug in the game itself.\r\n\r\n Did some research about Ys (J/FM), with help from Toshi.\r\n It is not considered anymore as a bad dump. The bug happening in MEKA also\r\n happens when using a real Game Gear or a Megadrive with an adapter.\r\n However the game show a perfect status bar on a Japanese Master System,\r\n so the bad behavior is considered as a bug of MEKA, even if in the first\r\n place it is due to a bug in the game code taking advantage of an odd\r\n behavior of the Japanese Master System.\r\n\r\n Also:\r\n  - Improved run-time TMS9918 video mode detection.\r\n  - Fixed Hyper Pro Yakyuu 92 (GG).\r\n  - Reduced flickers in NBA Action (GG).\r\n  - Fixed freezing until a key is pressed when loading the Japanese BIOS.\r\n  - Fixed yet another silly bug introduced in previous version and screwing\r\n    some SC-3000 software such as the Sega Basic.\r\n  - Added new entrys to compatibility and checksum lists. Also redone\r\n    SC-3000 list with names corrections for Japanese educational softwares.\r\n  - Fixed potential VDP bug - wasn't affecting any games, but could have.\r\n  - Implemented MAME Z80 CPU Core but did not enabled it in the public\r\n    version as it doesnt bring anything better than Marat's core: they\r\n    are on par, but MAME license is quite limiting.\r\n  - Improved documentation inside of the MEKA.BLT file.\r\n  - Fixed a bunch of minor bugs. Fixed handing of ROM smaller than eight\r\n    kilobytes. Fixed empty entry creation in the VFN database. Fixed a bug\r\n    in windows repositionning when changing resolution.\r\n  - Reduced executable size.\r\n  - Added preliminary Action Replay emulation (private).\r\n\r\n And also:\r\n  - Added background picture caching for a faster switch to the GUI when\r\n    a big image is used on background.\r\n  - Added a bunch of new themes into the distribution package.\r\n    Background pictures for some of the themes are available on a new\r\n    site at http://www.emucamp.com/meka/themes\r\n  - As of now the PICS/ directory should be considered as the one everyone\r\n    have to use to share themes easily. You can still have your own themes\r\n    pictures stored anyway, anyway.\r\n\r\n\r\n MEKA 0.51 OC Edition      Emulation: 96%     Speed: 56%     Features: 79%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n SG-1000 perfect compatibility rate is now of 100%\r\n\r\n  - Added the possibility of adding a custom background picture in themes.\r\n    Keyword to be used in MEKA.THM is \"background_pic\". Pictures need to\r\n    be in PCX format and a maximum of 128 colors will be used. You can\r\n    zoom, tile or center the picture using the appropriate keywords.\r\n  - Added desktop saving. Active windows and their position are now saved\r\n    and restored back when loading MEKA.\r\n  - Rewrote sprite engine for video modes 1/2/3, fixing the minor bug in\r\n    Pitfall 2 (SG-1000) and Rockn'Bolt (SG-1000). Probably also fixed some\r\n    Colecovision games. Added optional flickering emulation.\r\n\r\n\r\n MEKA 0.50                 Emulation: 96%     Speed: 56%     Features: 78%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n Master System perfect compatibility rate is now of 98.90%\r\n Games still causing problems are:\r\n   Back to the Future 2\r\n     (black section flickering between the road and status bar)\r\n   Gangster Town\r\n     (little line of skyblue pixels on the top of the car in the first scene)\r\n   Operation Wolf\r\n     (minor graphic glitches on the top of the bottom bar when shooting)\r\n   Wonderboy in Monsterworld\r\n     (minor glitche on the menu vertical scrolling line when pressing pause)\r\n Found out that the bug in Aerial Assault was happening on a real system.\r\n So it's not considered as a bug anymore.\r\n\r\n Next step will be to improve Game Gear perfect compatibility rate (94% now).\r\n\r\n [RC5]\r\n  - Added icons package from various contributors (see ICONS.ZIP).\r\n  - Fixed SG-1000/SC-3000 border color emulation, screwed in RC4.\r\n  - Added Massage savegame converter. Rename a .MSD file in the MEKA\r\n    naming convention and it will be automatically converted when loading.\r\n    You might in some cases experience sound or various other problems\r\n    with certain games. The usual solution is to pause and unpause the\r\n    game, else try to change screen/level.\r\n  - Fixed potential palette problems with some video card/mode couples.\r\n  - Slighty improved voice emulation.\r\n  - Compiled with latest Allegro library, adding support for the following\r\n    joysticks/pads drivers:\r\n      - DB9 pads through parallel ports (allow to plug real SMS pads!)\r\n      - PC Engine pads through parallel ports\r\n      - Saturn pads with IF-SEGA interface cards for PC.\r\n\r\n [RC4]\r\n  - Fixed Colecovision emulation, screwed in RC2/RC3.\r\n  - Fixed 32k RAM mapper (The Castle, Othello..) screwed in RC2/RC3.\r\n    (The cause of all these bugs is the rewrite of the drivers system).\r\n  - Revamped palette update handling.\r\n  - Made some structural optimisations, increasing speed of a few percents.\r\n    Now Phantasy Star runs at 49 frame per seconds on my computer !\r\n  - Fixed palette applet size when first loading a SG-1000/SC-3000/Coleco\r\n    game from the commandline.\r\n  - Fixed bug virtual longfile name self created list saving.\r\n  - Added new games and product numbers to compatibility and checksum lists.\r\n  - Rewrote palette handling, reducing snow and slighty increasing speed.\r\n  - Blitter improvments:\r\n      - Added page flipping.\r\n      - Added Double TV Mode blitter.\r\n      - Added \"Perfect\" blitter definition with all best features enabled\r\n        (TV Mode, Doubled Fullscreen, Page Flipping and Vertical Sync) for\r\n        people with very fast computer.\r\n  - Added wide effective area emulation (2 Star Trek games on Game Gear).\r\n\r\n [RC3]\r\n  - Reduced savegame size for SG-1000 and Colecovision systems.\r\n  - Implemented better systems hardware differences to allow detection.\r\n    Renaming Pit Pot (SMS) to the .SG extension and running it will\r\n    now show a custom screen! Thanks goes to Yujiro to the notice.\r\n  - Fixed pending interrupts that were screwed in RC2.\r\n  - Fixed Back to the Future 3 for Master System (minor bug on title screen).\r\n  - Fixed Out Run for Game Gear (musics now play).\r\n  - Fixed Sonic Drift 2 for Game Gear (bottom of screen is now perfect).\r\n  - Sega Basic Level 3 Version 1.1 Japanese now works with a patch.\r\n\r\n [RC2]\r\n  - Optimised \"double\" blitter.\r\n  - Fixed a sometimes happening savegame loading bug introduced in RC1.\r\n  - Fixed some emulation bugs introduced in RC1: Out Run, Back to the\r\n    Future 2, Spiderman vs the Sinister Six, and probably billions of\r\n    other are working again.\r\n  - Fixed a text overlapping screenshot bug introduced in RC1.\r\n  - Fixed rare crashing bug with the blood cursor GUI effect.\r\n\r\n [RC1]\r\n  - Improved emulation:\r\n      - Rewrote Light Phaser emulation. These games are now playable:\r\n         - Laser Ghost (Light Phaser is optional)\r\n         - Missile Defense 3D\r\n         - Operation Wolf\r\n         - Shooting Gallery\r\n         - Wanted\r\n      - Robocop 3 (SMS) does not crash anymore when pausing.\r\n      - Added Game Gear vertical scrolling lock emulation (fixing Fray).\r\n      - Slighty optimized Master System and Game Gear screen refresh.\r\n      - Fixed accidentally left bug in SG-1000 interrupt emulation, fixing\r\n        Championship Lode Runner and probably other games.\r\n      - Fixed accidentally left minor scrolling bug in a few games (Castle of\r\n        Illusion to name one. I forgot about the others).\r\n  - Rewrote blitters handling system:\r\n      - Added blitters definition file (MEKA.BLT) where you can configure\r\n        fullscreen video modes drivers, resolution and effects.\r\n      - Added \"TV Mode\" blitter that simulate accurates TV scanlines.\r\n      - Added \"Double\" blitter. Nice uses of it are:\r\n          - Doubling screen with 512x384 mode (getting true Fullscreen).\r\n          - Doubling screen in a tweaked mode (Game Gear with big pixels).\r\n            If you find any suitable mode for Game Gear other than the ones\r\n            listed in the MEKA.BLT file, please tell me about it.\r\n      - Removed hotkeys to enable/disable the Scanlines, Eagle and Parallel\r\n        effects. They are now part of blitters configuration. The current\r\n        blitter can be changed by pressing F1.\r\n  - Rewrote frameskip handling system and added speed throttling.\r\n      - F2 key now switch between standard and automatic frameskipping.\r\n      - F3 decrease speed in automatic mode, else decrease frameskip.\r\n      - F4 increase speed in automatic mode, else increase frameskip.\r\n  - Rewrote drivers handling system. It is easier to maintain internally now.\r\n  - Fixed configuration file problem when using PSX and N64 joypads.\r\n  - Added mouse button 2 shortcut to switch between the two Light Phasers.\r\n  - Added some new GUI themes - uncomment in MEKA.THM file to use them.\r\n  - Fixed file browser bug when overwriting recognized ROMs with unknown\r\n    ones would keep the old, recognized name showing.\r\n  - Fullscreen captures now ignore status message and filters/effects.\r\n  - Palette viewer now show no more than the correct number of colors\r\n    in SG-1000/SC-3000/Coleco mode.\r\n  - Fixed a screenshot naming bug with short ROM names.\r\n\r\n\r\n MEKA 0.40                 Emulation: 96%     Speed: 53%     Features: 77%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n [RC2]\r\n  - Fixed names in compatibility and checksum lists, differencied names for\r\n    alternate version, added new Japanese names (thanks to Luke & Casiopea).\r\n  - Fixed Choplifter (SG-1000).\r\n  - Fixed Coleco emulation somewhat screwed in RC1.\r\n  - Fixed bug in Legend of Illusion (SMS) at the sunken ship stage\r\n  - Improved memory mapping, letting Space Gun (SMS) to start.\r\n  - Added improved filter for old configuration file. As the keyboard\r\n    keycodes have changed in this version they cannot be imported.\r\n\r\n [RC1]\r\n Master System perfect compatibility rate is now of 97.78%\r\n Games still causing problems are:\r\n   Aerial Assault (minor scrolling glitch on the beginning of a level)\r\n   Back to the Future 3 (minor bug on title screen)\r\n   Missile Defense 3D (buggy lightgun emulation)\r\n   Operation Wolf (buggy lightgun emulation)\r\n   Robocop 3 (pausing crashes the game)\r\n   Shooting Gallery (buggy lightgun emulation)\r\n   Wanted (buggy lightgun emulation)\r\n   Wonderboy in Monsterworld (glitches when pressing pause)\r\n\r\n Game Gear perfect compatibility rate is 94.55%\r\n 17 games are still causing problems, including 5 which requires simulation\r\n of LCD screen visual persistance to produces transparency effect, 3 using\r\n an internal EEPROM to save custom teams, 2 having bad scrolling positions,\r\n and the 7 others:\r\n   GP Rider (road distort itself after a moment)\r\n   Kishin Douji Zenki (one line of clouds is not scrolling in fighting level)\r\n   NBA Action (sprites flickering, might be the real game behavior)\r\n   Out Run (no music for some reasons)\r\n   RBI Baseball '94 (sprites not visible in top view, might be a bad dump)\r\n   Sonic Blast / G-Sonic (micro title bug in US/Euro mode)\r\n   Sonic Drift 2 (bottom line has a bad scrolling offset)\r\n\r\n Sega Game 1000 perfect compatibility rate is 97.40%\r\n Games still causing problems are:\r\n   Pitfall 2 (minor glitch at the top when dying)\r\n   Rockn' Bolt (sprite priorities bug on lift when starting)\r\n\r\n  - Improved emulation on various point, fixing:\r\n      - Altered Beast (SMS): title screen effect is now ok\r\n      - Cool Spot (SMS): no more minor flickering\r\n      - Evander Holyfield Boxing (GG): no more blue screen every odd frame\r\n      - Global Gladiator (SMS): no more minor flickering\r\n      - Gun Star Heroes (GG): no more glitches here and here\r\n      - Hang On / Safari Hunt (SMS): fixed a bug preventing to start sometimes\r\n      - Heavy Weight Champ (SMS): music play on introduction\r\n      - Hurricanes (GG): no more blue screen every odd frame\r\n      - Impossible Mission (SMS): room are showing properly when entering\r\n      - NBA Jam (GG): playfield is ok\r\n      - PGA Tour Golf (SMS): playfield is ok before game start\r\n      - Out Run (GG): no more flickering\r\n      - Orguss (SG-1000): no hang when exploding with the small robot\r\n      - Safari Hunting (SG-1000): no hang when entering in the game area\r\n      - Safari Race (SG-1000): better response of button on title screen\r\n      - Shining Force 1 (GG): fixed random crashes\r\n      - Shining Force 2 (GG): fixed random crashes\r\n      - Shining Force 3 (GG): fixed random crashes\r\n      - Speedball 2 (SMS): no more flickering\r\n      - Sonic Drift (GG): now works perfectly\r\n      - Sonic Drift 2 (GG): now works almost perfectly, minor bug on bottom\r\n      - Terminator 2: Judgement Day (GG): no more blackout every odd frame\r\n      - WWF Steel Cage Challenge (SMS): no more moving bug on barriers\r\n      - Xenon 2 (SMS): no more flickering\r\n  - Custom IPeriod values for Aerial Assault (SMS), Barcelona 92 (SMS),\r\n    Gokuaku Doumei Dump Matsumoto (SMS) and Pro Wrestling (SMS) are not\r\n    needed anymore due to improved emulation, and were removed. The only\r\n    game left needing a custom IPeriod value is \"Shadow of Beast\" which\r\n    sometimes crash on title screen with the default value.\r\n  - Improved voice emulation, many games sound correct now (not all).\r\n  - Updated to Allegro WIP in prevision to future improvments. In the\r\n    meanwhile, the new version provides drivers for Gravis Grip, PSX and\r\n    Nintendo 64 joypads, as well as better Sidewinder support (untested).\r\n  - Rewrote hardware sprite collision emulation. Might break some games,\r\n    please report if you discover anything unusual!\r\n  - Improved Master System Sportpad controller emulation.\r\n    Games are easier to play now, even if it is not perfect.\r\n  - Added (buggy) EEPROM model 93c46 emulation. This chipset is used by\r\n    three Game Gear baseball games to save custom teams and game progress.\r\n    Pretty though one to emulate, but that's the only way to reach perfect\r\n    emulation ^_^\r\n  - Added Rapid Fire emulation.\r\n  - Improved video mode 2 emulation, fixing Cosmo Fighter 2 (Coleco).\r\n  - Added video mode 3 emulation, used by two painting programs for the\r\n    Coleco Vision, and very probably by many SC-3000 programs.\r\n  - Definitively removed the snow effect that pissed everyone :-(\r\n    I would have stopped on the 28 of December, anyway.\r\n    Instead, added the \"special=snow\" parameter in the theme file, to\r\n    create your own themes using that effect.\r\n  - Added Christmas and Sunrise GUI themes.\r\n  - Added product numbers for all Game Gear games released in Japan and\r\n    dumped (about 150). Also added a bunch of new names and fixed some.\r\n  - Added IPERIOD_SG1000_SC3000 setting in the configuration file.\r\n  - Added a patch to fix the bug in Sport Pad Soccer which make it hang on\r\n    systems without the FM chipset.\r\n  - Fixed bad screen size bug in certain cases after freeing ROM.\r\n  - Added /LOG command line parameters to log all messages to a file.\r\n  - Rewrote message applet from scratch. It does not slow down anymore\r\n    when the number of messages per second is too important (+1000).\r\n  [sources changes]\r\n  - Revamped mapper handling.\r\n  - Revamped backed memory handling.\r\n\r\n\r\n MEKA 0.32c                Emulation: 95%     Speed: 53%     Features: 77%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  (minor update - version number still the same in the executable)\r\n  - Fixed a stupid little damned bug causing the program to crash under DOS.\r\n  - Added IPERIOD_COLECO setting in the configuration file.\r\n    Do not touch unless you know what it means!\r\n\r\n\r\n MEKA 0.32b                Emulation: 95%     Speed: 53%     Features: 77%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  (minor update - version number still the same in the executable)\r\n  - Fixed slodown bug when loading a non Coleco ROM after a Coleco ROM.\r\n  - Fixed a bug preventing from switching the machine Off in certain cases.\r\n  - Fixed a minor file browser bug (selection was lost when using mouse).\r\n  - Added some new checksums for various hacks.\r\n  - Added a new GUI theme.\r\n\r\n\r\n MEKA 0.32                 Emulation: 95%     Speed: 53%     Features: 77%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed the following games:\r\n      - Andre Agassi Tennis [SMS, GG]\r\n      - Greendog [GG] (Sega logo now shake, it did not before)\r\n      - Panzer Dragoon Mini [GG]\r\n      - Pit Fighter [SMS]\r\n  - Improved emulation in the following games:\r\n      - PGA Tour Golf [SMS] (level presentation now scroll - buggy)\r\n      - Sonic Spinball [SMS, GG] (lake in introduction now scroll - buggy)\r\n  - Fixed a VDP bug introduced in 0.31 that affected Rescue Mission (and\r\n    probably many other games, too).\r\n  - Added .BIN extension in the file browser (for some Colecovision ROMs).\r\n  - Fixed incorrect palette of Colecovision picture after freeing ROM.\r\n  - Updated Colecovision compatibility list, Added a new GUI theme,\r\n    Added checksum and names for a bunch of SMS hacks.\r\n  - Improved debugger (still not for public consumption).\r\n\r\n\r\n MEKA 0.31                 Emulation: 95%     Speed: 53%     Features: 77%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n (YM-2413 emulation is disabled by default because of many people who\r\n  do not know about the existence of that chipset and complain about the\r\n  musics and sound effects not being the same as they used to hear. Now\r\n  that you know about it, feel free to enable YM-2413 emulation yourself).\r\n\r\n  - Updated various chapters of the documentation. Please read it!\r\n  - Added ZIP files support. Also improved file handling in general.\r\n    Warning: loading ZIP files which do not contains valid ROM images may\r\n    crash the program when it comes to emulating a non Z80-code file.\r\n  - Made some minor optimizations of screen refresh.\r\n  - Fixed a bug that caused games not to run before being reseted\r\n    when in Japanese mode with the BIOS enabled.\r\n  - Fixed a bug which cause the START button to be randomly pressed just\r\n    after loading a Game Gear savegame.\r\n  - Added a patch to fix the bug in American Pro Football that make it\r\n    hang on systems with the FM chipset.\r\n  - Fixed too early palette setting when loading a SG-1000/SC-3000/Coleco\r\n    game from the command line.\r\n  - Added support for sprites both doubled and zoomed.\r\n  - Added options box with various flags modifiable directly under the GUI:\r\n     - Enable/disable startup BIOS logo.\r\n     - Keep file browser open after loading game.\r\n     - Switch to fullscreen mode after loading game (new option).\r\n     - Enable/disable virtual long file names (new option).\r\n     - Enable/disable messages in fullscreen mode.\r\n  - Slighty improved dynamic palette system, fixing Moldorian and other\r\n    games, until a better fix could be applied.\r\n  - Added an option to show games product numbers.\r\n  - Game comments are now displayed under the GUI, and a warning is given\r\n    on known bad dumps. Any cool informations and comments that could be\r\n    included in the default distribution are welcome.\r\n  - Updated Colecovision support (finally):\r\n     - Improved keypad emulation. Mapped # and * keys on the keyboard.\r\n       Their corresponding keys are minus and equals, next to the 0.\r\n     - Fixed garbage sound on the beginning of some games.\r\n     - Improved interrupt emulation.\r\n     - Fixed joypad emulation in some cases.\r\n     - Added Colecovision picture in the graphical user interface.\r\n//  - Added snow flakes for Christmas :)\r\n  - Reorganized and cleaned various parts of the sources. Improved\r\n    widgets and configuration file handling (no visible changes).\r\n  - Updated compatibility and checksum lists with new entrys. Added and\r\n    fixed even more Japanese names. Added flags here and here.\r\n\r\n\r\n MEKA 0.30                 Emulation: 95%     Speed: 52%     Features: 75%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n [SOUND]\r\n  - Hiroshi added a preliminary FM Voice Editor.\r\n  - Added sound rate variable in the configuration file.\r\n  - Fixed FM emulation bug in Wonderboy 2 / Monster World 1 / Monica 1.\r\n  - FM writes are now delayed, and FM musics are now in better sync with PSG.\r\n [BIOS]\r\n  - Hiroshi dumped the original Japanese Master System BIOS. Then I hacked\r\n    and interfaced it to includes it in MEKA. To watch the demo included\r\n    in the Japanese SMS: change the machine country to Japanese, remove\r\n    cartridge if any is loaded and switch the power ON.\r\n [EMULATION]\r\n//  - Implemented Richard Mitton's new assembly Z80 core: RAZE.\r\n//    The following games are now fixed without tricking with the IPeriod:\r\n//      - Pro Wrestling (SMS)\r\n//      - Gokuaku Domein Dump Matsumoto (SMS)\r\n  - Fixed a bug in VRAM access emulation (AX Battler sprites now works).\r\n  - Improved dynamic palette system:\r\n      - No more color bug in Itchy & Scratchy (GG) and Bust a Move (GG)\r\n      - Less flickering in Space Harrier (GG) menu\r\n  - Improved palette handling when a game quickly change the video mode\r\n    in the middle of a frame, fixing Back to the Future 2 (SMS).\r\n  - Fixed title screen bug in California Games 2 (SMS).\r\n  - Fixed top screen flickering in Addams Family (SMS)\r\n  - Fixed Pop Breaker (GG). I did introduce a bug just before releasing 0.10.\r\n  - Fixed dirty first column when reseting some SG-1000 games.\r\n  - Fixed dirty first column on badly programmed SMS games (Jurassic Park).\r\n [INTERFACE]\r\n  - Improved file browser:\r\n      - Added keyboard input (arrows, page up/down, home/end, letters)\r\n      - Added little flags next to Japanese, Brazilian and Australian games.\r\n      - Added a configuration switch to keep the browser open after loading.\r\n      - Selected file is now kept after loading a game.\r\n  - Rewrote some parts of the GUI engine (no visual changes).\r\n [VARIOUS]\r\n  - Fixed a command line bug.\r\n  - The pause/start button has been moved to the SPACE key for two reasons:\r\n    first, some games use it as an action button, and secondly, when the file\r\n    browser is open it would interfer with it because of the ENTER key.\r\n  - Added patch to fix Sega logo color in the Ninja Gaiden bad dump.\r\n  - Added tons of new entrys to the checksum, name and compatibility lists.\r\n  - Added 3 new GUI themes (uncomment manually or enable with WonderTheme).\r\n  - A bunch of other minor fixes and improvements.\r\n\r\n\r\n MEKA 0.20                 Emulation: 95%     Speed: 52%     Features: 68%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Removed delays when accessing to soundblaster hardware registers,\r\n    resulting in a 20 frame per seconds speedup in R-Type, and no more\r\n    slowdowns in Wonderboy 3 with YM2413 emulation enabled. If you have\r\n    problems with this version, try setting the value back to 16 in the\r\n    configuration file, and be sure to contact me.\r\n  - Added automatic peripheral type switching.\r\n  - Added Sport Pad controller emulation.\r\n  - Improved Paddle controller emulation (much more precise).\r\n  - Finally managed to understand peripheral detection, so you can\r\n    play Out Run with the Paddle controller enabled (ala Steering Wheel)\r\n    for the first time in your life :-)\r\n  - Fixed Light Phaser emulation bug in Operation Wolf.\r\n  - Added a switch to enable/disable YM-2413 emulation inside of the GUI.\r\n  - Added a switch to change country inside of the GUI.\r\n  - Emusphere.com sucks (just checking if they ever read what they paste).\r\n  - Messages are now shown in fullscreen mode, making things a bit slower.\r\n    You can disable that feature in the configuration file.\r\n  - Fixed snow when VSync is enabled and colors are being updated. Check the\r\n    Star Wars introduction to notice the difference. (thanks to Lord_B).\r\n  - Major checksum, name and compatibility lists update. Added more than\r\n    200 new entrys, fixed some names, and added more product numbers and\r\n    Japanese name equivalents. (special thanks to Jossa and Tincho DJ)\r\n  - Fixed a potential nationalization bug.\r\n  - Added hard pause feature, available from the menu or with CTRL-P.\r\n  - Added ALT-F11 hotkey to enable/disable the background layer (for\r\n    sprites ripping).\r\n  - Added values in the configuration file to resize the file browser.\r\n  - Added values in the configuration file to remap the joystick buttons.\r\n  - Added necessary menu entrys to swap keyboard and gamepad buttons.\r\n  - Added two new GUI themes, courtesy of Tincho DJ. Uncomment them in the\r\n    default theme file or enable them with Wonder Theme.\r\n  - Updated savegame format (backward compatible, of course).\r\n  - Increased end delay for non registered users.\r\n  - A few other cosmetic changes.\r\n\r\n Special thanks for this release goes to James McKay for having figured the\r\n big part of the controller thing by originally hacking Sport Pad Football.\r\n\r\n And no thanks to the author (no name given) who always \"forget\" what he\r\n programmed a week ago, just like if he was competing.\r\n\r\n\r\n MEKA 0.13.1                 Emulation: 94%     Speed: 52%     Features: 66%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed many crashing bug introduced in version 0.13.\r\n  - Fixed FM persistant sound when loading a PSG game after a FM game.\r\n  - Fixed a bug when trying to free a ROM when the BIOS logo is running.\r\n  - Now you can load a savegame while the BIOS logo is running.\r\n  - Fixed Shining Force 3 (Game Gear).\r\n  - Added some more entrys in the compatibility and checksum lists.\r\n\r\n\r\n MEKA 0.13                   Emulation: 94%     Speed: 52%     Features: 66%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non emulation bug fixed.\r\n  - Added an option to free the current loaded ROM (to play the snail game).\r\n  - Added Colecovision emulation.\r\n  - Color themes are no more hardcored into the executable, so you can create\r\n    your own ones by editing the MEKA.THM file. Added the following new ones:\r\n      - Girl's Power (by me)\r\n      - Monochrome (by Limbs a Flyin')\r\n      - Necro (by Roni)\r\n      - Grey Box (by Puyolin and me)\r\n  - Added the necessary code for handling registration keys. Now registered\r\n    users have a permanent keyfile that unlock MEKA.\r\n  - All pause buttons bug with or without joypads enabled should be fixed\r\n    now, although I still cannot test the code.\r\n  - Fixed snow in SG-1000/SC-3000/Colecovision games.\r\n  - Fixed a keyboard lock bug that happened sometimes (mainly when starting\r\n    \"BrAin waSH\" but also in some other cases).\r\n  - Updated savegame file format. Old files can still be loaded with this\r\n    version, but you won't be able to play the new savegames with an older\r\n    version. Oh well, who cares ?\r\n  - Removed SMS background picture anti-aliasing to fit with all color themes\r\n    and added a picture when no cartridges is inserted.\r\n  - Some optimizations in SG-1000/SC-3000/Colecovision games.\r\n  - Added FM patch for Monica Em: O Resgate.\r\n  - Added a few more titles to the compatibility and checksum lists.\r\n\r\n\r\n MEKA 0.12                   Emulation: 94%     Speed: 52%     Features: 64%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added preliminary voice emulation.\r\n  - Added joystick and video drivers in the configuration file.\r\n  - Fixed the bug that prevented VESA modes to be usable.\r\n  - Fixed PSG/FM volumes.\r\n  - Fixed SaveRAM bug.\r\n  - Fixed a BIOS bug when no ROM was loaded in Japanese mode.\r\n  - Added an option to disable background refresh (for GFX ripping).\r\n  - Fixed virtual long filename duplicates creation.\r\n  - Changed default IPeriod to 228 and updated the list.\r\n  - Fixed Shining Force 2.\r\n  - Added new entrys into checksum and compatibily lists.\r\n  - Improved double dump detection, via a tolerance system.\r\n  - Added BrainWash game by Gollum.\r\n  - Added PoNG game by Johannes Holmberg.\r\n  - Some minor optimizations.\r\n\r\n\r\n MEKA 0.11                   Emulation: 94%     Speed: 52%     Features: 63%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed sound engine, improved FM emulation.\r\n  - Mapped start/pause to joystick.\r\n  - Added Tetris game by Archeide.\r\n  - Fixed Orguss.\r\n  - Fixed Power Strike.\r\n\r\n\r\n MEKA 0.10                   Emulation: 94%     Speed: 52%     Features: 62%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added an about box.\r\n  - Added virtual long file name (c)(r)(tm) support.\r\n  - Added video mode integer conversion (for config file).\r\n  - Added an option to use a brighter and more accurate palette.\r\n  - Finished implementing BIOS (US/European Master System mode only).\r\n  - Added an option to disable BIOS logo on startup.\r\n  - Fixed random crashes due to a sound bug.\r\n  - Various non-emulation related bugs fixed.\r\n  - Improved dynamic palette handling, fixing Magical Tarutokun.\r\n  - Better support for special mappers (used in Castle, Sega Basic, etc..).\r\n  - Added some more entrys to the checksum and compatibility lists.\r\n  - Fixed minor savegame bug with some Game Gear games.\r\n\r\n\r\n MEKA 0.0.42 [private]       Emulation: 94%     Speed: 52%     Features: 60%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non-emulation related bugs fixed.\r\n  - Added a file browser / ROM loader, from the GUI !\r\n  - After hundred hours of research, I finally found and corrected *the* bug\r\n    in Marat's Faizullin Z80 core. The following games are now fixed:\r\n      - Bart VS Space Mutants (Master System and Game Gear versions).\r\n      - Space Harrier 3D (original and alternate versions).\r\n      - Tazmania (Game Gear version).\r\n  - Added an hidden game, courtesy of Johannes Holmberg (special guest :).\r\n  - Improved BIOS support (now the instruction screen is shown).\r\n  - Message stopped being displayed in the status bar in version 0.0.39, and\r\n    no one noticed that.. fixed.\r\n  - Fixed a potentiel hardware sprite collision bug.\r\n  - Fixed NTSC mode detection.\r\n  - Fixed a screenshot filename bug.\r\n  - In Japanese mode, Japanese name are now shown if available.\r\n  - Fixed and improved widget code.\r\n  - Fixed Eagle screen refresh position.\r\n  - Sound synchronisation to CPU clock is more precise now (3.574595 mhz).\r\n  - Added support for paddle limitation (no more LEFT+RIGHT bug in Wonderboy\r\n    in Monsterland, although I know some people liked the bug :-).\r\n  - Fixed various bugs related to dynamic ROM loading.\r\n  - Restructured the code to allow changing games while MEKA is running.\r\n  - Fixed a minor bug in configuration file parsing.\r\n  - Fixed UP and DOWN arrows in keyboard emulation (they were inverted).\r\n  - Corrected some mistakes in the documentation (thanks to Keuuuuviiiiin).\r\n  - Fixed a stupid bug introduced a few minutes before finishing version 41\r\n    and that screwed the dynamic palette handler. If you were wondering why\r\n    Power Strike 2 introduction was even worse than in version 40, then you\r\n    have an answer now :-)\r\n\r\n\r\n MEKA 0.0.41 [private]       Emulation: 93%     Speed: 52%     Features: 54%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed a nationalization bug (Pop Breaker).\r\n  - Added auto country setting in the checksum list (Pop Breaker).\r\n  - Fixed a major bug in checksum calculation. I don't even understand why\r\n    does it worked before :)\r\n  - Fixed bug that caused major slow down on certains games using FM musics.\r\n  - Fixed a crashing bug when running the program without parameters.\r\n  - Rewrote the dynamic palette engine. As a result:\r\n     - NO MORE SNOW ON SCREEN !\r\n     - The emulator now runs slighty fasters (+5 FPS).\r\n     - Power Strike 2 (Game Gear version) introduction was fixed.\r\n  - Minor change to the interrupt system. Tell me if something was broken.\r\n  - Fixed various sound related bugs.\r\n  - Added detection for roms that were dumped bigger as they are.\r\n  - Updated a lot of checksum entrys, added a bunch of new games or different\r\n    version of existing games, started adding Japanese equivalents of some\r\n    game names, added some more ID numbers, and a few comments.\r\n  - Finished and added my Wonderboy 3 crack. Now you can hear FM musics\r\n    without having to play in Japanese mode !\r\n  - Fixed various bugs to make Castle (SG-1000 + 32kb on board RAM) working.\r\n    This game absolutly rocks ! (and it is very addictive :)\r\n  - Optimized screen refresh in Game Gear mode.\r\n  - Fixed a bug with checksum options parsing on first load (Altered Beast).\r\n  - Optimized text mode screen refresh (SC-3000) using pre-calculated tables.\r\n  - Fixed Up Arrow in SC-3000 keyboard emulation.\r\n  - Fixed a bug that screwed SaveRAM when doing an Hard Reset.\r\n  - Added complete checksum and name listing for Game Gear games, by Mxs.\r\n  - Finally took the time to sort my Game Gear collection and get the missing\r\n    games. Tested some games that were marked as \"non-working\" in previous\r\n    versions, and many of them are now working. Updated compatibility list.\r\n  - Removed support for pending interrupts (it was broking a few games).\r\n  - Fixed a bug when sound was disabled.\r\n  - Added an option to permanently set default country in configuration file.\r\n  - Added a \"/US\" command line parameter.\r\n  - Recompiled Allegro with Pentium optimizations.\r\n\r\n\r\n MEKA 0.0.40 [private]       Emulation: 92%     Speed: 51%     Features: 53%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n In this version, I have changed a lot of \"vital\" things in emulation\r\n (VDP accesses, IPeriod and line interrupts).\r\n Be sure to tell me if you notice *any* broken game !\r\n\r\n  - Implemented Hiro-shi improved FM emulation code !\r\n    Please note that FM hardware emulation is a very CPU intensive process,\r\n    and therefore you should disable it if you doesn't have a fast computer,\r\n    or the games that use it will become very slow ;)\r\n    Also, there are still bugs in some games (Wonderboy 3, for exemple).\r\n  - Now compiled with SEAL 1.0.6. Should fixes bugs with newer soundcards.\r\n  - The defaults VDP registers values are now the same as set by the BIOS.\r\n  - Fixed lightgun position limits in fullscreen mode.\r\n  - Fixed a VDP bug introduced in 0.0.39.5 (Wonderboy 3..).\r\n  - Started working on virtual machine. This required a MAJOR code overhaul,\r\n    which means lot of work. It was also one of the last things required to\r\n    be able to implement the \"Load ROM\" option, so stop requesting it :-)\r\n  - Fixed patching system (no more crashes).\r\n  - Fixed a graphic bug in \"F16 Fighters\" and \"F16 Fighting Falcon\".\r\n  - Finally managed to find the \"magic\" IPeriod value (200) and added an\r\n    option to choose a different value when it is stored in the rom database.\r\n    This change also improve speed ! The following games are fixed:\r\n      - Altered Beast (SMS)\r\n      - Barcelona '92 (SMS) - still has bug (bad dump?)\r\n      - Monaco Grand Prix (SMS)\r\n      - NBA Action (GG)\r\n      - Shadow of the Beast (SMS)\r\n      - WWF Steel Cage Challenge (SMS)\r\n  - Fixed Mortal Kombat 2 (GG).\r\n  - Changed a few things in the Game Gear interrupt system.\r\n  - Various code changes, related to Jason Nelson's Windows port.\r\n  - Fixed a bug so that \"gui_access_mode = flipped\" should not crashes\r\n    anyway (but there is still a lot of flickers, and it is slower than\r\n    the \"direct\" mode - although faster than \"buffered\").\r\n  - Master System games marked with \"Ok, No Voices\" are not counted anymore\r\n    as non-working. And hopefully Hiro-shi will get voices to work soon :)\r\n  - Added support for pending interrupts, although I didn't noticed any\r\n    changes in any games.\r\n  - Various GUI code improvments.\r\n  - Various optimizations.\r\n  - Improved theme system, added a new color, improved existing themes.\r\n    Added a new \"Emucamp\" theme (by Puyolin) and removed the \"Peach\" theme,\r\n    as it really really sucked (and I doubt anyone was using it).\r\n  - Added a VSync option in the configuration file (for fast PC).\r\n  - Fixed screenshot size when Eagle is enabled.\r\n  - Improved TV effect.\r\n\r\n\r\n MEKA 0.0.39 [private]       Emulation: 87%     Speed: 50%     Features: 51%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various bugs fixed, mainly related to the new sound engine.\r\n  - Wrote documentation, and moved the history section to a separate file.\r\n  - Improved error handling.\r\n  - Added support for video mode 0 used in Sega Basic and Music Editor.\r\n  - Added support for additionnal RAM used in Sega Basic and Music Editor.\r\n  - Fixed savegames, as there was a paging problem with some games (such as\r\n    Gunstar Heroes or Alex Kidd BMX Trial).\r\n  - Added a very cool ROM patching system. Check the file MEKA.PAT.\r\n  - Added dynamic CPU handlers changes, so I can assign a different (faster)\r\n    memory handler in SC-3000 mode, for exemple.\r\n  - Started interfacing for the Master System BIOS. Check machine->power->on.\r\n  - Various GUI fixes and improvments:\r\n     - Fixed some menus names.\r\n     - Improved the theme system, improved existing themes and added a new\r\n       one by Puyolin : Ocean.\r\n     - Optimized pop-up menus refresh and rounded corners.\r\n     - Reduced flicker a bit in the direct GUI access mode (see MEKA.CFG).\r\n  - Fixed and completed keyboard mapping. Key are mapped *at the same place*\r\n    as the SC3000 keyboard, so you can simply look at the provied picture to\r\n    find which key to press. For exemple:\r\n      * Eng Dier's = Left Alt\r\n      * Home/Clear = Right Alt\r\n      * Control    = Caps Lock\r\n      * Graph      = Left Control\r\n    The only exception is the \"üE key, which is mapped on the tilde, as there\r\n    is not enough room on the PC keyboard to put it at the left.\r\n    Ins/Del is mapped to Right Control, but also to Backspace as this key is\r\n    unused and is the more regular way to delete characters ;-)\r\n  - Improved configuration files parsing.\r\n  - Rewrote the function to blit the image in fullscreen mode. As a result:\r\n      - Scanlines are now working. Press ALT-S to enable/disable them.\r\n      - The crap 3-D parallel view can be combined with scanlines (ALT-3).\r\n      - The eagle graphics filter now work in fullscreen mode, and can\r\n        be enabled/disabled while running the emulator (with ALT-E).\r\n      - Removed all effects (Eagle, 3-D, Scanlines) under the interface. It\r\n        caused too much trouble. Maybe I will put them back later.\r\n  - Added a better messaging / error handling system (based on Raine code).\r\n  - Added more Master System games to the compatibility and checksum lists.\r\n  - Fixed screenshot size and now the filename is based on the rom name.\r\n  - Some minor optimizations.\r\n\r\n\r\n MEKA 0.0.38 [private]       Emulation: 87%     Speed: 49%     Features: 50%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Hiromitsu Shioya has joigned the team and contributed with a very good\r\n    sound engine, featuring *FM emulation* ! MEKA doesn't use Adlib / OPL\r\n    anymore as the waves are generated, and it sounds much better. Please\r\n    note that as of version 0.0.38, the sound engine is still in development\r\n    and FM emulation has some bugs and missing features. It will be improved\r\n    and should be perfect in the next version.\r\n  - Added preliminary Gear-to-Gear communication port emulation. Just enough\r\n    to allow \"Star Gate\" to run.\r\n  - Fixed and improved keyboard emulation. Also added a shortcut (ALT-F9).\r\n  - Added a buggy scanline option, until I found a better way to do it.\r\n  - Various GUI fixes and improvments, included but not limited to:\r\n     - Major pop-up menus re-organization.\r\n     - Now pop-up menus uses gradients.\r\n     - Added a nice background - to be used in the future.\r\n     - Support for windows title wrapping (when the text doesn't fit).\r\n     - Fixed a bug with the tile viewer, and slighty optimized it.\r\n  - Fixed a major graphic bug introduced in previous version (Gauntlet, Great\r\n    Basketball, Solomon Key and a few other games).\r\n  - Changed default IPeriod (again!) to 226, to fix Shadow of the Beast.\r\n  - Finally succeeded in implementing Marcel De Kogel Z80 Core. The problem\r\n    is that Mortal Kombat 1 and 2 hang with it, so it is not yet included.\r\n  - Fixed sprites clipping bug in SG1000 mode (Congo Bongo..).\r\n  - Improved checksum file structure, allowing for custom fields.\r\n    Started completing the \"ID\" field with all ID values. Please help !\r\n  - Added a bunch of new Master System games to the compatibility list, with\r\n    their checksum, and some new Game Gear games.\r\n  - Fixed MSM recording.\r\n  - Improved documentation.\r\n\r\n\r\n MEKA 0.0.37 [private]       Emulation: 88%     Speed: 49%     Features: 47%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed graphics bugs in the following games:\r\n     - Rainbow Island (no more black screen)\r\n     - Gangster Town (minor interrupt bug)\r\n     - Sonic Drift 2 (it is playable, but there is still some glitchs)\r\n  - Fixed sprites priorities. The bug was introduced in version 0.0.28, but\r\n    I didn't bothered fixing it until now :)\r\n  - Support for zoomed sprites (used in X-Men title screen).\r\n  - Fixed a pause bug in Wonderboy 2 / Monica.\r\n  - Fixed a file parsing bug when loading a file with more than one comma.\r\n  - Now using Eagle version 0.41 (should be slighty faster).\r\n  - Rewrote and improved Makefile (for developers).\r\n\r\n\r\n MEKA 0.0.36 [private]       Emulation: 88%     Speed: 49%     Features: 46%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n * Perfect compatibility rate in Game Gear mode is now of 85% !\r\n   (not counting voice emulation, used by many games)\r\n\r\n  - Slighty optimized emulation.\r\n  - Implemented SC3000 keyboard emulation (used in Tanoshii Sansuu and Uranai\r\n    Angel). It tooks me more time to draw the keyboard than to emulate it :)\r\n    Use popup menus to enable it. A keyboard will appears on the background.\r\n    To use it, you'll have to press the corresponding keys directly on your\r\n    keyboard. You cannot click on the keys with the mouse yet. Also, you MUST\r\n    change the value for the \"key_pause\" in the configuration file to zero or\r\n    something else to be able to use the enter key. To be fixed.\r\n  - Reformated the compatibility list, and Mxs started adding GG titles.\r\n  - Fixed a bug in various Game Gear games (GP Rider, Joe Montana, Lemmings).\r\n  - Fixed a major interrupt bug in betas between 35 and 36.\r\n  - Fixed a SG1000 graphic bug in betas between 35 and 36 (James Bond 007..).\r\n  - Fixed a memory paging bug in Columns (Game Gear).\r\n  - Fixed a crashing bug with the tile viewer bug SG1000/SC3000 mode when the\r\n    game used the end of the VRAM as the tile area.\r\n  - Now default IPeriod is now set to 227. Be sure to delete your old config\r\n    file or update it manually if you want to use the new value.\r\n  - Fixed a dynamic palette bug. Unfortunaly the fix slow down emulation, but\r\n    I must keep it until I found a better way.\r\n  - FM chipset can now be enabled and autodetected. It is disabled by default\r\n    because nothing is emulated yet. Check the configuration file.\r\n  - Border color is now always black (finally).\r\n  - Added a command line help and improved parsing.\r\n  - Memory is now properly released at the end of the program.\r\n  - Fixed a crashing bug introduced in previous version when loading very\r\n    large roms (such as Street Fighter 2').\r\n  - Separated even more object files, for a faster compilation.\r\n\r\n\r\n MEKA 0.0.35 [private]       Emulation: 88%     Speed: 49%     Features: 45%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n\r\n * Perfect compatibility rate in Master System mode is 85%.\r\n   Voice emulation is still missing, and 18 games (9%) are using it.\r\n   Also, three games are buggy because of a CPU bug.\r\n\r\n * Perfect compatibility rate in SG1000 mode is now of 97% !\r\n   There very minor bugs in only two games: Pitfall 2 and Rockn' Bolt.\r\n\r\n  - Added support for a new video mode used in the following SG1000 games:\r\n     - Champion Baseball\r\n     - Champion Golf (both versions)\r\n     - James Bond 007\r\n     - Pop Flamer\r\n  - Fixed a sprite bug in the following SG1000 games:\r\n     - Border Line\r\n     - Yamato\r\n  - Added support for sprite shifting, as used in Ghouls'n Ghosts.\r\n  - Better SG1000/SC3000 mode autodetection.\r\n  - Started working on sound emulation (nothing is included yet).\r\n  - Screen refresh is now slighty faster.\r\n  - Rewrote and optimized message applet.\r\n  - Improved command line parsing.\r\n  - Added a cool ANSI when quitting.\r\n  - Slighty improved color theme.\r\n  - Improved the configuration file.. hehe :)\r\n  - Reduced executable size thanks to the UPX compressor (better than DJP).\r\n\r\n\r\n MEKA 0.0.34 [private]       Emulation: 85%     Speed: 48%     Features: 44%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Improved VDP emulation, fixing graphic bugs in the following games:\r\n      - Astro Warrior (SMS)\r\n      - Astro Warrior / Pit Pot (SMS)\r\n      - Championship Hockey (SMS)\r\n      - Klax (SMS)\r\n      - Surfs Ninja (GG)\r\n      - Wolfchild (SMS)\r\n      - Yamato (SG1000)\r\n      - and probably other on Game Gear (I was too lazy to test them)\r\n  - Fixed a sprite bug in the following games:\r\n      - Golvellius (SMS) - I already fixed it but accidentally re-broke it\r\n      - Gulkave (SG1000)\r\n  - Changed default IPERIOD to 221 to fix the following games:\r\n      - Safari Race (SG1000)\r\n      - Zippy Race (SG1000)\r\n    Be sure to tell me if another game is now broken.\r\n  - Fixed the bug which prevented top lines to refresh.\r\n  - Fixed a potential sprite collision bug in SG1000 mode.\r\n  - Fixed a bug when SaveRAM was corrupted before being saved.\r\n  - Fixed a bug with the tile viewer.\r\n  - Fixed a bug when creating a game box after enabling 3D Glasses.\r\n  - Improved error handling (eg: when the datafile is missing).\r\n\r\n\r\n MEKA 0.0.33 [private]       Emulation: 83%     Speed: 48%     Features: 43%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non-emulation bugs fixed.\r\n  - Fixed a silly input bug introduced in previous version.\r\n  - Fixed country switch when hard reseting.\r\n  - Fixed checksum calculation when an end header is found (rare, only in\r\n    the very first roms dumped) and updated the database when necessary.\r\n  - Various GUI improvements. Although visible changes are minors, most of\r\n    the code was entirely rewritten, to allow widget integration and a more\r\n    flexible interface. The mouse code was also rewritten.\r\n  - Added the first widgets:\r\n     - Little stars at the top-right of boxes, used to close them.\r\n     - An invisible one to change the palette used in the tile viewer when\r\n       pressing the second mouse button on it.\r\n  - Added a /NIRV parameter to speed up emulation dramatically. To use when\r\n    benchmarking only :-)\r\n\r\n\r\n MEKA 0.0.32 [private]       Emulation: 83%     Speed: 48%     Features: 42%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non-emulation bugs fixed.\r\n  - Renamed emulator to MEKA and started writing the documentation.\r\n  - I ported the emulator to Linux in ONE HOUR !! Ok, it's is still a bit\r\n    slow and buggy, but I cannot believe it myself - Linux rocks :)\r\n    Hopefully it will be as good as the DOS version soon.\r\n  - Rewrote memory accesses. Emulation is now slighty faster and I finally\r\n    fixed SaveRAM emulation ! The following games do not have graphics\r\n    problems anymore: Flash, Phantasy Star (the three versions) and Y's.\r\n    Shining Force 2 and 3 (Game Gear).\r\n  - Fixed a bug to make Street Fighter 2' working.\r\n  - Implemented parallel 3D Glasses simulation (press [ALT]-[3] to use it).\r\n    Please note that the sides are inversed in some games, because there is\r\n    no sure way to differenciate the left from the right.\r\n  - Fixed a minor IO bug (Wonderboy 5).\r\n  - In SG1000/SC3000 mode:\r\n     - Fixed minor sprite bug (top of the screen in Girl's Garden).\r\n     - Fixed various bugs in VDP emulation (Champion Tennis, Hyper Sport,\r\n       Sega Galaga).\r\n     - Slighty optimized screen refresh.\r\n  - Fixed various savegames bugs, and switched to a better format (SRAM is\r\n    now saved if necessary, as well as full Game Gear palette).\r\n  - Updated to Marat's latest Z80 core, which count cycles.\r\n  - Added a switch in configuration file to disable the TV effect.\r\n\r\n\r\n ZSms 0.0.31 [private]       Emulation: 79%     Speed: 48%     Features: 41%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non-emulation bugs fixed.\r\n  - Fixed a palette problem that was introduced in previous version, and\r\n    affected a few games (Gauntlet, Klax, Indiana Jones..).\r\n  - Fixed country in Game Gear emulation. Use \"/jap\" to switch to japanese\r\n    mode, then check the differences in Street of Rage 2 / Bare Knuckles 2\r\n    or in Power Strike 2 / Aleste 2.\r\n  - In SG1000/SC3000 mode:\r\n     - VDP Register 7 is now used to replace background color 0 when needed.\r\n       It fixes the color bugs in many games (eg: Champion Soccer, Dragon\r\n       Wang, Flicky, Pacar, Sega Flipper, Yamato..).\r\n     - Fixed a bug in sprite engine (top of the screen in Champion Boxing,\r\n       Girl's Garden, Orguss, Pitfall 2 and Wonderboy).\r\n     - Fixed general bugs in VDP (sprites in Exerion, background in Yamato).\r\n     - Inverted the two availables palette. The second one, which looks\r\n       better, is now used by default.\r\n  - Due to numerous requests, I finally added joypad/joystick support !\r\n    It was not much tested, so feedback is highly needed. Be sure to tell\r\n    me if it's working for you.\r\n  - Added non working GUI page flipping access mode.\r\n    Set \"gui_access_mode\" to \"flipped\" in the configuration file to see your\r\n    machine crashing :)\r\n  - Started interfacing for Marcel de Kogel's CPU core.\r\n  - More cleans in the source code. Graphic hardware emulation part is now\r\n    separated from the main object file, for a faster compilation.\r\n\r\n\r\n ZSms 0.0.30 [private]       Emulation: 78%     Speed: 47%     Features: 41%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non-emulation bugs fixed.\r\n  - Cleaned source code, renamed tons of variables.\r\n  - Added support for dynamic palette effects in Master System and Game Gear\r\n    mode (the one in Massage sucks in Game Gear mode :)\r\n    It fixes the color blink bug in the following Master System games:\r\n      - California Games (various events)\r\n      - Championship Hockey (configuration screen)\r\n      - Gangsters Town (road scene) (still problems)\r\n      - Golden Axe Warrior (title screen)\r\n      - Poseidon Wars 3D (title screen)\r\n      - Space Harrier (game)\r\n      - Space Harrier 3D (game)\r\n    and in the following Game Gear games:\r\n      - Gunstar Heroes (level 1)\r\n      - Space Harrier (game) (still problems)\r\n      - Power Strike 2 (title screen) (still problems)\r\n      - probably a few others. I'm not testing much Game Gear games..\r\n    Please note that it's not perfect at all, and you will still notice bugs\r\n    in these games. But *PLEASE* contact me if you notice color related bugs\r\n    in others games (all the one which do not use color effects), because I\r\n    did rewrote the whole palette code and it may contains some bugs.\r\n  - In Game Gear mode:\r\n      - Fixed game window size.\r\n      - Reset key is now mapped to hard reset (because no soft reset).\r\n      - Eagle is now separately activated for each systems, so you can\r\n        enable it only for Game Gear mode (which is a good idea).\r\n  - More accurate manual and automatic frame skipping.\r\n  - Rewrote the checksum code and updated the database. Sapo Xule is not\r\n    recognized anymore as Psycho Fox. Same thing with Phantasy Star US/Port.\r\n  - IPeriod can now be changed from the configuration file.\r\n  - Improved Bloodlust theme :)\r\n\r\n\r\n ZSms 0.0.29 [private]       Emulation: 78%     Speed: 47%     Features: 40%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various non-emulation bugs fixed.\r\n  - Added hard reset feature (available from GUI menus).\r\n  - The pause key is now handled a slighty different way. It fixes the bug\r\n    in Wonderboy 2 / Monica, and probably in other games.\r\n  - Fixed screenshot size in Game Gear mode.\r\n  - Fixed graphic problem with Lightgun's cursor in Fullscreen mode.\r\n  - Changed the following things in GUI:\r\n     - Added technical informations applet.\r\n     - Reorganized pop-up menus, no more testing things.\r\n     - Now applets can be enabled/disabled by pressing ALT+[key], where [key]\r\n       is [P] for Palette, [T] for the Tiles viewer, [I] for the technical\r\n       Informations box and [M] for the Messages box.\r\n     - Fixed Tiles Viewer in Master System mode.\r\n     - Improved Bloodlust theme :)\r\n  - Changed the following things in SG1000/SC3000 mode:\r\n     - Fixed sprites clipping.\r\n     - Fixed screen disabling (Girl's Garden, Gulkave).\r\n     - Slighty optimized emulation.\r\n     - Implemented a second predefined palette (see configuration file).\r\n     - The reset key is now mapped to hard reset (because no soft reset).\r\n  - Kevin corrected tons of english mistakes in the documentation.\r\n  - Added a Master System cartridge icon (ZSMS.ICO). Paint Shop Pro rules :)\r\n\r\n\r\n ZSms 0.0.28 [private]       Emulation: 78%     Speed: 46%     Features: 38%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n NOTE: !! Sprites Priorities in SMS/GG mode are screwed in this version !!\r\n\r\n  - Various non-emulation bugs fixed.\r\n  - Optimized SMS/GG screen refresh (a little).\r\n  - Optimized SG1000 screen refresh (a lot).\r\n  - Fixed various video bugs in SG1000 emulation, the following games\r\n    are now working: C!So, Champion Billiard, F16 Fighters and Rockn'Bolt.\r\n  - Implemented a non-buffered GUI mode. It's much faster (+15/20 FPS on\r\n    my machine), but expect tons of flickering and flashs when using it.\r\n    Set \"gui_buffered\" to 0 in the configuration file to use this mode.\r\n  - Now FPS counter work when auto frame skipping was disabled.\r\n    Also added a key (F) to show current FPS in fullscreen mode.\r\n  - Optimized tile viewer, and fixed it in SG1000/SC3000 mode.\r\n  - Now compiled by GCC 2.8 with 7 passes and Pentium instructions enabled.\r\n\r\n\r\n ZSms 0.0.27 [private]       Emulation: 78%     Speed: 45%     Features: 37%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added Game Gear support.\r\n  - Optimized new graphic engine - it's now faster than the old one.\r\n  - Fixed horizontal tile clipping bug in new graphic engine.\r\n  - SG1000 emulation is back, and was slighty optimized.\r\n  - Implemented a MSM recording feature. MSM, for \"Master System Music\", is\r\n    a text based format, so you can easily rip part of the music, or even\r\n    create your own using the Master System sound hardware (which rocks :)\r\n    The text based replayer (MSMP.EXE) is available on request.\r\n  - Finally fixed the f*cking color bug which affected snapshots and fades.\r\n    It looks like an Allegro's bug. Thanks to R. Mitton for finding it.\r\n  - Fixed bugs in Battle Out Run, Sagaia, and Impossible Mission.\r\n  - Implemented a quick hack to make voices sound slighty better. Contact\r\n    me if you have any problems with musics/sounds in this version.\r\n  - Implemented a \"/NOSOUND\" command line switch.\r\n  - Cleaned the source code.\r\n\r\n\r\n ZSms 0.0.26 [private]       Emulation: 78%     Speed: 40%     Features: 36%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - ZSMS now features a real line-per-line engine !\r\n\r\n    Pros:\r\n     -> Coolspot, Global Gladiator, Speedball 2 and Xenon 2 now shows all\r\n        the sprites. You'll notice flickering sometimes, but I cannot do much\r\n        since there is the same problem even on the real machine..\r\n     -> Outrun and Fantasy Zone 2 do not have priority bugs anymore\r\n     -> You can see sprites in Bart versus Space Mutants\r\n     -> Y's is now almost perfect\r\n     -> Psycho Fox now has the black line effect when pausing and un-pausing\r\n     -> The same kind of effect is noticeable in Quartet title screen\r\n\r\n    Cons:\r\n     -> It's 18% slower. But I'll optimize it later.\r\n     -> There are bugs on screen borders when scrolling. To be fixed.\r\n     -> It crashes sometimes. To be fixed.\r\n     -> SG1000 games are using an old engine, and the screen tries to\r\n         redraw itself 11000 times per second.. so it's a bit slow :)\r\n\r\n    The old engine was now dropped, and now I'll work on improving the new\r\n    one to make it faster and faster (I didn't really tried to optimize the\r\n    old one because I knew that I needed to switch to a new engine first).\r\n\r\n  - Cleaned the source code and renamed tons of variables.\r\n  - Various GUI improvements and fixes to make Nirv even more happy :)\r\n  - Fixed a few things with the savegame format (still not the final one).\r\n  - Replaced tiles decoding by a slighty faster code, provided by D.Michel.\r\n\r\n\r\n ZSms 0.0.25 [private]       Emulation: 85%     Speed: 41%     Features: 35%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Slighty optimized emulation.\r\n  - Various GUI improvements to make Nirv happy.\r\n  - Fixed tons of warnings and potential bugs in the code.\r\n  - Finally fixed the nasty bug which freezed everything at the beginning !\r\n  - The auto frame skipper is bugged ! If you experience problems such as\r\n    slowdowns or temporary freezes, try disabling it.\r\n\r\n\r\n ZSms 0.0.24 [private]       Emulation: 85%     Speed: 40%     Features: 34%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various GUI improvements.\r\n  - Added voice recognition, using standard microphone input :)\r\n  - Optimized GUI - now up to 100% faster !\r\n\r\n\r\n ZSms 0.0.23 [private]       Emulation: 85%     Speed: 38%     Features: 33%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various bugs fixed.\r\n  - Now ZSms doesn't crash anymore when run from another directory.\r\n  - Added an unique checksum feature. Coupled with a list of all released\r\n    Master System roms, ZSms can find (and use) the name of a game by itself.\r\n  - Various GUI improvements.\r\n\r\n\r\n ZSms 0.0.22 [private]       Emulation: 85%     Speed: 38%     Features: 32%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed graphic bug in Golvellius.\r\n  - Fixed various bugs in SG-1000 emulation.\r\n  - Optimized tile decoding (thanks to Tuo !).\r\n  - Various non-emulation bug fixes and updates.\r\n  - Now build date and time are saved into the executable.\r\n\r\n\r\n ZSms 0.0.21 [private]       Emulation: 84%     Speed: 37%     Features: 32%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Rewrote input code, and added support for Paddles / Steering Wheel,\r\n    used in \"Alex Kidd BMX Trial\".\r\n  - Now pop-up menus support a \"checked\" attribute.\r\n  - Switched to a new savegame format, which is *working* and is *smaller*\r\n    Not the final version of the format, though.\r\n  - No more colors problems in SG-1000 games.\r\n  - Background is now correctly displayed in SG-1000 games.\r\n  - Support for magnified sprites in SG-1000 games.\r\n\r\n\r\n ZSms 0.0.20 [private]       Emulation: 82%     Speed: 37%     Features: 31%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - 99% completed menus code. Still not much to see, but \"QUIT\" works.\r\n    There is a small bug left, causing some entries to be highlighted..\r\n  - Sprites are now displayed in the strange video mode used by Hang On 2\r\n    and Girl's Garden, not with good colors, though.\r\n  - Support for two lightguns (Gangster Town). Press [SPACE] when lightgun\r\n    emulation is activated to switch between them.\r\n  - Reduced savegame size - I will switch to a permanent format asap.\r\n\r\n\r\n ZSms 0.0.19 [private]       Emulation: 80%     Speed: 37%     Features: 30%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Rewrote memory accesses - slighty faster.\r\n  - Added working *and precise* lightgun emulation (thanks to J.McKay !)\r\n  - Added SRAM emulation (Phantasy Star, Golden Axe Warrior..).\r\n  - Updated compatibility list.\r\n\r\n\r\n ZSms 0.0.18 [private]       Emulation: 70%     Speed: 36%     Features: 30%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various bugs fixed.\r\n  - Now almost perfect raster effects - more games are working perfectly !\r\n  - Added Eagle support. Add \"eagle=1\" in the config file to enable it.\r\n  - Completely rewrote menus code. Now about 90% is done and it's clean :)\r\n  - Savegames and captures are now saved in a separate directory.\r\n  - Updated compatibility list.\r\n\r\n\r\n ZSms 0.0.17 [private]       Emulation: 63%     Speed: 36%     Features: 27%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Various fixes.\r\n  - Continued working on pop-up menus (although there is not much to see,\r\n    about 50% of the work was already completed).\r\n  - Implemented configuration file, using a cool and tolerant parser.\r\n  - Added non working lightgun emulation (press [F9] to \"activate\" it).\r\n  - Optimized screen refresh.\r\n\r\n\r\n ZSms 0.0.16 [private]       Emulation: 61%     Speed: 35%     Features: 25%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Optimized screen refresh in GUI.\r\n  - Added preliminary non working pop-up menus.\r\n  - Major clean up of the GUI code, also cleaned up some others things.\r\n  - Support for bit 7 of VDP register 0 (Gauntlet, Golvellius ..).\r\n  - Non-players keys do not stop the system when pressed anymore.\r\n  - Splitted the program in separated objects files for a faster compilation.\r\n\r\n\r\n ZSms 0.0.15 [private]       Emulation: 60%     Speed: 33%     Features: 23%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed top sprite clipping.\r\n  - Slighty faster screen refresh.\r\n  - Better rasters support (but still bugged).\r\n  - Fixed border color (now it's always black, so no flickering).\r\n\r\n\r\n ZSms 0.0.14 [private]       Emulation: 50%     Speed: 32%     Features: 23%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added preliminary rasters support ! (still fully bugged)\r\n  - Added auto frame skipper and frame per second counter in GUI. Press\r\n    [F4] to activate it (thanks to Archeide for his code).\r\n  - Fixed a crashing bug when loading non compatible snapshots.\r\n  - Slighty optimized user interface. But it's still very slow :(\r\n\r\n\r\n ZSms 0.0.13 [private]       Emulation: 45%     Speed: 31%     Features: 21%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added support for player 2 inputs and [RESET] button.\r\n  - Support for bit 3 of background/foreground attributes (finally !).\r\n  - Emulated CPU speed is now set to 3.3 mhz, instead of 3 mhz.\r\n  - Now uses VESA for fullscreen mode (if available).\r\n  - Added a compatibility list.\r\n  - Fixed border color.\r\n\r\n\r\n ZSms 0.0.12 [private]       Emulation: 40%     Speed: 31%     Features: 20%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Added status bar and status messages.\r\n  - Fixed windows moving code and multitasking code.\r\n  - Various bug fixed in the graphical user interface.\r\n  - Optimized the tiles viewer applet.\r\n\r\n\r\n ZSms 0.0.11 [private]       Emulation: 40%     Speed: 30%     Features: 17%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Optimized screen refresh & memory accesses (this version is about\r\n    three times faster !). Now runs at full speed on my p120.\r\n  - Fixed scrolling clipping in graphical user interface.\r\n  - Added a tiles viewer applet (it seems that the SMS has 512 tiles!)\r\n  - Added frameskip hotkeys (F1: 1/1, F2: 1/2, F3: 1/3, F4: 1/4).\r\n    Frameskip values are different between fullscreen mode and GUI mode.\r\n    Default values are: FullScreen: 1/2, GUI: 1/3.\r\n  - Now applets can be enabled/disabled by pressing their specific hotkeys\r\n    (C: Clock, P: Palette, T: Tiles Viewer).\r\n  - Rewrote some parts of the GUI/applets code.\r\n\r\n ZSms 0.0.10 [private]       Emulation: 40%     Speed: 25%     Features: 15%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed some bugs. Now the program *should* work on all computers.\r\n  - Better command line parsing.\r\n\r\n\r\n ZSms 0.0.09 [private]       Emulation: 40%     Speed: 25%     Features: 15%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Now perfect scrollings.\r\n  - Support for VDP register 0 bit 5.\r\n  - Better synchronisation (now Golden Axe Warrior is playable).\r\n\r\n\r\n ZSms 0.0.08 [private]       Emulation: 35%     Speed: 25%     Features: 15%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Improved graphical user interface code.\r\n  - Added a totally useless feature: multiscreens.\r\n  - Keys are no more hardcoded. Adding a configuration file soon.\r\n\r\n\r\n ZSms 0.0.07 [private]       Emulation: 35%     Speed: 25%     Features: 12%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Support background and foreground transparency.\r\n  - Better scrollings.\r\n  - Re-organized the source code.\r\n\r\n\r\n ZSms 0.0.06 [private]       Emulation: 30%     Speed: 25%     Features: 12%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Support for VDP register 0 bit 6 (two non scrolling chars at the top\r\n    of the screen, used in most scrolling games).\r\n  - Better synchronisation, so more games (Sonic..) are working !\r\n  - Added game snapshot features (0-9: CHOOSE, F5: SAVE, F7: LOAD).\r\n  - Some other fixes.\r\n\r\n\r\n ZSms 0.0.05 [private]       Emulation: 25%     Speed: 25%     Features: 11%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Now all 512 kb games work ! Whooooo.. Phantasy Star rocks! :)\r\n  - Better synchronization. Now all games are fast enough on my p120.\r\n  - Fixed problems with the GUI which caused the emulator to crash.\r\n  - Now creates snapshot called ZSMS_xxx.PCX (find the first available one).\r\n  - Added nationalization support. Default is english, use \"/jap\" to use\r\n    japanese. Required with certains games (Wonderboy 3..).\r\n\r\n ZSms 0.0.04 [private]       Emulation: 21%     Speed: 20%     Features: 10%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Fixed palette when screen is not updated (VDP register 1, bit 6).\r\n  - Now almost all games display correct sprites (VDP register 6, bit 2).\r\n\r\n\r\n ZSms 0.0.03 [private]       Emulation: 21%     Speed: 20%     Features: 10%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - A few bugs fixed.\r\n  - Better synchronisation: now almost all games work (still sprites pbs).\r\n  - A lot faster than previous version.\r\n\r\n\r\n ZSms 0.0.02 [private]       Emulation: 10%     Speed: 10%     Features: 10%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Vertical and Horizontal fully-bugged scrolling support.\r\n  - 8x16 tiles support (Double Dragon, Rescue Mission..).\r\n  - VDP Register 1 bit 6 support.\r\n  - Fixed sprites priorities.\r\n  - Slighty optimized emulation.\r\n\r\n\r\n ZSms 0.0.01 [private]       Emulation: 05%     Speed: 05%     Features: 10%\r\n───────────────────────────────────────────────────────────── ───- ──- ─- -\r\n  - Initial \"release\".\r\n"
  },
  {
    "path": "meka/meka.blt",
    "content": ";-----------------------------------------------------------------------------\r\n; MEKA - Video Configuration\r\n; http://www.smspower.org/meka\r\n;-----------------------------------------------------------------------------\r\n; To create your own themes, the easiest way is to use Maxim's MEKA configurator:\r\n;    http://www.smspower.org/maxim/mconfig/\r\n; Otherwise, you can manually edit this file, using the syntax described below.\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Syntax:\r\n;\r\n;   [name]\r\n;   res = XRESOLUTIONxYRESOLUTION\r\n;   blitter = normal | tvmode | tvmode_double | hq2x\r\n;\r\n; The configuration name must be postfixed by a mark of the appliable operating system:\r\n;   ::WIN   for the Windows version of MEKA.\r\n;   ::UNIX  for the UNIX version of MEKA.\r\n;\r\n; Optional settings:\r\n;   refresh_rate = auto | 60 | 70 | ... (video refresh rate - prefer 60 Hz)\r\n;   stretch                             (enable fullscreen stretch)\r\n;\r\n; Available video modes depends on your video card. Some modes you may\r\n; want to try are 256x192, 256x240, 320x200 and 512x384.\r\n;\r\n; ADVICE\r\n; A great setting in most cases is to setting refresh_rate to 60,\r\n; enable vsync and disable the autoframeskipper in MEKA. This way,\r\n; emulation will be perfectly synchronized to 60 Hz.\r\n; Not all video card / drivers support setting a refresh rate other\r\n; than the default one, however.\r\n;\r\n; Blitters description:\r\n;  \"normal\"         default blitter\r\n;  \"tvmode\"         simulates TV scanlines, a bit slower but very nice\r\n;                   looking. lines are vertically doubled so you need a\r\n;                   suitable resolution (eg: 320x400).\r\n;  \"tvmode_double\"  simulates TV scanlines and double the size of each\r\n;                   pixels both horizontally and vertically.\r\n;  \"hq2x\"           apply HQ2X filtering (requires a *2 resolution)\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; WINDOWS - Default Modes\r\n;-----------------------------------------------------------------------------\r\n\r\n[Default::WIN]\r\nres = 768x576\r\n;res = 1024x768\r\nblitter = normal\r\nstretch\r\n\r\n;[Normal::WIN]\r\n;res = 320x200\r\n;refresh_rate = auto\r\n\r\n;[PAL Screen::WIN]\r\n;res = 320x240\r\n;refresh_rate = auto ; 50\r\n\r\n;[TV Mode::WIN]\r\n;res = 640x480\r\n;blitter = tvmode_double\r\n;;refresh_rate = 60\r\n\r\n;[HQ2X::WIN]\r\n;res = 1024x768\r\n;refresh_rate = 60\r\n;blitter = hq2x\r\n;stretch\r\n\r\n;[Eagle::WIN]\r\n;res = 1024x768\r\n;refresh_rate = 60\r\n;blitter = eagle\r\n;stretch\r\n\r\n;-----------------------------------------------------------------------------\r\n; UNIX - Default Modes\r\n;-----------------------------------------------------------------------------\r\n\r\n[Default::UNIX]\r\nres = 768x576\r\n;res = 1024x768\r\nblitter = normal\r\nstretch\r\n\r\n;-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/meka.inp",
    "content": ";-----------------------------------------------------------------------------\r\n; MEKA 0.80-alpha - Inputs Configuration\r\n; This file is automatically updated and rewritten when quitting\r\n; Feel free to edit this file manually if you feel the need to.\r\n; However, any comment you may manually add will be deleted!\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Links:\r\n; Using a SMS/DB-9 controller on your computer:\r\n;  - Read the TECH.TXT file at first!\r\n;  - SmsCardPad\r\n;    http://www.smspower.org/smscartpad/\r\n;  - PPJoy joystick driver for Windows 2000/XP\r\n;    Download mirror: http://www.zophar.net/joy/ppjoy.html\r\n;    Obsolete official website: http://web.archive.org/web/20021018045524/http://www.geocities.com/deonvdw/\r\n;  - ArcadeWereld.nl usb controller board\r\n;    http://www.smspower.org/forums/15321-SMSDB9ControllerOnPcUsingUSB\r\n; Schematics and drivers for various console controllers adapters:\r\n;  - Direct Pad Pro\r\n;    http://www.arcadecontrols.com/Mirrors/www.ziplabel.com/dpadpro/\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Miscellaneous features:\r\n;\r\n; Invert ESC (switch screens) and F10 (quit) keys. Arcade cabinet owners\r\n; often have the ESC key mapped to a certain button they want to quit with.\r\ncabinet_mode         = 0\r\n;\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Template for creating new input sources:\r\n;\r\n; [Name]\r\n; type = keyboard (digital) | joypad (digital) | mouse (analog)\r\n;   Select the type of input device\r\n; enabled = yes | no\r\n;   Set to no in order to tell MEKA to ignore input from this device\r\n; player = 1 | 2\r\n;   Player number\r\n; connection = <number>\r\n;   Joypad only. Select connection to use: 1 = first pad, 2 = second pad..\r\n; emulate_digital\r\n;   Mouse only. Enable support for digital devices (such as SMS joypad),\r\n;   to play games with the mouse. Recommended with shooters mainly.\r\n; digital_falloff (between 0 and 1, default being 0.8)\r\n;   Mouse only, when digital emulation is enabled. Reduce to increase\r\n;   precision, but most games will be harder to play.\r\n;-----------------------------------------------------------------------------\r\n\r\n[Keyboard 1]\r\ntype                = keyboard\r\nenabled             = yes\r\nplayer              = 1\r\nplayer_up           = key Up\r\nplayer_down         = key Down\r\nplayer_left         = key Left\r\nplayer_right        = key Right\r\nplayer_button1      = key Z\r\nplayer_button2      = key X\r\nplayer_start_pause  = key Space\r\nplayer_reset        = key Backspace\r\n\r\n[Keyboard 2]\r\ntype                = keyboard\r\nenabled             = yes\r\nplayer              = 2\r\nplayer_up           = key W\r\nplayer_down         = key S\r\nplayer_left         = key A\r\nplayer_right        = key D\r\nplayer_button1      = key Q\r\nplayer_button2      = key E\r\n\r\n[Joypad 1]\r\ntype                = joypad\r\nconnection          = 1\r\nenabled             = yes\r\nplayer              = 1\r\nplayer_up           = joy stick 2 axis 1 dir 0\r\nplayer_down         = joy stick 2 axis 1 dir 1\r\nplayer_left         = joy stick 2 axis 0 dir 0\r\nplayer_right        = joy stick 2 axis 0 dir 1\r\nplayer_button1      = joy_button 0\r\nplayer_button2      = joy_button 1\r\nplayer_start_pause  = joy_button 7\r\nplayer_reset        = joy_button 6\r\n\r\n[Joypad 2]\r\ntype                = joypad\r\nconnection          = 2\r\nenabled             = yes\r\nplayer              = 2\r\nplayer_up           = joy stick 0 axis 1 dir 0\r\nplayer_down         = joy stick 0 axis 1 dir 1\r\nplayer_left         = joy stick 0 axis 0 dir 0\r\nplayer_right        = joy stick 0 axis 0 dir 1\r\nplayer_button1      = joy_button 0\r\nplayer_button2      = joy_button 1\r\nplayer_start_pause  = joy_button 7\r\n\r\n[Mouse 1]\r\ntype                = mouse\r\nenabled             = yes\r\nplayer              = 1\r\nplayer_x_axis       = mouse_axis 0\r\nplayer_y_axis       = mouse_axis 1\r\nplayer_button1      = mouse_button 0\r\nplayer_button2      = mouse_button 1\r\nplayer_start_pause  = mouse_button 2\r\nemulate_digital     = no\r\ndigital_falloff     = 0.80\r\n\r\n[Mouse 2]\r\ntype                = mouse\r\nenabled             = no\r\nplayer              = 2\r\nplayer_x_axis       = mouse_axis 0\r\nplayer_y_axis       = mouse_axis 1\r\nplayer_button1      = mouse_button 0\r\nplayer_button2      = mouse_button 1\r\nemulate_digital     = no\r\ndigital_falloff     = 0.80\r\n\r\n;-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/meka.msg",
    "content": ";-----------------------------------------------------------------------------\r\n; MEKA - Text Messages / Localization\r\n; http://www.smspower.org/meka\r\n;-----------------------------------------------------------------------------\r\n; Please contact me if you have corrections to make or if\r\n; you are willing to translate messages to a new language.\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; History\r\n;----------------------------------------\t-------------------------------------\r\n; MEKA 0.73  : Updated language: Dutch\r\n;              Added:            Msg_Menu_Video_ScreenCapture\r\n;                                Msg_Menu_Video_ScreenCapture_Capture\r\n;                                Msg_Menu_Video_ScreenCapture_CaptureRepeat\r\n;                                Msg_Menu_Video_ScreenCapture_IncludeGUI\r\n;              Updated:          Msg_Options_Capture_Crop_Align\r\n;              Renamed:          Msg_Options_Capture_Automatic_Crop_Align -> Msg_Options_Capture_Crop_Align\r\n;              Removed:          Msg_Menu_Video_Screens*\r\n; MEKA 0.72  : Added:            Msg_Inputs_Config_Peripheral_Click\r\n;                                Msg_Inputs_Config_Source_Enabled\r\n;                                Msg_Inputs_Config_Source_Player\r\n;                                Msg_Inputs_Config_Source_Emulate_Joypad\r\n;                                Msg_Theme_Error_Syntax\r\n;                                Msg_Theme_Error_Attribute_Defined\r\n;                                Msg_Theme_Error_Out_of_Bound\r\n;                                Msg_Theme_Error_Theme_Missing_Data\r\n;                                Msg_Blitters_Error_Incorrect_Value\r\n;                                Msg_Menu_Tools_TilemapViewer\r\n;                                Msg_Menu_Help_Debugger\r\n;                                Msg_Options_Capture_Automatic_Crop_Align\r\n;              Renamed:          Msg_Inputs_Configuration_BoxTitle -> Msg_Inputs_Config_BoxTitle\r\n;                                Msg_Theme_Not_Enough -> Msg_Theme_Error_Not_Enough\r\n;                                Msg_Theme_Missing -> Msg_Theme_Error_Missing_Theme_Name\r\n;                                Msg_Blitters_Not_Enough -> Msg_Blitters_Error_Not_Enough\r\n;                                Msg_Blitters_Not_Found -> Msg_Blitters_Error_Not_Found\r\n;                                Msg_Blitters_Missing -> Msg_Blitters_Error_Missing\r\n;                                Msg_Blitters_Unrecognized -> Msg_Blitters_Error_Unrecognized\r\n;                                MSG_Options_NES_Activated -> MSG_Options_NES_Enable\r\n;              Removed:          Msg_Theme_Unrecognized\r\n;                                Msg_VoiceRecognition_BoxTitle\r\n;                                Msg_VoiceRecognition_Enabled\r\n;                                Msg_VoiceRecognition_Disabled\r\n;                                Msg_Menu_Sound_VoiceRecognition\r\n;              Updated:          Msg_Window_Title\r\n;                                Msg_Inputs_Joy_Init_None\r\n;                                Msg_Inputs_Joy_Init_Found\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Currently supporting:\r\n;   English\r\n;   French\r\n;   Dutch\r\n;   Spanish\r\n;   Polski\r\n;   Portuguese\r\n;   Italian\r\n;   German\r\n;   Swedish\r\n;   Danish\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; How does it work ?\r\n;\r\n; - [xxx] define a new language\r\n; - You can add messages for the same language at different places, as long\r\n;\tas they are defined after the corresponding [xxx] line.\r\n;   However, for the purpose of easing maintainance, try to stick to\r\n;   same order as the reference language (english).\r\n; - First language (english) is the default language.\r\n;   If another language is missing sentences, it will use the ones from the\r\n;\tdefault language. The default language must not be missing any sentence!\r\n; - Messages are using printf() style format markers:\r\n;\t\t%s\t:\tstring replacement\r\n;\t\t%d\t:\tinteger number replacement\r\n;\t\t%i\t:\tinteger number replacement\r\n;\tThose markers are to be kept in the same order as defined by the reference\r\n;\tEnglish text. Removing or re-ordering markers will likely lead to MEKA crashing.\r\n;\tPlease contact me if your language requires a better solution for localisation.\r\n; - ';' is the comment character in this file\r\n;   As of yet, you cannot use a ';' character in a sentence\r\n; - 'WIP' (Work In Progress) on a line will disable warnings and error\r\n;   messages for this language, if it this uncomplete. This is useful\r\n;   for when a language is missing few sentences, in a release version.\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; The messages listed below are to be given special care when translating,\r\n; because they are to fit in fixed sized regions. If they're causing problem\r\n; with your translation, the best is to keep them in english and report me\r\n; so. Later on I hope to find a solution.\r\n;-----------------------------------------------------------------------------\r\n; Msg_Options_*\r\n; Msg_FileBrowser_Load\r\n; Msg_FileBrowser_Close\r\n; Msg_FileBrowser_LoadNames\r\n; Msg_FileBrowser_ReloadDir\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[English]\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Welcome to %s (c) %s\"\r\nMsg_Window_Title                        = \"MEKA - In Pixels We Trust!\"\r\nMsg_Quit                                = \"Good night, brave warrior. Good night, monster-land....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"About Meka...\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"by %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Ok                                  = \"Ok\"\r\nMsg_Failed                              = \"Failed!\"\r\nMsg_Error_Base                          = \"Error: %s\"\r\nMsg_Error_Error                         = \"Fatal: error getting error type. Something must be wrong.\"\r\nMsg_Error_Memory                        = \"Not enough memory!\"\r\nMsg_Error_Param                         = \"Parameter \\\"%s\\\" is invalid!\\n\"\r\nMsg_Error_Syntax                        = \"Syntax error!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Unable to switch to desired video mode (%dx%d).\"\r\nMsg_Error_Video_Mode_Back_To_GUI        = \"Switching back to graphical user interface.\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"File not found!\"\r\nMsg_Error_File_Read                     = \"Unable to read from file!\"\r\nMsg_Error_File_Empty                    = \"File is empty!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"This version doesn't handle ZIP files!\"\r\nMsg_Error_ZIP_Loading                   = \"Unable to read ZIP file!\"\r\nMsg_Error_ZIP_Internal                  = \"Internal error while loading ZIP file!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Error opening directory!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Reset the game for the changes to take effect\"\r\nMsg_No_ROM                              = \"No ROM was loaded!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Initializing Allegro...\"\r\nMsg_Init_GUI                            = \"Initializing graphical user interface...\"\r\nMsg_Init_Completed                      = \"[READY]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\nMsg_Setup_Running                       = \"Running setup...\"\r\nMsg_Setup_Setup                         = \"Setup\"\r\nMsg_Setup_Video_Driver                  = \"Display driver:\"\r\nMsg_Setup_Video_DisplayMode             = \"Display mode:\"\r\nMsg_Setup_SampleRate_Select             = \"Sample rate:\"\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Screen captured to %s\"\r\nMsg_Capture_Error                       = \"Unable to create screen capture!\"\r\nMsg_Capture_Error_File                  = \"Unable to find valid filename to save screen capture!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"Loaded SaveRAM from disk (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Unable to load SaveRAM from disk\"\r\nMsg_SRAM_Wrote                          = \"Wrote SaveRAM to disk (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Unable to write SaveRAM to disk (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Resetting 93c46\"\r\nMsg_93c46_Loaded                        = \"Loaded 93c46 EEPROM data from disk (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Unable to load 93c46 EEPROM data from disk\"\r\nMsg_93c46_Wrote                         = \"Wrote 93c46 EEPROM data to disk (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Unable to write 93c46 EEPROM data to disk (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"TV Type is now %s\"\r\nMsg_TVType_Info_Speed                   = \"(Original speed is %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Loading MEKA.BLT (video modes / blitters)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Not enough blitters found! Check MEKA.BLT file or try re-installing.\"\r\nMsg_Blitters_Error_Not_Found            = \"Blitter not found!\"\r\nMsg_Blitters_Error_Missing              = \"On line %d: No blitter name defined for storing value!\"\r\nMsg_Blitters_Error_Unrecognized         = \"On line %d: Unrecognized variable!\"\r\nMsg_Blitters_Error_Incorrect_Value      = \"On line %d: Incorrect value!\"\r\nMsg_Blitters_Set                        = \"Now using \\\"%s\\\" fullscreen blitter.\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Fat plumber mode activated\"\r\nMsg_NES_Sucks                           = \"Fatal error: user likes Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Unsupported Mapper: %d. Game should not function.\"\r\nMsg_NES_Deny_Facts                      = \"You can't deny facts.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Initializing debugger... \"\r\nMsg_Debug_Welcome                       = \"Welcome to Meka Debugger!\"\r\nMsg_Debug_Not_Available                 = \"Debugger not available in this version!\"\r\nMsg_Debug_Trap_Read                     = \"At PC:%04X - Read from %04X\"\r\nMsg_Debug_Trap_Write                    = \"At PC:%04X - Write %02X to %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"At PC:%04X - Port [%02X] Read\"\r\nMsg_Debug_Trap_Port_Write               = \"At PC:%04X - Port [%02X] Write %02X\"\r\nMsg_Debug_Symbols_Loaded                = \"Loaded %d symbols from \\\"%s\\\".\"\r\nMsg_Debug_Symbols_Error                 = \"Error loading symbols from \\\"%s\\\":\"\r\nMsg_Debug_Symbols_Error_Line            = \"On line %d: unrecognized syntax.\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Data dumps will now be made in ASCII mode.\"\r\nMsg_DataDump_Mode_Raw                   = \"Data dumps will now be made in Raw mode.\"\r\nMsg_DataDump_Error                      = \"Error creating file to dump %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"No on-board memory to dump!\"\r\nMsg_DataDump_Error_Palette              = \"No palette to dump!\"\r\nMsg_DataDump_Error_Sprites              = \"No sprites to dump!\"\r\nMsg_DataDump_Main                       = \"Dumped %s (%d %s) in %s mode\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Documentation\"\r\nMsg_Doc_File_Error                      = \"Unable to open documentation!\"\r\nMsg_Doc_Enabled                         = \"Documentation showing up.\"\r\nMsg_Doc_Disabled                        = \"Documentation is no more.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite flickering will be handled automatically.\"\r\nMsg_Flickering_Yes                      = \"Sprite flickering emulation enabled.\"\r\nMsg_Flickering_No                       = \"Sprite flickering emulation disabled.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Background refresh disabled\"\r\nMsg_Layer_BG_Enabled                    = \"Background refresh enabled\"\r\nMsg_Layer_Spr_Disabled                  = \"Sprites refresh disabled\"\r\nMsg_Layer_Spr_Enabled                   = \"Sprites refresh enabled\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Unknown disk read command %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Unknown disk write command %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Disk Image is larger than expected (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Additional data will be ignored\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Disk Image is smaller than expected (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Missing data will be assumed as empty\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Palette\"\r\nMsg_Palette_Disabled                    = \"Palette viewer disabled\"\r\nMsg_Palette_Enabled                     = \"Palette viewer enabled\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Messages\"\r\nMsg_Message_Disabled                    = \"Message box disabled\"\r\nMsg_Message_Enabled                     = \"Message box enabled\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Technical Information\"\r\nMsg_TechInfo_Disabled                   = \"Technical information box disabled\"\r\nMsg_TechInfo_Enabled                    = \"Technical information box enabled\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Tiles Viewer\"\r\nMsg_TilesViewer_Disabled                = \"Tiles viewer disabled\"\r\nMsg_TilesViewer_Enabled                 = \"Tiles viewer enabled\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Memory Editor --------------------------------------------------------------\r\nMsg_MemoryEditor_BoxTitle\t\t\t\t= \"Memory Editor\"\r\nMsg_MemoryEditor_Disabled\t\t\t\t= \"Memory Editor disabled\"\r\nMsg_MemoryEditor_Enabled\t\t\t\t= \"Memory Editor enabled\"\r\nMsg_MemoryEditor_WriteZ80_Unable\t\t= \"Unable to write to Z80 address space at this moment!\"\r\nMsg_MemoryEditor_Address_Out_of_Bound\t= \"Address %s is out of %s boundaries!\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Rapid Fire activated for Player %d Button %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Rapid Fire disabled for Player %d Button %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"FM Unit (YM-2413 chipset) emulation enabled\"\r\nMsg_FM_Disabled                         = \"FM Unit (YM-2413 chipset) emulation disabled\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Emulated machine is now European/US\"\r\nMsg_Country_JAP                         = \"Emulated machine is now Japanese\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Loading MEKA.PAT (patches)... \"\r\nMsg_Patch_Missing                       = \"On line %d: No checksum defined to apply command to!\"\r\nMsg_Patch_Unrecognized                  = \"On line %d: Syntax error or unrecognized command!\"\r\nMsg_Patch_Value_Not_a_Byte              = \"On line %d: Value %s do not fit into an unsigned byte!\"\r\nMsg_Patch_Out_of_Bound                  = \"While patching %s: address $%04X is out of boundaries. Patch not applied.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"3-D Glasses emulation enabled\"\r\nMsg_Glasses_Disabled                    = \"3-D Glasses emulation disabled\"\r\nMsg_Glasses_Show_Both                   = \"3-D effect kept as is.\"\r\nMsg_Glasses_Show_Left                   = \"3-D effect disabled by showing only left side.\"\r\nMsg_Glasses_Show_Right                  = \"3-D effect disabled by showing only right side.\"\r\nMsg_Glasses_Com_Port                    = \"3-D Glasses emulation enabled through COM port %d.\"\r\nMsg_Glasses_Com_Port2                   = \"(edit MEKA.CFG to select which COM port to use)\"\r\nMsg_Glasses_Com_Port_Open_Error\t\t\t= \"Error opening COM port %d. 3-D Glasses support will not function.\"\r\nMsg_Glasses_Unsupported                 = \"This game seems not to support 3-D Glasses.\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Initializing joystick... \"\r\nMsg_Inputs_Joy_Init_None                = \"none found.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d found.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Error calibrating joystick. Aborting.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Input peripheral: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Input peripheral: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Input peripheral: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Input peripheral: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Input peripheral: Terebi Oekaki Graphic Board\"\r\nMsg_Inputs_GraphicBoardV2               = \"Input peripheral: Sega Graphic Board v2.0\"\r\nMsg_Inputs_Play_Digital                 = \"Control with digital input device\"\r\nMsg_Inputs_Play_Mouse                   = \"Control with analog input device (mouse)\"\r\nMsg_Inputs_Play_Digital_Unrecommended   = \"A digital input device (eg: keyboard) is supported but NOT recommended\"\r\nMsg_Inputs_Play_Pen                     = \"Control pen with mouse\\nRight-click simulates removing the pen from the board\"\r\nMsg_Inputs_SK1100_Enabled               = \"Sega Keyboard (SK-1100) emulation enabled\"\r\nMsg_Inputs_SK1100_Disabled              = \"Sega Keyboard (SK-1100) emulation disabled\"\r\n\r\n; Input Configuration --------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Input Configuration\"\r\nMsg_Inputs_Config_Peripheral_Click      = \"Click to select peripheral\"\r\nMsg_Inputs_Config_Source_Enabled        = \"Enabled\"\r\nMsg_Inputs_Config_Source_Player         = \"Controlling Player %d\"\r\nMsg_Inputs_Config_Source_Emulate_Joypad = \"Emulate joypad\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Loading MEKA.INP (inputs sources definition)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Not enough inputs sources found! Check MEKA.INP file or try re-installing.\"\r\nMsg_Inputs_Src_Missing                  = \"On line %d: No input source defined for storing value!\"\r\nMsg_Inputs_Src_Equal                    = \"On line %d: Missing equal sign for variable assignment!\"\r\nMsg_Inputs_Src_Unrecognized             = \"On line %d: Unrecognized variable \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"On line %d: Syntax error on variable parameter!\"\r\nMsg_Inputs_Src_Inconsistency            = \"On line %d: inconsistency with previous settings!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Now press the key you want to assign to this action\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Action assigned to key \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Now press the button/axis you want to assign to this action\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Action assigned to joypad stick %i, axis %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Action assigned to joypad button %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Now press the button you want to assign to this action\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Action assigned to mouse button %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Sorry - Mouse axis cannot be changed\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Assignment cancelled!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Machine emulation paused\"\r\nMsg_Machine_Resume                      = \"Machine emulation resumed\"\r\nMsg_Machine_Reset                       = \"Machine reset\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\nMsg_FDB_Loading                         = \"Loading MEKA.FDB (filenames database)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Loading MEKA.NAM (games names)... \"\r\nMsg_DB_Name_Default                     = \"Game Screen\"\r\nMsg_DB_Name_NoCartridge                 = \"No Cartridge\"\r\nMsg_DB_SyntaxError                      = \"On line %d: Syntax error!\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Loading %s (configuration)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Loading MEKA.DAT (resources)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatal: Unknown Machine Driver!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\nMsg_OverDump                            = \"This ROM contains %d times the necessary data.\\nPlease download SMS Checker to clean it (http://www.smspower.org/maxim/smschecker/).\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Initializing sound system...\"\r\nMsg_Sound_Init_Error_Audio              = \" - Error opening Audio system. Try a different card and/or sample rate.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER variable not found, disabling FM sound!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - BLASTER variable does not contain address (A=xxx), disabling FM sound!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Voices initialization failed.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Voice #%d creation failed.\"\r\nMsg_Sound_Init_Soundcard                = \" - Initializing sound card @ %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Can't initialize audio: no sound card selected!\"\r\nMsg_Sound_Init_SN76496                  = \" - SN76496 digital emulator:\"\r\nMsg_Sound_Init_YM2413_Digital           = \" - YM2413 digital emulator:\"\r\nMsg_Sound_Stream_Error                  = \"Sound buffer stop. Restarting stream.\"\r\nMsg_Sound_Volume_Changed                = \"Volume changed to %d%%.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Loading MEKA.THM (interface themes)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Not enough themes found! Check MEKA.THM file or try re-installing.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"On line %d: No theme name defined for storing value!\"\r\nMsg_Theme_Error_Syntax                  = \"On line %d: syntax error!\"\r\nMsg_Theme_Error_Attribute_Defined       = \"On line %d: attribute already defined!\"\r\nMsg_Theme_Error_Out_of_Bound            = \"On line %d: value out of bounds!\"\r\nMsg_Theme_Error_Theme_Missing_Data      = \"Theme \\\"%s\\\" is missing data. Will be disabled.\"\r\nMsg_Theme_Error_BG_Big                  = \"Background picture to small to fit with integer scaling!\"\r\nMsg_Theme_Error_BG                      = \"Error loading picture associated with theme!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Loading ROM... \"\r\nMsg_LoadROM_Success                     = \"Successfully loaded %s\"\r\nMsg_LoadDisk_Success                    = \"Successfully loaded %s as a floppy disk\"\r\nMsg_LoadROM_Comment                     = \"Comment: %s\"\r\nMsg_LoadROM_SMSGG_Mode_Comment          = \"This is a Game Gear ROM running in Master System compatibility mode.\"\r\nMsg_LoadROM_Warning                     = \"-Warning-\"\r\nMsg_LoadROM_Bad_Dump_Long               = \"This ROM is known as being a bad dump.\\nChances are that it will not function properly. Please download SMS Checker to check it (http://www.smspower.org/maxim/smschecker/).\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Warning - This ROM is known as being a bad dump.\"\r\nMsg_LoadROM_Product_Num                 = \"Product Number: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Header-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Name: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Version: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Date: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Author: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Release Note: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Unknown>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Error>\"\r\nMsg_LoadROM_Reload_Reloaded             = \"Loaded ROM.\"\r\nMsg_LoadROM_Reload_No_ROM               = \"No ROM to reload!\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Load ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Drive %c]\"\r\nMsg_FileBrowser_Load                    = \"Load\"\r\nMsg_FileBrowser_Close                   = \"Close\"\r\nMsg_FileBrowser_LoadNames               = \"Load Names\"\r\nMsg_FileBrowser_ReloadDir               = \"Reload Dir\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"FM Instruments Editor\"\r\nMsg_FM_Editor_Enabled                   = \"FM Instruments Editor enabled\"\r\nMsg_FM_Editor_Disabled                  = \"FM Instruments Editor disabled\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Frameskip value set to: Automatic (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Frameskip value set to: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"FPS counter enabled\"\r\nMsg_FPS_Counter_Disabled                = \"FPS counter disabled\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"LOG parameter requires a filename!\"\r\nMsg_Log_Session_Start                   = \"-- Logging session started on %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"LOAD parameter requires a savestate number!\"\r\nMsg_Load_Error                          = \"Error opening %s!\"\r\nMsg_Load_Not_Valid                      = \"File %s is not a valid %s savegame!\"\r\nMsg_Load_Success                        = \"State loaded from %s\"\r\nMsg_Load_Version                        = \"%s is an unsupported savegame version!\"\r\nMsg_Load_Wrong_System                   = \"%s is not a savegame for this system!\"\r\nMsg_Load_Massage                        = \"File is in MSD format - converting\"\r\nMsg_Save_Not_in_BIOS                    = \"Can't save while running BIOS!\"\r\nMsg_Save_Error                          = \"Error writing to %s!\"\r\nMsg_Save_Success                        = \"State saved to %s\"\r\nMsg_Save_Slot                           = \"Current savegame slot is: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Options\"\r\nMsg_Options_Close                       = \"Close\"\r\nMsg_Options_BIOS_Enable                 = \"Display BIOS logo.\"\r\nMsg_Options_DB_Display                  = \"Display names, flags and icons from database.\"\r\nMsg_Options_Product_Number              = \"Display product number from database.\"\r\nMsg_Options_Bright_Palette              = \"Enable bright palette on SMS and GG.\"\r\nMsg_Options_Allow_Opposite_Directions   = \"Allow pressing opposite joypad directions.\"\r\nMsg_Options_Load_Close                  = \"Close file browser after loading a game.\"\r\nMsg_Options_Load_FullScreen             = \"Switch to fullscreen mode after loading a game.\"\r\nMsg_Options_FullScreen_Messages         = \"Show messages in fullscreen mode.\"\r\nMsg_Options_GUI_VSync                   = \"Wait for VSync in interface mode.\"\r\nMsg_Options_Capture_Crop_Align          = \"Crop and align screen captures to 8x8 boundaries.\"\r\nMsg_Options_NES_Enable                  = \"Mario is not a fat plumber.\"\r\nMsg_Options_GUI_GameWindowScale         = \"Game window size: %d%%\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Language set to %s\"\r\nMsg_Language_Set_Warning                = \"Note: it is recommended that you restart MEKA to make sure all text updates.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Started dumping sound output to %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Stopped dumping sound output (%2.02f seconds logged)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Unable to find a valid filename to dump sound output!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Error opening output file %s for dumping!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"VGM dumps will now be frame accurate (smaller files, skip voices)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"VGM dumps will now be sample accurate (bigger files, dump voices)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(VGM dumping will have to be restarted to take account of new accuracy)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"MAIN\"\r\nMsg_Menu_Main_LoadROM                   = \"Load ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Free ROM\"\r\nMsg_Menu_Main_SaveState_Save            = \"Save State\"\r\nMsg_Menu_Main_SaveState_Load            = \"Load State\"\r\nMsg_Menu_Main_SaveState_PrevSlot        = \"Previous Slot\"\r\nMsg_Menu_Main_SaveState_NextSlot        = \"Next Slot\"\r\nMsg_Menu_Main_Options                   = \"Options..\"\r\nMsg_Menu_Main_Language                  = \"Language\"\r\nMsg_Menu_Main_Quit                      = \"Quit\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Enabled                  = \"Enabled..\"\r\nMsg_Menu_Debug_ReloadROM                = \"Reload ROM\"\r\nMsg_Menu_Debug_ReloadSymbols            = \"Reload Symbols\"\r\nMsg_Menu_Debug_StepFrame                = \"Step Frame\"\r\nMsg_Menu_Debug_LoadStateAndContinue     = \"Load State & Continue\"\r\nMsg_Menu_Debug_Dump                     = \"Dump\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MACHINE\"\r\nMsg_Menu_Machine_Power                  = \"Power\"\r\nMsg_Menu_Machine_Power_On               = \"On\"\r\nMsg_Menu_Machine_Power_Off              = \"Off\"\r\nMsg_Menu_Machine_Region                 = \"Region\"\r\nMsg_Menu_Machine_Region_Export          = \"Europe/US\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japan\"\r\nMsg_Menu_Machine_TVType                 = \"TV Type\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\nMsg_Menu_Machine_PauseEmulation         = \"Pause Emulation\"\r\nMsg_Menu_Machine_ResetEmulation         = \"Reset Emulation\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Fullscreen\"\r\nMsg_Menu_Video_Themes                   = \"Themes\"\r\nMsg_Menu_Video_Blitters                 = \"Blitters\"\r\nMsg_Menu_Video_Layers                   = \"Layers\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Background\"\r\nMsg_Menu_Video_Flickering               = \"Sprite Flickering\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Yes\"\r\nMsg_Menu_Video_Flickering_No            = \"No\"\r\nMsg_Menu_Video_3DGlasses                = \"3-D Glasses\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Enabled\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Show both sides\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Show left side\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Show right side\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Uses Glasses on COM Port\"\r\nMsg_Menu_Video_ScreenCapture            = \"Screen Capture\"\r\nMsg_Menu_Video_ScreenCapture_Capture    = \"Screen Capture\"\r\nMsg_Menu_Video_ScreenCapture_CaptureRepeat = \"Screen Capture (every frame)\"\r\nMsg_Menu_Video_ScreenCapture_IncludeGUI = \"Include GUI\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"SOUND\"\r\nMsg_Menu_Sound_FM                       = \"FM Unit\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Enabled\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Disabled\"\r\nMsg_Menu_Sound_FM_Editor                = \"Instruments Editor\"\r\nMsg_Menu_Sound_Volume                   = \"Volume\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Mute\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Rate\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Channels\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Tone %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Noises\"\r\nMsg_Menu_Sound_Capture                     = \"Capture\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"WAV Start\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"WAV Stop\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"VGM Start\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"VGM Stop\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM Sample Accurate\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"INPUTS\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddle Control\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Graphic Board (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_GraphicBoardV2          = \"Graphic Board v2.0\"\r\nMsg_Menu_Inputs_SK1100                  = \"Sega Keyboard\"\r\nMsg_Menu_Inputs_RapidFire               = \"Rapid Fire\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Player %d Button %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Configuration..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"TOOLS\"\r\nMsg_Menu_Tools_Messages                 = \"Messages..\"\r\nMsg_Menu_Tools_Palette                  = \"Palette..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Tiles Viewer..\"\r\nMsg_Menu_Tools_TilemapViewer            = \"Tilemap Viewer..\"\r\nMsg_Menu_Tools_CheatFinder              = \"Cheat Finder..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Tech Info..\"\r\nMsg_Menu_Tools_MemoryEditor             = \"Memory Editor..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"HELP\"\r\nMsg_Menu_Help_Documentation             = \"Documentation..\"\r\nMsg_Menu_Help_Compat                    = \"Compatibility List..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Multiplayer Games List..\"\r\nMsg_Menu_Help_Changes                   = \"Changes List..\"\r\nMsg_Menu_Help_Debugger\t\t\t\t\t= \"Debugger..\"\r\nMsg_Menu_Help_About                     = \"About..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Français]\r\nWIP\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Bienvenue dans %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - 8 bit ou rien!\"\r\nMsg_Quit                                = \"Good night, brave warrior. Good night, monster-land....\"\r\n;Msg_Quit                               = \"Bonne nuit, brave guerrier. Bonne nuit, pays des monstres....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"A propos de Meka...\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"par %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Ok                                  = \"Ok\"\r\nMsg_Failed                              = \"Echec!\"\r\nMsg_Error_Base                          = \"Erreur: %s\"\r\nMsg_Error_Error                         = \"Fatal: l'erreur a fait une erreur. Quelque chose ne va pas.\"\r\nMsg_Error_Memory                        = \"Mémoire insuffisante!\"\r\nMsg_Error_Param                         = \"Le paramètre \\\"%s\\\" est invalide!\\n\"\r\nMsg_Error_Syntax                        = \"Erreur de syntaxe!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Impossible de basculer vers le mode vidéo souhait‚ (%dx%d).\"\r\nMsg_Error_Video_Mode_Back_To_GUI        = \"Passage en mode interface.\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Fichier introuvable!\"\r\nMsg_Error_File_Read                     = \"Impossible de lire le fichier!\"\r\nMsg_Error_File_Empty                    = \"Le fichier est vide!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Cette version ne supporte pas les fichiers ZIP!\"\r\nMsg_Error_ZIP_Loading                   = \"Impossible de lire le fichier ZIP!\"\r\nMsg_Error_ZIP_Internal                  = \"Erreur interne lors du chargement du fichier ZIP!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Erreur en ouvrant le dossier!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Réinitialiser le jeu pour que les changements prennent effet\"\r\nMsg_No_ROM                              = \"Aucune ROM chargée!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Initialisation d'Allegro...\"\r\nMsg_Init_GUI                            = \"Initialisation de l'interface graphique...\"\r\nMsg_Init_Completed                      = \"[PRET]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\nMsg_Setup_Running                       = \"Execution du programme de configuration...\"\r\nMsg_Setup_Setup                         = \"Configuration\"\r\nMsg_Setup_SampleRate_Select             = \"Fréquence d'échantillonage:\"\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Ecran capturé dans %s\"\r\nMsg_Capture_Error                       = \"Impossible de sauvegarder la capture d'écran!\"\r\nMsg_Capture_Error_File                  = \"Impossible de trouver un nom de fichier valide pour sauvegarder la capture d'écran!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"SaveRAM chargée depuis le disque (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Impossible de charger la SaveRAM depuis le disque\"\r\nMsg_SRAM_Wrote                          = \"SaveRAM écrite sur le disque (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Impossible d'écrire la SaveRAM sur le disque (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Réinitialisation du 93c46\"\r\nMsg_93c46_Loaded                        = \"Données EEPROM 93c46 chargées depuis le disque (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Impossible de charger les données EEPROM 93c46 depuis le disque\"\r\nMsg_93c46_Wrote                         = \"Données EEPROM 93c46 écrites sur le disque (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Impossible d'écrire les données EEPROM 93c46 sur le disque (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"Le type de TV est maintenant %s\"\r\nMsg_TVType_Info_Speed                   = \"(La vitesse originale est %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Chargement de MEKA.BLT (modes vid‚o / paramˆtres)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Il manque des paramˆtres! V‚rifiez le fichier MEKA.BLT ou essayez de r‚-installer.\"\r\nMsg_Blitters_Error_Not_Found            = \"Paramˆtres introuvables!\"\r\nMsg_Blitters_Error_Missing              = \"Ligne %d: Aucun nom de paramˆtre d‚fini pour la valeur en mˆmoire!\"\r\nMsg_Blitters_Error_Unrecognized         = \"Ligne %d: Variable inconnue!\"\r\nMsg_Blitters_Set                        = \"Paramêtre plein écran actuel \\\"%s\\\".\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Mode gros plombier activé\"\r\nMsg_NES_Sucks                           = \"Erreur fatale: l'utilisateur aime Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Mapper non supporté: %d. Le jeu ne devrait pas fonctionner.\"\r\nMsg_NES_Deny_Facts                      = \"Un fait est un fait.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Initialisation du débuggueur... \"\r\nMsg_Debug_Welcome                       = \"Bienvenue dans le débuggueur de Meka!\"\r\nMsg_Debug_Not_Available                 = \"Le débuggueur n'est pas disponible dans cette version!\"\r\nMsg_Debug_Trap_Read                     = \"A PC:%04X - Lecture depuis %04X\"\r\nMsg_Debug_Trap_Write                    = \"A PC:%04X - Ecriture de %02X dans %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"A PC:%04X - Lecture Port [%02X] \"\r\nMsg_Debug_Trap_Port_Write               = \"A PC:%04X - Ecriture %02X Port [%02X] \"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"L'acquisition des données sera maintenant faite en mode ASCII.\"\r\nMsg_DataDump_Mode_Raw                   = \"L'acquisition des données sera maintenant faite en mode Raw.\"\r\nMsg_DataDump_Error                      = \"Erreur en créant le fichier d'acquisition %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Pas de mémoire sur carte à acquérir!\"\r\nMsg_DataDump_Error_Palette              = \"Pas de palette à acquérir!\"\r\nMsg_DataDump_Error_Sprites              = \"Pas de sprites à acquérir!\"\r\nMsg_DataDump_Main                       = \"Acquisition %s (%d %s) en mode %s\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Documentation\"\r\nMsg_Doc_File_Error                      = \"Impossible d'ouvrir la documentation!\"\r\nMsg_Doc_Enabled                         = \"Documentation ouverte.\"\r\nMsg_Doc_Disabled                        = \"Documentation fermée.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Le clignotement des sprites sera géré automatiquement.\"\r\nMsg_Flickering_Yes                      = \"L'émulation du clignotement des sprite est maintenant activée.\"\r\nMsg_Flickering_No                       = \"L'émulation du clignotement des sprites n'est plus activée.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Rafraichissement du fond d'écran désactivé\"\r\nMsg_Layer_BG_Enabled                    = \"Rafraichissement du fond d'écran activé\"\r\nMsg_Layer_Spr_Disabled                  = \"Rafraichissement des sprites désactivé\"\r\nMsg_Layer_Spr_Enabled                   = \"Rafraichissement des sprites activé\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Commande %3i de lecture de disque inconnue\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Commande %3i d'écriture de disque inconnue\"\r\nMsg_FDC765_Disk_Too_Large1              = \"L'image du disque est plus grande que prévue (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Les données supplémentaires seront ignorées\"\r\nMsg_FDC765_Disk_Too_Small1              = \"L'image du disque est plus petite que prévue (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Les données manquantes seront considérées comme vides\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Palette\"\r\nMsg_Palette_Disabled                    = \"Visualisateur de palette désactivé\"\r\nMsg_Palette_Enabled                     = \"Visualisateur de palette activé\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Messages\"\r\nMsg_Message_Disabled                    = \"Fenêtre des messages désactivée\"\r\nMsg_Message_Enabled                     = \"Fenêtre des messages activée\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Informations Techniques\"\r\nMsg_TechInfo_Disabled                   = \"Fenêtre d'informations techniques désactivée\"\r\nMsg_TechInfo_Enabled                    = \"Fenêtre d'informations techniques activée\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Visionneur de tiles\"\r\nMsg_TilesViewer_Disabled                = \"Visionneur de tiles désactivé\"\r\nMsg_TilesViewer_Enabled                 = \"Visionneur de tiles activé\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Memory Editor --------------------------------------------------------------\r\nMsg_MemoryEditor_BoxTitle\t\t\t\t= \"Editeur mémoire\"\r\nMsg_MemoryEditor_Disabled\t\t\t\t= \"Editeur mémoire désactivé\"\r\nMsg_MemoryEditor_Enabled\t\t\t\t= \"Editeur mémoire activé\"\r\nMsg_MemoryEditor_WriteZ80_Unable\t\t= \"Impossible d'écrire dans l'espace d'addressage Z80 à cet instant!\"\r\nMsg_MemoryEditor_Address_Out_of_Bound\t= \"L'addresse %s est hors de la zone %s!\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Tir Automatique activé pour le joueur %d, bouton %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Tir Automatique désactivé pour le joueur %d, bouton %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"Emulation de l'unité FM (chipset YM-2413) activée\"\r\nMsg_FM_Disabled                         = \"Emulation de l'unité FM (chipset YM-2413) désactivée\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"La machine émulée est maintenant Européenne/US\"\r\nMsg_Country_JAP                         = \"La machine émulée est maintenant Japonaise\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Chargement de MEKA.PAT (patches)... \"\r\nMsg_Patch_Missing                       = \"Ligne %d: Checksum non d‚finit pour appliquer la commande!\"\r\nMsg_Patch_Unrecognized                  = \"Ligne %d: Erreur de syntaxe ou commande inconnue!\"\r\nMsg_Patch_Value_Not_a_Byte              = \"Ligne %d: La valeur %s ne tient pas sur un octet non signé!\"\r\nMsg_Patch_Out_of_Bound                  = \"Lors du patch de %s: la position $%04X est hors des limites. Patch non appliqué.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"Emulation des lunettes 3-D activée\"\r\nMsg_Glasses_Disabled                    = \"Emulation des lunettes 3-D désactivée\"\r\nMsg_Glasses_Show_Both                   = \"Effet 3-D complet.\"\r\nMsg_Glasses_Show_Left                   = \"Effet 3-D désactivé en ne gardant que le côté gauche.\"\r\nMsg_Glasses_Show_Right                  = \"Effet 3-D désactivé en ne gardant que le côté droit.\"\r\nMsg_Glasses_Com_Port                    = \"Support des lunettes 3-D activé sur le port COM %d.\"\r\nMsg_Glasses_Com_Port2                   = \"(éditer MEKA.CFG pour sélectionner le port COM à utiliser)\"\r\nMsg_Glasses_Com_Port_Open_Error\t\t\t= \"Erreur à l'ouverture du port COM %d. Le support des lunettes 3-D ne fonctionnera pas.\"\r\nMsg_Glasses_Unsupported                 = \"Ce jeu ne supporte pas les lunettes 3-D.\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Initialisation des joysticks... \"\r\nMsg_Inputs_Joy_Init_None                = \"aucun joystick trouv‚.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d trouv‚(s).\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Arrˆt : Erreur de calibrage de joystick.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Périphérique de contrôle: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Périphérique de contrôle: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Périphérique de contrôle: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Périphérique de contrôle: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Périphérique de contrôle: Tablette Graphique\"\r\nMsg_Inputs_Play_Digital                 = \"Contrôle avec périphérique d'entrée digital\"\r\nMsg_Inputs_Play_Mouse                   = \"Contrôle avec périphérique d'entrée analogique (souris)\"\r\nMsg_Inputs_Play_Digital_Unrecommended   = \"Un périphérique d'entrée digital (ex: clavier) est supporté mais NON conseillé\"\r\nMsg_Inputs_Play_Pen                     = \"Contrôle du stylo avec la souris\\nLe click-droit simule la levée du stylo de la tablette\"\r\nMsg_Inputs_SK1100_Enabled               = \"Emulation du Sega Keyboard (SK-1100) activée\"\r\nMsg_Inputs_SK1100_Disabled              = \"Emulation du Sega Keyboard (SK-1100) désactivée\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Configuration des contrôles\"\r\nMsg_Inputs_Config_Peripheral_Click      = \"Clic pour sélectionner périphérique\"\r\nMsg_Inputs_Config_Source_Enabled        = \"Actif\"\r\nMsg_Inputs_Config_Source_Player         = \"Contrôle joueur %d\"\r\nMsg_Inputs_Config_Source_Emulate_Joypad = \"Emule le joypad\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Chargement de MEKA.INP (d‚finition des sources de contr“le)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Il manque des sources de contr“le! V‚rifiez le fichier MEKA.INP ou essayez de r‚-installer.\"\r\nMsg_Inputs_Src_Missing                  = \"Ligne %d: Aucune source de contr“le d‚finie pour la valeur en m‚moire!\"\r\nMsg_Inputs_Src_Equal                    = \"Ligne %d: Signe ‚gal manquant pour l'attribution de la variable!\"\r\nMsg_Inputs_Src_Unrecognized             = \"Ligne %d: Variable \\\"%s\\\" non reconnue!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"Ligne %d: Erreur de syntaxe sur paramˆtre variable!\"\r\nMsg_Inputs_Src_Inconsistency            = \"Ligne %d: Ne correspond pas aux r‚glages pr‚c‚dents!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Appuyez sur la touche souhaitée pour y attribuer cette action\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Action attribuée à la touche \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Appuyez sur le bouton ou la direction souhaité pour y attribuer cette action\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Action attribuée au stick %i, axe %i, %c du joypad.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Action attribuée au bouton %i du joypad.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Appuyez sur le bouton souhaité pour y attribuer cette action\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Action attribuée au bouton %i de la souris.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Désolé - L'axe de la souris ne peut pas être changé\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Attribution annulée!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Emulation en pause\"\r\nMsg_Machine_Resume                      = \"Emulation rétablie\"\r\nMsg_Machine_Reset                       = \"Réinitialisation de la machine\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\nMsg_FDB_Loading                         = \"Chargement de MEKA.FDB (base de donnée fichiers)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Chargement de MEKA.NAM (noms des jeux)... \"\r\nMsg_DB_Name_Default                     = \"Ecran de jeu\"\r\nMsg_DB_Name_NoCartridge                 = \"Pas de cartouche\"\r\nMsg_DB_SyntaxError                      = \"Ligne %d: Erreur de syntaxe!\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Chargement de %s (configuration)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Chargement de MEKA.DAT (ressources)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatal: Pilote Machine Inconnu!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\nMsg_OverDump                            = \"Cette ROM contient %d fois les données nécessaires.\\nTéléchargez SMS Checker pour la vérifier (http://www.smspower.org/maxim/smschecker/).\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Initialisation du son...\"\r\nMsg_Sound_Init_Error_Audio              = \" - Erreur en ouvrant le systˆme audio. Essayez une carte et/ou une fr‚quence diff‚rente.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - Variable BLASTER introuvable, son FM d‚sactiv‚!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - La variable BLASTER ne contient l'adresse (A=xxx), son FM d‚sactiv‚!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Echec de l'initialisation des voies.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Echec dans la cr‚ation de la voie #%d.\"\r\nMsg_Sound_Init_Soundcard                = \" - Initialisation de la carte son … %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Impossible d'initialiser l'audio: aucune carte son s‚lectionn‚e!\"\r\nMsg_Sound_Init_SN76496                  = \" - Emulateur SN76496 digital:\"\r\nMsg_Sound_Init_YM2413_Digital           = \" - Emulateur YM2413 digital:\"\r\nMsg_Sound_Stream_Error                  = \"Arrêt du tampon son. Redémarrage du flux.\"\r\nMsg_Sound_Volume_Changed                = \"Volume changé à %d%%.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Chargement de MEKA.THM (thêmes de l'interface)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Il manque des thêmes! Vérifiez le fichier MEKA.THM ou essayez de réinstaller.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"Ligne %d: Aucun nom de thême défini pour stocker l'attribut!\"\r\nMsg_Theme_Error_Syntax                  = \"Ligne %d: Erreur de syntaxe!\"\r\nMsg_Theme_Error_Attribute_Defined       = \"Ligne %d: Attribute déja défini!\"\r\nMsg_Theme_Error_Out_of_Bound            = \"Ligne %d: Valeur hors limites!\"\r\nMsg_Theme_Error_Theme_Missing_Data      = \"Le thême \\\"%s\\\" est incomplet. Il sera désactivé.\"\r\nMsg_Theme_Error_BG_Big                  = \"Image d'arrière-plan trop petite pour l'ajuster complètement!\"\r\nMsg_Theme_Error_BG                      = \"Erreur de chargement de l'image associée au thème!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Chargement de la ROM.. \"\r\nMsg_LoadROM_Success                     = \"Chargement de %s réussi\"\r\nMsg_LoadDisk_Success                    = \"Chargement de %s réussi depuis la disquette\"\r\nMsg_LoadROM_Comment                     = \"Commentaire: %s\"\r\nMsg_LoadROM_SMSGG_Mode_Comment          = \"Ceci est une ROM Game Gear fonctionnant en mode de compatibilité Master System.\"\r\nMsg_LoadROM_Warning                     = \"-Avertissement-\"\r\nMsg_LoadROM_Bad_Dump_Long               = \"Cette ROM est connue comme étant un mauvais dump.\\nIl se peut qu'elle ne fonctionne pas correctement. Téléchargez SMS Checker pour la vérifier (http://www.smspower.org/maxim/smschecker/).\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Avertissement - Cette ROM est connue comme étant un mauvais dump.\"\r\nMsg_LoadROM_Product_Num                 = \"Numéro de produit: %s\"\r\nMsg_LoadROM_SDSC                        = \"-En-tête SDSC-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Nom: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Version: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Date: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Auteur: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Note: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Inconnu>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Erreur>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Charger une ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Disque %c]\"\r\nMsg_FileBrowser_Load                    = \"Charger\"\r\nMsg_FileBrowser_Close                   = \"Fermer\"\r\nMsg_FileBrowser_LoadNames               = \"Lire noms\"\r\nMsg_FileBrowser_ReloadDir               = \"Relire dossier\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"Editeur d'instruments FM\"\r\nMsg_FM_Editor_Enabled                   = \"Editeur d'instruments FM activé\"\r\nMsg_FM_Editor_Disabled                  = \"Editeur d'instruments FM désactivé\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Saut d'image automatique (à %d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Saut d'image fixé à: 1/%d images\"\r\nMsg_FPS_Counter_Enabled                 = \"Compteur d'image par seconde activé\"\r\nMsg_FPS_Counter_Disabled                = \"Compteur d'image par seconde désactivé\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"Le paramêtre LOG nécessite un nom de fichier!\"\r\nMsg_Log_Session_Start                   = \"-- Rapport de session débuté le %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"Le paramêtre LOAD nécessite un numéro de sauvegarde!\"\r\nMsg_Load_Error                          = \"Erreur en ouvrant %s!\"\r\nMsg_Load_Not_Valid                      = \"Le fichier %s n'est pas une sauvegarde valide de %s!\"\r\nMsg_Load_Success                        = \"Etat chargé depuis %s\"\r\nMsg_Load_Version                        = \"%s n'est pas une version de sauvegarde supportée!\"\r\nMsg_Load_Wrong_System                   = \"%s n'est pas une sauvegarde pour ce système!\"\r\nMsg_Load_Massage                        = \"Le fichier est au format MSD - conversion en cours\"\r\nMsg_Save_Not_in_BIOS                    = \"Impossible de sauver pendant le BIOS!\"\r\nMsg_Save_Error                          = \"Erreur d'écriture dans %s!\"\r\nMsg_Save_Success                        = \"Etat sauvegardé dans %s\"\r\nMsg_Save_Slot                           = \"Emplacement actuel de sauvegarde: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Options\"\r\nMsg_Options_Close                       = \"Fermer\"\r\nMsg_Options_BIOS_Enable                 = \"Afficher le logo du BIOS.\"\r\nMsg_Options_DB_Display                  = \"Afficher noms, drapeaux et icônes de la base.\"\r\nMsg_Options_Product_Number              = \"Afficher numéros de produit de la base.\"\r\nMsg_Options_Bright_Palette              = \"Activer palette vive pour SMS et GG.\"\r\nMsg_Options_Allow_Opposite_Directions   = \"Permettre l'appui de directions opposées.\"\r\nMsg_Options_Load_Close                  = \"Fermer l'explorateur après chargement d'un jeu.\"\r\nMsg_Options_Load_FullScreen             = \"Mode plein écran auto après chargement d'un jeu.\"\r\nMsg_Options_FullScreen_Messages         = \"Afficher les messages en mode plein écran.\"\r\nMsg_Options_GUI_VSync                   = \"Attendre la VSync en mode interface.\"\r\nMsg_Options_NES_Enable                  = \"Mario n'est pas un gros plombier.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"La langue est maintenant le %s\"\r\nMsg_Language_Set_Warning                = \"Note: il est recommandé de redémarrer MEKA afin d'avoir tous les textes mis à jour.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Acquisition de la sortie sonore dans %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Acquisition de la sortie sonore arrêtée (%2.02f secondes enregistrées)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Impossible de trouver un nom de fichier valide pour extraire la sortie sonore!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Erreur d'ouverture du fichier %s pour l'acquisition!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"L'acquisition VGM sera maintenant fidèle à la trame (fichiers plus petits, voies sautées)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"L'acquisition VGM sera maintenant fidèle à l'échantillon (fichiers plus importants, acquisition des voies)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(l'acquisition VGM devra être redémarrée pour tenir en compte du changement de paramètre)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"PRINCIPAL\"\r\nMsg_Menu_Main_LoadROM                   = \"Charger ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Libérer ROM\"\r\nMsg_Menu_Main_SaveState_Save            = \"Sauver état\"\r\nMsg_Menu_Main_SaveState_Load            = \"Charger état\"\r\nMsg_Menu_Main_Options                   = \"Options..\"\r\nMsg_Menu_Main_Language                  = \"Langue\"\r\nMsg_Menu_Main_Quit                      = \"Quitter\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Enabled                  = \"Activé..\"\r\nMsg_Menu_Debug_Dump                     = \"Acquisition\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MACHINE\"\r\nMsg_Menu_Machine_Power                  = \"Marche/Arrêt\"\r\nMsg_Menu_Machine_Power_On               = \"Allumer\"\r\nMsg_Menu_Machine_Power_Off              = \"Eteindre\"\r\nMsg_Menu_Machine_Region                 = \"Région\"\r\nMsg_Menu_Machine_Region_Export          = \"Europe/US\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japon\"\r\nMsg_Menu_Machine_TVType                 = \"Type de TV\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\nMsg_Menu_Machine_PauseEmulation         = \"Pause émulation\"\r\nMsg_Menu_Machine_ResetEmulation         = \"Reset émulation\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Plein écran\"\r\nMsg_Menu_Video_Themes                   = \"Thèmes\"\r\nMsg_Menu_Video_Blitters                 = \"Paramètres\"\r\nMsg_Menu_Video_Layers                   = \"Plans\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Arrière plan\"\r\nMsg_Menu_Video_Flickering               = \"Clignotement des sprites\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Automatique\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Activé\"\r\nMsg_Menu_Video_Flickering_No            = \"Désactivé\"\r\nMsg_Menu_Video_3DGlasses                = \"Lunettes 3-D\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Activées\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Activer les deux côtés\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Activer le côté gauche\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Activer le côté droit\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Lunettes sur le Port COM\"\r\nMsg_Menu_Video_ScreenCapture            = \"Capture d'écrqn\"\r\nMsg_Menu_Video_ScreenCapture_Capture    = \"Capturer l'écran\"\r\nMsg_Menu_Video_ScreenCapture_CaptureRepeat = \"Capturer l'écran (tous)\"\r\nMsg_Menu_Video_ScreenCapture_IncludeGUI    = \"Inclure l'interface\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"SON\"\r\nMsg_Menu_Sound_FM                       = \"Module FM\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Activé\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Désactivé\"\r\nMsg_Menu_Sound_FM_Editor                = \"Editeur d'instruments\"\r\nMsg_Menu_Sound_Volume                   = \"Volume\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Muet\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Fréquence\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Canaux\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Ton %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Bruits\"\r\nMsg_Menu_Sound_Capture                     = \"Capture\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"Démarrer en WAV\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"Arrêter en WAV\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"Démarrer en VGM\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"Arrêter en VGM\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"Haute précision VGM\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"CONTROLE\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddle Control\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Table Graphique (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_GraphicBoardV2          = \"Table Graphique v2.0\"\r\nMsg_Menu_Inputs_SK1100                  = \"Clavier Sega\"\r\nMsg_Menu_Inputs_RapidFire               = \"Tir Automatique\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Joueur %d Bouton %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Configuration..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"OUTILS\"\r\nMsg_Menu_Tools_Messages                 = \"Messages..\"\r\nMsg_Menu_Tools_Palette                  = \"Palette..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Visionneur de tiles..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Informations techniques..\"\r\nMsg_Menu_Tools_MemoryEditor\t\t\t\t= \"Editeur mémoire..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"AIDE\"\r\nMsg_Menu_Help_Documentation             = \"Documentation..\"\r\nMsg_Menu_Help_Compat                    = \"Compatibilité..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Jeux Multijoueurs..\"\r\nMsg_Menu_Help_Changes                   = \"Mises à jour..\"\r\nMsg_Menu_Help_About                     = \"A propos..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Dutch]\r\nWIP\r\n; Dutch text door Mark van Tilburg\r\n; Beheerder: Mark van Tilburg (markvt AT van-tilburg DOT info)\r\n; Laatst bijgewerkt 22-07-2012\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Welkom bij %s (c) %s\"\r\nMsg_Window_Title                        = \"MEKA - Wij Vertrouwen Op Pixels!\"\r\nMsg_Quit                                = \"Slaap lekker, dappere strijder. goede nacht, monsterland....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"Over Meka..\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"by %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Ok                                  = \"Ok\"\r\nMsg_Failed                              = \"Failed!\"\r\nMsg_Error_Base                          = \"Error: %s\"\r\nMsg_Error_Error                         = \"Fatale error: getting error type. Er moet iets fout zijn.\"\r\nMsg_Error_Memory                        = \"Niet genoeg geheugen!\"\r\nMsg_Error_Param                         = \"Parameter \\\"%s\\\" is invalide!\\n\"\r\nMsg_Error_Syntax                        = \"Syntax fout!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Niet mogelijk naar de gewenste video mode te switchen (%dx%d).\"\r\nMsg_Error_Video_Mode_Back_To_GUI        = \"Terugschakelen naar de grafische user interface.\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"bestand niet gevonden!\"\r\nMsg_Error_File_Read                     = \"onmogelijk om van bestand te lezen!\"\r\nMsg_Error_File_Empty                    = \"bestand is leeg!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"deze versie kan niet met ZIP bestanden werken!\"\r\nMsg_Error_ZIP_Loading                   = \"niet mogelijk ZIP bestand te lezen\"\r\nMsg_Error_ZIP_Internal                  = \"Interne error bij het openen van ZIP bestand!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Error opening directory!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Reset het spel om de wijzigingen te bekijken\"\r\nMsg_No_ROM                              = \"Er is geen ROM geladen!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Opstarten van Allegro..\"\r\nMsg_Init_GUI                            = \"Opstarten grafische gebruikers interface\"\r\nMsg_Init_Completed                      = \"[klaar]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\nMsg_Setup_Running                       = \"Setup wordt uitgevoerd...\"\r\nMsg_Setup_Setup                         = \"Setup\"\r\nMsg_Setup_Video_Driver                  = \"Video driver:\"\r\nMsg_Setup_Video_DisplayMode             = \"Video mode:\"\r\nMsg_Setup_SampleRate_Select             = \"Sample rate:\"\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Screenfoto naar %s\"\r\nMsg_Capture_Error                       = \"Niet mogelijk een schermfoto te maken!\"\r\nMsg_Capture_Error_File                  = \"Niet mogelijk een bestandsnaam te vinden voor screenfoto!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"SaveRAM van disk geladen (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"niet mogelijk SaveRAM van disk te laden\"\r\nMsg_SRAM_Wrote                          = \"SaveRAM to disk geschreven (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"niet mogelijk SaveRAM naar disk te schrijven (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Herstarting 93c46\"\r\nMsg_93c46_Loaded                        = \"geladen 93c46 EEPROM data van disk (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"niet mogelijk 93c46 EEPROM data van disk te laden\"\r\nMsg_93c46_Wrote                         = \"93c46 EEPROM data naar disk geschreven (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"niet mogelijk 93c46 EEPROM data naar disk te schrijven (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"TV Type is nu %s\"\r\nMsg_TVType_Info_Speed                   = \"(Originele snelheid is %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Laden van MEKA.BLT (video modes / blitters)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"niet genoeg blitters gevonden controleer MEKA.BLT herinstalleer\"\r\nMsg_Blitters_Error_Not_Found            = \"Blitter niet gevonden!\"\r\nMsg_Blitters_Error_Missing              = \"Op regel %d: Geen blitter naam ingesteld om de waarde te bewaren!\"\r\nMsg_Blitters_Error_Unrecognized         = \"Op regel %d: niet herkende variable!\"\r\nMsg_Blitters_Error_Incorrect_Value      = \"Op regel %d: Incorrect value!\"\r\nMsg_Blitters_Set                        = \"Gebruikt nu \\\"%s\\\" volledig scherm.\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Dikke loodgieter mode geactiveerd\"\r\nMsg_NES_Sucks                           = \"Fatale fout: gebruiker houd van Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Niet ondersteunde mapper: %d. Spel zou niet moeten functioneren\"\r\nMsg_NES_Deny_Facts                      = \"Je kunt geen feiten ontkennen\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Opstarten van de debugger \"\r\nMsg_Debug_Welcome                       = \"Welkom bij de Meka Debugger!\"\r\nMsg_Debug_Not_Available                 = \"Debugger is niet beschikbaar in deze versie!\"\r\nMsg_Debug_Trap_Read                     = \"Op PC:%04X - lees van %04X\"\r\nMsg_Debug_Trap_Write                    = \"Op PC:%04X - schrijf %02X tot %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"Op PC:%04X - Poort [%02X] lees\"\r\nMsg_Debug_Trap_Port_Write               = \"Op PC:%04X - Poort [%02X] schrijf %02X\"\r\nMsg_Debug_Symbols_Loaded                = \"%d symbolen geladen uit \\\"%s\\\".\"\r\nMsg_Debug_Symbols_Error                 = \"Error bij het laden van de symbolen uit \\\"%s\\\":\"\r\nMsg_Debug_Symbols_Error_Line            = \"Op regel %d: niet herkende syntax.\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Data dumps zullen gemaakt worden in ASCII mode\"\r\nMsg_DataDump_Mode_Raw                   = \"Data dumps zullen gemaakt worden in RAW mode.\"\r\nMsg_DataDump_Error                      = \"Fout bij het maken van het bestand voor de dump %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Geen memory om te dumpen!\"\r\nMsg_DataDump_Error_Palette              = \"Geen palet om te dumpen!\"\r\nMsg_DataDump_Error_Sprites              = \"Geen sprites om te dumpen!\"\r\nMsg_DataDump_Main                       = \"Dumped %s (%d %s) in %s mode\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Documentatie\"\r\nMsg_Doc_File_Error                      = \"Niet mogelijk de documentatie te openen!\"\r\nMsg_Doc_Enabled                         = \"Documentatie geopend\"\r\nMsg_Doc_Disabled                        = \"Documentatie gesloten\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite flikkeren zal automatisch gedaan worden.\"\r\nMsg_Flickering_Yes                      = \"Sprite flikkeren emulatie is nu aan.\"\r\nMsg_Flickering_No                       = \"Sprite flikkeren emulatie is nu uit.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Background herlaad uit\"\r\nMsg_Layer_BG_Enabled                    = \"Background herlaad aan\"\r\nMsg_Layer_Spr_Disabled                  = \"Sprites herlaad uit\"\r\nMsg_Layer_Spr_Enabled                   = \"Sprites herlaad aan\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: onbekend disk lees commando %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: onbekend disk schrijf commando %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Disk bestand is groter dan verwacht (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Extra data zal worden genegeerd\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Disk Image is kleiner dan verwacht (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Missende data wordt aangenomen als leeg\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Kleuren pallet\"\r\nMsg_Palette_Disabled                    = \"Palet bekijker uit\"\r\nMsg_Palette_Enabled                     = \"Palet bekijker aan\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Berichten\"\r\nMsg_Message_Disabled                    = \"Berichtenbox uit\"\r\nMsg_Message_Enabled                     = \"Berichtenbox aan\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Technische Informatie\"\r\nMsg_TechInfo_Disabled                   = \"Technische informatie box uit\"\r\nMsg_TechInfo_Enabled                    = \"Technische informatie box aan\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Tiles bekijker\"\r\nMsg_TilesViewer_Disabled                = \"Tiles bekijker uit\"\r\nMsg_TilesViewer_Enabled                 = \"Tiles bekijker aan\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Memory Editor --------------------------------------------------------------\r\nMsg_MemoryEditor_BoxTitle\t\t\t\t= \"Memory Editor\"\r\nMsg_MemoryEditor_Disabled\t\t\t\t= \"Memory Editor uitgeschakeld\"\r\nMsg_MemoryEditor_Enabled\t\t\t\t= \"Memory Editor ingeschakeld\"\r\nMsg_MemoryEditor_WriteZ80_Unable\t\t= \"Niet mogelijk om in Z80 addres te schrijven!\"\r\nMsg_MemoryEditor_Address_Out_of_Bound\t= \"Addres %s is niet binnen de toegestane %s grenzen!\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Snelschieten is geactiveerd voor speler %d knop %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Snelschieten is gedeactiveerd voor speler %d knop %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"FM Unit (YM-2413 chipset) emulatie aan\"\r\nMsg_FM_Disabled                         = \"FM Unit (YM-2413 chipset) emulatie uit\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Emulated machine is nu Europees/US\"\r\nMsg_Country_JAP                         = \"Emulated machine is nu Japans\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Laden MEKA.PAT (patches)... \"\r\nMsg_Patch_Missing                       = \"On line %d: Geen checksum ingesteld voor de patch!\"\r\nMsg_Patch_Unrecognized                  = \"On line %d: Niet herkende instruktie!\"\r\nMsg_Patch_Value_Not_a_Byte              = \"On line %d: waarde %s past niet in een unsigned byte!\"\r\nMsg_Patch_Out_of_Bound                  = \"Tijdens het patchen van de ROM: geprobeerd om buiten het bestand te schrijven $%02X. Afbreken van de patch.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"3-D bril emulatie aan\"\r\nMsg_Glasses_Disabled                    = \"3-D bril emulatie uit\"\r\nMsg_Glasses_Show_Both                   = \"3-D effect hetzelfde\"\r\nMsg_Glasses_Show_Left                   = \"3-D effect uit u ziet alleen de linker kant.\"\r\nMsg_Glasses_Show_Right                  = \"3-D effect uit u ziet alleen de rechtse kant\"\r\nMsg_Glasses_Com_Port                    = \"3-D Glasses emulatie geactiveerd door COM Poort %d.\"\r\nMsg_Glasses_Com_Port2                   = \"(wijzig MEKA.CFG om de te gebruiken COM poort in te stellen.)\"\r\nMsg_Glasses_Com_Port_Open_Error\t\t    = \"Error bij het openen van COM poort %d. 3-D bril ondersteuning zal niet werken.\"\r\nMsg_Glasses_Unsupported                 = \"Het lijkt erop alsof dit spel de 3d bril niet ondersteunt\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Initializeren joystick.. \"\r\nMsg_Inputs_Joy_Init_None                = \"geen gevonden.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d gevonden.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Error bij het afstellen van de joystick. Afbrekende.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Input apparaat: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Input apparaat: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Input apparaat: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Input apparaat: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Input apparaat: TV Oekaki Graphic Board\"\r\nMsg_Inputs_Play_Digital                 = \"Controle met digitaal input device\"\r\nMsg_Inputs_Play_Mouse                   = \"Controle met analoog input device (mouse)\"\r\nMsg_Inputs_Play_Digital_Unrecommended   = \"Een dingitaal input apparaat (bv: toetsenbord) is ondersteund maar NIET aanbevolen\"\r\nMsg_Inputs_Play_Pen                     = \"Controle pen with mouse\\nRight-click simulates removing the pen from the board\"\r\nMsg_Inputs_SK1100_Enabled               = \"Sega toetsenbord (SK-1100) emulatie ingeschakeld\"\r\nMsg_Inputs_SK1100_Disabled              = \"Sega toetsenbord(SK-1100) emulatie uitgeschakeld\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Input Configuratie\"\r\nMsg_Inputs_Config_Peripheral_Click      = \"Klik om de accesoire te selecteren\"\r\nMsg_Inputs_Config_Source_Enabled        = \"Ingeschakeld\"\r\nMsg_Inputs_Config_Source_Player         = \"Bestuurd speler %d\"\r\nMsg_Inputs_Config_Source_Emulate_Joypad = \"Joypad emuleren\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Laden van MEKA.INP (voegt sources definitions in)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"niet genoeg input sources gevonden! raadpleeg MEKA.INP bestand, of herinstalleer.\"\r\nMsg_Inputs_Src_Missing                  = \"On line %d: Geen input signaal om de waarde toe te kennen!\"\r\nMsg_Inputs_Src_Equal                    = \"On line %d: Mist hetzelfde signaal voor de waarde!\"\r\nMsg_Inputs_Src_Unrecognized             = \"On line %d: niet herkende variable \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"On line %d: Syntax error bij variabele parameter\"\r\nMsg_Inputs_Src_Inconsistency            = \"On line %d: niet werkend met vorige instelling!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"druk op de knop die je met deze aktie wilt gebruiken\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Aktie vastgemaakt aan knop \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Druk op de knop/as die je aan deze aktie wilt koppelen\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Aktie vastgemaakt aan joypad knuppel %i, as %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Aktie vastgemaakt aan joypad knop %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Druk op de knop die je aan deze aktie wilt koppelen\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Aktie gekoppeld aan muis knop %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Sorry - Muis assen kunnen niet wordne verandert\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"koppeling geannuleerd!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Machine emulatie gepauzeerd\"\r\nMsg_Machine_Resume                      = \"Machine emulatie hervat\"\r\nMsg_Machine_Reset                       = \"Machine reset\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\nMsg_FDB_Loading                         = \"Laden van MEKA.FDB (bestandsnamen database)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Laden van MEKA.NAM (Spel namen)... \"\r\nMsg_DB_Name_Default                     = \"Spel scherm\"\r\nMsg_DB_Name_NoCartridge                 = \"Geen Cartridge\"\r\nMsg_DB_SyntaxError                      = \"Op regel %d: Syntax fout!\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Laden van %s (configuratie)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Laden van MEKA.DAT (resources)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fataal: Onbekende Machine Driver!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\nMsg_OverDump                            = \"Deze ROM bevat %d keer de noodzakelijke data.\\nDownload SMS Checker om deze data te verwijderen (http://www.smspower.org/maxim/smschecker/).\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Initialiseren geluids systeem..\"\r\nMsg_Sound_Init_Error_Audio              = \" - Error opening Audio systeem. probeer een andere kaart of sample rate.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER variable niet gevonden, uitzetten van FM sound!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - BLASTER variable bevat het adres (A=xxx) niet, uitzetten van FM sound!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Voices initialisatie gefaaild.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Voice #%d creatie gefaald.\"\r\nMsg_Sound_Init_Soundcard                = \" - Initialiseren geluidskaart @ %d Hz..\"\r\nMsg_Sound_Init_Soundcard_No             = \"Kan audio niet initialiseren: geen geluidskaart geselecteerd!\"\r\nMsg_Sound_Init_SN76496                  = \" - SN76496 digitale emulator:\"\r\nMsg_Sound_Init_YM2413_Digital           = \" - YM2413 digitale emulator:\"\r\nMsg_Sound_Stream_Error                  = \"Sound buffer stop. herstarten van stream.\"\r\nMsg_Sound_Volume_Changed                = \"Volume gewijzigd naar %d%%.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Laden van MEKA.THM (interface themes)... \"\r\nMsg_Theme_Error_Not_Enough              = \"niet genoeg themes gevonden! bekijk MEKA.THM bestand her installeer\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"On line %d: Geen theme name gespecificeerd om waarde op te slaan!\"\r\nMsg_Theme_Error_Syntax                  = \"Op regel %d: syntax error!\"\r\nMsg_Theme_Error_Attribute_Defined       = \"Op regel %d: attribuut al gedefinieerd!\"\r\nMsg_Theme_Error_Out_of_Bound            = \"Op regel %d: waarde niet toegestaan!\"\r\nMsg_Theme_Error_Theme_Missing_Data      = \"Theme \\\"%s\\\" is missing data. Will be disabled.\"\r\nMsg_Theme_Error_BG_Big                  = \"Achtergrond plaatje naar klein om te passen met een integere schaling!\"\r\nMsg_Theme_Error_BG                      = \"Error bij het laden van het plaatje wat bij het theme hoort!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Laden van ROM.. \"\r\nMsg_LoadROM_Success                     = \"Succesvol geladen %s\"\r\nMsg_LoadDisk_Success                    = \"Succesvol geladen %s als een floppy disk\"\r\nMsg_LoadROM_Comment                     = \"Commentaar: %s\"\r\nMsg_LoadROM_SMSGG_Mode_Comment          = \"Dit is een Game Gear rom die wordt geemuleerd in Master System modus.\"\r\nMsg_LoadROM_Warning                     = \"-Waarschuwing-\"\r\nMsg_LoadROM_Bad_Dump_Long               = \"Deze ROM staat bekend als een slechte dump.\\nEr bestaat een kans dat deze niet goed werkt. Download SMS Checker om deze rom te controleren (http://www.smspower.org/maxim/smschecker/).\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Waarschuwing - Deze ROM staat bekend als een slechte dump.\"\r\nMsg_LoadROM_Product_Num                 = \"Produkt Nummer: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Hoofd-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Naam: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Versie: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Datum: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Auteur: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Release Notities: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Onbekend>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Fout>\"\r\nMsg_LoadROM_Reload_Reloaded             = \"Rom geladen ROM.\"\r\nMsg_LoadROM_Reload_No_ROM               = \"Geen ROM om te herladen!\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Laad ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Drive %c]\"\r\nMsg_FileBrowser_Load                    = \"Laad\"\r\nMsg_FileBrowser_Close                   = \"Sluit\"\r\nMsg_FileBrowser_LoadNames               = \"Laad Namen\"\r\nMsg_FileBrowser_ReloadDir               = \"Herlaad Dir\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"FM Instrumenten Editor\"\r\nMsg_FM_Editor_Enabled                   = \"FM Voice Editor aan\"\r\nMsg_FM_Editor_Disabled                  = \"FM Voice Editor uit\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Frameskip waarde gezet op: Automatisch (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Frameskip waarde gezet op: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"FPS teller ingeschakeld\"\r\nMsg_FPS_Counter_Disabled                = \"FPS teller uitgeschakeld\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"LOG optie heeft een bestandsnaam nodig!\"\r\nMsg_Log_Session_Start                   = \"-- Logge sessie gestart op %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"LAAD optie heeft een savestate nummer nodig!\"\r\nMsg_Load_Error                          = \"Error openen van %s!\"\r\nMsg_Load_Not_Valid                      = \"File %s is geen valide %s savegame!\"\r\nMsg_Load_Success                        = \"State geladen van %s\"\r\nMsg_Load_Version                        = \"%s is een niet ondersteunde savegame versie!\"\r\nMsg_Load_Wrong_System                   = \"%s is geen savegame voor dit systeem!\"\r\nMsg_Load_Massage                        = \"bestand is in MSD formaat - omzetten\"\r\nMsg_Save_Not_in_BIOS                    = \"Kan niet opslaan wanneer de BIOS draait\"\r\nMsg_Save_Error                          = \"Error bij het schrijven naar %s!\"\r\nMsg_Save_Success                        = \"Status opgeslagen naar %s\"\r\nMsg_Save_Slot                           = \"Dit savegame slot is: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Opties\"\r\nMsg_Options_Close                       = \"Sluit\"\r\nMsg_Options_BIOS_Enable                 = \"Laat BIOS logo zien.\"\r\n;Msg_Options_BIOS_Enable                 = \"laat intern bios logo zien als het op het systeem zit.\"\r\nMsg_Options_DB_Display                  = \"Laat namen, vlaggen en iconen zien uit de database.\"\r\nMsg_Options_Product_Number              = \"Laat product nummer zien uit de database.\"\r\n;Msg_Options_Product_Number              = \"laat spel produkt nummer zien als het in de database staat.\"\r\nMsg_Options_Bright_Palette              = \"helder kleurenpalet voor Master System / Game Gear.\"\r\nMsg_Options_Allow_Opposite_Directions   = \"Toestaan indrukken van tegenovergestelde joypad richtingen.\"\r\nMsg_Options_Load_Close                  = \"sluit bestandsselecteerder na openen.\"\r\nMsg_Options_Load_FullScreen             = \"Schakel over naar fullscreen na een spel te laden.\"\r\n;Msg_Options_VFN_Support                 = \"Laat lange bestandsnamen zien en landen vlaggen.\"\r\nMsg_Options_FullScreen_Messages         = \"laat berichten zien in fullscreen mode.\"\r\nMsg_Options_GUI_VSync                   = \"Wacht for VSync in interface mode.\"\r\nMsg_Options_Capture_Crop_Align          = \"Screenshots automatisch aanpassen tot 8x8 formaat.\"\r\nMsg_Options_NES_Enable                  = \"Mario is geen dikke loodgieter.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Taal gezet op %s\"\r\nMsg_Language_Set_Warning                = \"Notitie: het is aanbevolen meka te herstarten om er zeker van te zijn dat alle text wordt geupdated.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"geStart dumping geluid naar %s\"\r\nMsg_Sound_Dumping_Stop                  = \"geStopt dumping geluid naar (%2.02f seconden gelogd)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"niet mogelijk een valide bestandsnaam te vinden om de geluiddump in te laten!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Error bij het openen van het ouput bestand %s voor het dumpen!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"VGM dumps zullen nu beter met frames werken (kleinere bestanden, stemmen overslaan)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"VGM dumps zullen nu beter met samples zijn (grotere bestanden, stemmen ook dumpen)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(VGM dumpen moet opnieuw opgestart worden om gebruik te maken van de nieuwe accuraatheid)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"BESTAND\"\r\nMsg_Menu_Main_LoadROM                   = \"Laad ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Haal ROM eruit\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Status opslaan\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Status laden\"\r\nMsg_Menu_Main_Options                   = \"Opties..\"\r\nMsg_Menu_Main_Language                  = \"Taal\"\r\nMsg_Menu_Main_Quit                      = \"Stoppen\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Enabled                  = \"Ingeschakeld..\"\r\nMsg_Menu_Debug_ReloadROM                = \"Herlaad ROM\"\r\nMsg_Menu_Debug_Dump                     = \"Opslaan\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MACHINE\"\r\nMsg_Menu_Machine_Power                  = \"Power\"\r\nMsg_Menu_Machine_Power_On               = \"Aan\"\r\nMsg_Menu_Machine_Power_Off              = \"Uit\"\r\nMsg_Menu_Machine_Region                 = \"Land\"\r\nMsg_Menu_Machine_Region_Export          = \"Europees/US\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japans\"\r\nMsg_Menu_Machine_TVType                 = \"TV Type\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Harde Pause\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Harde Reset\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Volledig scherm\"\r\nMsg_Menu_Video_Themes                   = \"Thema's\"\r\nMsg_Menu_Video_Blitters                 = \"Blitters\"\r\nMsg_Menu_Video_Layers                   = \"Lagen\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Achtergrond\"\r\nMsg_Menu_Video_Flickering               = \"Sprite flikkeren\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Automatisch\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Ja\"\r\nMsg_Menu_Video_Flickering_No            = \"Nee\"\r\nMsg_Menu_Video_3DGlasses                = \"3-D Bril\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Aan\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Laat beide kanten zien\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Laat linkerkant zien\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Laat rechterkant zien\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Gebruik bril op COM Poort\"\r\nMsg_Menu_Video_ScreenCapture                  = \"Opnemen\"\r\nMsg_Menu_Video_ScreenCapture_Capture    = \"Scherm opnemen\"\r\nMsg_Menu_Video_ScreenCapture_CaptureRepeat = \"Scherm opnemen (Alle)\"\r\nMsg_Menu_Video_ScreenCapture_IncludeGUI       = \"GUI Meenemen in opname\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"GELUID\"\r\nMsg_Menu_Sound_FM                       = \"FM Unit\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Aan\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Uit\"\r\nMsg_Menu_Sound_FM_Editor                = \"Instrumenten Editor\"\r\nMsg_Menu_Sound_Volume                   = \"Volume\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Mute\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Rate\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Kanalen\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Toon %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Geluiden\"\r\nMsg_Menu_Sound_Capture                     = \"Opslaan\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"WAV Start\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"WAV Stop\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"VGM Start\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"VGM Stop\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM Sample Accuratie\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"CONTROLS\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Pistool\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddle Controller\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Teken tablet (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Sega Toetsenbord\"\r\nMsg_Menu_Inputs_RapidFire               = \"Snel vuren\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Speler %d Knop %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Configuratie..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"WERKSET\"\r\nMsg_Menu_Tools_Messages                 = \"Berichten..\"\r\nMsg_Menu_Tools_Palette                  = \"Kleuren Palet..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Tegel bekijker..\"\r\nMsg_Menu_Tools_TilemapViewer            = \"Tegelkaart Viewerv\r\nMsg_Menu_Tools_CheatFinder              = \"Cheat Finder..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Technische Info..\"\r\nMsg_Menu_Tools_MemoryEditor             = \"Geheugen Editor..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"HELP\"\r\nMsg_Menu_Help_Documentation             = \"Documentatie..\"\r\nMsg_Menu_Help_Compat                    = \"Compatibiliteits lijst..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Mp spellen lijst..\"\r\nMsg_Menu_Help_Changes                   = \"Veranderingen..\"\r\nMsg_Menu_Help_Debugger\t\t\t\t\t= \"Debugger..\"\r\nMsg_Menu_Help_About                     = \"Over..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Español]\r\nWIP\r\n; Translation by Bazathlon (bazathlon AT wanadoo DOT es)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Bienvenido a %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - ¡8-bit o muere!\"\r\nMsg_Quit                                = \"Good night, brave warrior. Good night, monster-land....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"Acerca de...\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"por %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Failed                              = \"¡Fallo!\"\r\nMsg_Error_Base                          = \"Error: %s\"\r\nMsg_Error_Error                         = \"Error fatal: algo debe ir mal.\"\r\nMsg_Error_Memory                        = \"No hay suficiente memoria\"\r\nMsg_Error_Param                         = \"¡El parametro \\\"%s\\\" es invalido!\\n\"\r\nMsg_Error_Syntax                        = \"¡Error de sintaxis!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Inhabilitado el modo de video deseado (%dx%d).\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Archivo no encontrado\"\r\nMsg_Error_File_Read                     = \"No se puede leer del archivo\"\r\nMsg_Error_File_Empty                    = \"Archivo vacio\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Esta version no soporta archivos ZIP\"\r\nMsg_Error_ZIP_Loading                   = \"Incapaz de leer archivos ZIP\"\r\nMsg_Error_ZIP_Internal                  = \"Error interno durante la carga del archivo ZIP\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Error abriendo el directorio\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Resetea el juego para que los cambios surtan efecto\"\r\nMsg_No_ROM                              = \"Ninguna ROM fue cargada\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Iniciando Allegro..\"\r\nMsg_Init_GUI                            = \"Iniciando GUI..\"\r\nMsg_Init_Completed                      = \"[PREPARADO]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Pantalla capturada a %s\"\r\nMsg_Capture_Error                       = \"Incapaz de crear captura de pantalla\"\r\nMsg_Capture_Error_File                  = \"Incapaz de encontrar un nombre de fichero valido para salvar la pantalla capturada\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"Cargada SRAM desde disco (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Incapaz de cargar SRAM desde disco\"\r\nMsg_SRAM_Wrote                          = \"Escribio SRAM a disco (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Incapaz de escribir SRAM a disco (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Reseteando 93c46\"\r\nMsg_93c46_Loaded                        = \"Cargado datos del 93c46 EEPROM desde disco (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Incapaz de cargar datos del 93c46 EEPROM desde disco\"\r\nMsg_93c46_Wrote                         = \"Escribio datos del 93c46 EEPROM a disco (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Incapaz de escribir datos del 93c46 EEPROM a disco (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"Tipo de TV es ahora %s\"\r\nMsg_TVType_Info_Speed                   = \"(Velocidad original es %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Cargando MEKA.BLT (video modes / blitters)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Insuficientes blitters encontrados! Comprueba el archivo MEKA.BLT o reinstala MEKA\"\r\nMsg_Blitters_Error_Not_Found            = \"Blitter no encontrado\"\r\nMsg_Blitters_Error_Missing              = \"On line %d: Sin nombre definido de blitter para almacenar valores!\"\r\nMsg_Blitters_Error_Unrecognized         = \"On line %d: Variable irreconocible\"\r\nMsg_Blitters_Set                        = \"Usando \\\"%s\\\" blitter a pantalla completa\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Modo Fat plumber activado\"\r\nMsg_NES_Sucks                           = \"Error fatal: al usuario le gusta Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Mapeado no soportado: %d. El juego no deberia funcionar\"\r\nMsg_NES_Deny_Facts                      = \"Puedes negar los hechos.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Iniciando debugger.. \"\r\nMsg_Debug_Welcome                       = \"Bienvenido al MEKA Debugger!\"\r\nMsg_Debug_Not_Available                 = \"Debugger no disponible en esta version!\"\r\nMsg_Debug_Trap_Read                     = \"A PC:%04X - Leido desde %04X\"\r\nMsg_Debug_Trap_Write                    = \"A PC:%04X - Escrito %02X a %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"A PC:%04X - Puerto [%02X] Leido\"\r\nMsg_Debug_Trap_Port_Write               = \"A PC:%04X - Puerto [%02X] Escrito %02X\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Datos de dumpeo ahora estaran hechos en codigo ASCII\"\r\nMsg_DataDump_Mode_Raw                   = \"Datos de dumpeo ahora estaran hechos en modo Raw.\"\r\nMsg_DataDump_Error                      = \"Error creando archivo a dumpear %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Sin memoria en placa para dumpear!\"\r\nMsg_DataDump_Error_Palette              = \"Sin paleta para dumpear!\"\r\nMsg_DataDump_Error_Sprites              = \"Sin sprites para dumpear!\"\r\nMsg_DataDump_Main                       = \"Dumpeo %s (%d %s) en %s modo\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Documentación\"\r\nMsg_Doc_File_Error                      = \"Incapaz de abrir documentacion.\"\r\nMsg_Doc_Enabled                         = \"Documentacion mostrandose.\"\r\nMsg_Doc_Disabled                        = \"No hay mas documentacion.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite flickering sera manejado automacicamente.\"\r\nMsg_Flickering_Yes                      = \"Emulacion de Sprite flickering activada.\"\r\nMsg_Flickering_No                       = \"Emulacion de Sprite flickering desactivada.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Refresco de fondo desactivada\"\r\nMsg_Layer_BG_Enabled                    = \"Refresco de fondo activada\"\r\nMsg_Layer_Spr_Disabled                  = \"Refresco de sprites desactivada\"\r\nMsg_Layer_Spr_Enabled                   = \"Refresco de sprites activada\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Comando de lectura de disco desconocido %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Comando de escritura en disco desconocido %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Imagen de disco es mas grande de lo esperado (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Datos adicionales seran ignorados\"\r\nMsg_FDC765_Disk_Too_Small1              = \"La imagen del disco es más pequeña de lo esperado (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Datos perdidos serán asumidos como vacíos\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Paletas\"\r\nMsg_Palette_Disabled                    = \"Visor de paletas desactivado\"\r\nMsg_Palette_Enabled                     = \"Visor de paletas activado\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Mensajes\"\r\nMsg_Message_Disabled                    = \"Caja de mensajes desactivada\"\r\nMsg_Message_Enabled                     = \"Caja de mensajes activada\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Información técnica\"\r\nMsg_TechInfo_Disabled                   = \"Caja de informacion tecnica desativada\"\r\nMsg_TechInfo_Enabled                    = \"Caja de informacion tecnica activada\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Visor de retales\"\r\nMsg_TilesViewer_Disabled                = \"Visor de retales desactivado\"\r\nMsg_TilesViewer_Enabled                 = \"Visor de retales activado\"\r\nMsg_TilesViewer_Tile                    = \"Retal %d ($%X) @ %s\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Fuego rapido activado para jugador %d boton %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Fuego rapido desactivado para jugador %d boton %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"Emulacion de la unidad FM (YM-2413 chipset) activada\"\r\nMsg_FM_Disabled                         = \"Emulacion de la unidad FM (YM-2413 chipset) desactivada\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"La maquina emulada es ahora europea/americana\"\r\nMsg_Country_JAP                         = \"La maquina meulada es ahora japonesa\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Cargando MEKA.PAT (parches)... \"\r\n;Msg_Patch_Missing                       = \"On line %d: No hay suma de comprobaciones definidas para esta instruccion\"\r\n;Msg_Patch_Unrecognized                  = \"On line %d: Instruccion no reconocida\"\r\n;Msg_Patch_Out_of_Bound                  = \"Durante el parcheo de la ROM: intentando escribir fuera de limites, en la positcion $%02X. Abortando parcheo\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"Emulacion de gafas 3D activada\"\r\nMsg_Glasses_Disabled                    = \"Emulacion de gafas 3D desactivada\"\r\nMsg_Glasses_Show_Both                   = \"Efecto 3D mantenido tal como es\"\r\nMsg_Glasses_Show_Left                   = \"Efecto 3D desactivado por mostrar solo el lado izquierdo\"\r\nMsg_Glasses_Show_Right                  = \"Efecto 3D desactivado por mostrar solo el lado derecho\"\r\nMsg_Glasses_Com_Port                    = \"Emulacion de gafas 3D activada a traves del puerto COM %d.\"\r\n;Msg_Glasses_Com_Port2                   = \"(editar MEKA.CFG para cambiar el puerto de comunicacion)\"\r\nMsg_Glasses_Unsupported                 = \"Este juego parece no soportar gafas 3D\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Iniciando joystick... \"\r\nMsg_Inputs_Joy_Init_None                = \"ninguno encontrado.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d encontrado.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Error calibrando joystick. Abortando.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Periferico de entrada: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Periferico de entrada: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Periferico de entrada: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Periferico de entrada: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Periferico de entrada: TV Oekaki Graphic Board\"\r\nMsg_Inputs_Play_Digital                 = \"Control con dispositivo de entrada digital\"\r\nMsg_Inputs_Play_Mouse                   = \"Control con dispositivo de entrada analogico (raton)\"\r\nMsg_Inputs_Play_Pen                     = \"Control de pluma con raton\\nboton derecho simula quitando la pluma de la tableta\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Configuración de entrada\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Cargando MEKA.INP (definicion de rutas de entrada)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Insuficientes caminos de entrada encontrados! Comprueba el archivo MEKA.INP o reinstala MEKA\"\r\nMsg_Inputs_Src_Missing                  = \"On line %d: Sin camino de entrada definido para almacenar valores\"\r\nMsg_Inputs_Src_Equal                    = \"On line %d: Señal de equilibrio perdida para asignamiento de variable\"\r\nMsg_Inputs_Src_Unrecognized             = \"On line %d: Variable irreconocible \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"On line %d: Error de sintaxis en parametro de variable!\"\r\nMsg_Inputs_Src_Inconsistency            = \"On line %d: Inconsistencia con la configuracion previa!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Ahora presione la tecla que quiera asignar a esta accion\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Accion asignada a la tecla \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Ahora presione el boton/eje que quiera asignar a esta accion\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Accion asignada al control del joypad %i, eje %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Accion asignada al boton de joypad %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Ahora presione el boton que quiera asignar a esta accion\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Accion asignada al boton de raton %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Lo siento - el eje de raton no ha podido ser cambiado\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Asignamiento cancelado!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Emulacion de maquina pausada\"\r\nMsg_Machine_Resume                      = \"Emulacion de maquina reanudada\"\r\nMsg_Machine_Reset                       = \"Maquina reseteada\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\n;Msg_VFN_Loading                         = \"Cargando MEKA.VFN (nombres de archivo virtuales)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Cargando MEKA.NAM (nombres de juegos)... \"\r\nMsg_DB_Name_Default                     = \"Pantalla de juego\"\r\nMsg_DB_Name_NoCartridge                 = \"No hay cartucho\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Cargando %s (configuracion)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Cargando MEKA.DAT (recursos)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatal: Driver de maquina desconocido!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\nMsg_OverDump                            = \"Esta ROM contiene %d veces los datos necesarios.\\nGet \\\"SMS Checker\\\" para limpiarlo.\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Iniciando sistema de sonido...\"\r\nMsg_Sound_Init_Error_Audio              = \" - Error abriendo sistema de audio. Intente una tarjeta diferente y/o ratio de frecuencia.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER variable no encontrada, desactivando sonido FM!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - BLASTER variable no cuenta con direccion (A=xxx), desactivando sonido FM!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Voces iniciacion fallo.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Voces #%d creacion fallo.\"\r\nMsg_Sound_Init_Soundcard                = \" - Iniciando tarjeta de sonido @ %d Hz...\"\r\nMsg_Sound_Init_Soundcard_No             = \"No se pudo iniciar el audio: no hay tarjeta de sonido seleccionada!\"\r\n;Msg_Sound_Init_SN76496_Ok               = \" - SN76496 emulador: OK\"\r\n;Msg_Sound_Init_YM2413_Ok                = \" - YM2413 emulador: OK\"\r\nMsg_Sound_Stream_Error                  = \"Buffer de sonido detenido. Reempezando stream.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Cargando MEKA.THM (temas de interfaz)... \"\r\nMsg_Theme_Error_Not_Enough              = \"No hay suficientes temas encontrados! Comprueba el archivo MEKA.THM o intenta reinstalando MEKA.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"On line %d: Sin nombre de tema definido para almacenar valores!\"\r\nMsg_Theme_Error_BG_Big                  = \"Dibujo de fondo demasiado pequeño para agrandar con scaling integrado!\"\r\nMsg_Theme_Error_BG                      = \"Error cargando dibujo asociado con juego!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Cargando ROM... \"\r\nMsg_LoadROM_Success                     = \"Satisfactoriamente cargado %s\"\r\nMsg_LoadDisk_Success                    = \"Satisfactoriamente cargado %s como un disco flexible\"\r\nMsg_LoadROM_Comment                     = \"Comentario: %s\"\r\nMsg_LoadROM_Warning                     = \"-Advertencia-\"\r\n;Msg_LoadROM_Bad_Dump_Long               = \"This ROM parece estar mal dumpeada.\\nPosibilidades de que no funcionara propiamente.\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Advertencia - Esta ROM parece estar mal dumpeada.\"\r\nMsg_LoadROM_Product_Num                 = \"Numero de producto: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Header-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Nombre: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Version: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Fecha: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Autor: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Nota de edicion: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Desconocido>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Error>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Cargar ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Unidad %c]\"\r\nMsg_FileBrowser_Load                    = \"Cargar\"\r\nMsg_FileBrowser_Close                   = \"Cerrar\"\r\nMsg_FileBrowser_LoadNames               = \"Cargar nombres\"\r\nMsg_FileBrowser_ReloadDir               = \"Recargar Dir\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"Editor FM\"\r\nMsg_FM_Editor_Enabled                   = \"Editor de voz FM activado\"\r\nMsg_FM_Editor_Disabled                  = \"Editor de voz FM activado\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Frameskip valor establecido a: Automatico (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Frameskip valor establecido a: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"Contador de FPS habilitado\"\r\nMsg_FPS_Counter_Disabled                = \"Contador de FPS deshabilitado\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"LOG de opciones necesita un nombre de archivo!\"\r\nMsg_Log_Session_Start                   = \"-- Sesion de LOG empezada en %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"La opcion LOAD necesita un numero de estado salvado\"\r\nMsg_Load_Error                          = \"Error abriendo %s!\"\r\nMsg_Load_Not_Valid                      = \"Archivo %s no es un valido %s juego salvado!\"\r\nMsg_Load_Success                        = \"Stado cargado desde %s\"\r\nMsg_Load_Version                        = \"%s no es una version soportada de juego salvado!\"\r\nMsg_Load_Wrong_System                   = \"%s no es un juego salvado para esta sistema!\"\r\nMsg_Load_Massage                        = \"El archivo esta en formato MSD - convirtiendo\"\r\nMsg_Save_Not_in_BIOS                    = \"No se puede salvar mientras se ejecuta la BIOS!\"\r\nMsg_Save_Error                          = \"Error escribiendo en %s!\"\r\nMsg_Save_Success                        = \"Stado salvado en %s\"\r\nMsg_Save_Slot                           = \"Slot de juego salvado actual es: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Opciones\"\r\nMsg_Options_Close                       = \"Cerrar\"\r\n;Msg_Options_BIOS_Enable                 = \"Mostrar logo de BIOS interna si es posible.\"\r\n;Msg_Options_Product_Number              = \"Mostrar numero de producto del juego si es posible.\"\r\n;Msg_Options_Bright_Palette              = \"Paleta de brillo para Master System / Game Gear.\"\r\nMsg_Options_Load_Close                  = \"Cerrar explorador despues de cargar un juego.\"\r\nMsg_Options_Load_FullScreen             = \"Cambiar a pantalla completa tras cargar un juego.\"\r\n;Msg_Options_VFN_Support                 = \"Mostrar nombre largo de fichero y pais.\"\r\nMsg_Options_FullScreen_Messages         = \"Mostrar mensajes en modo pantalla completa\"\r\nMsg_Options_GUI_VSync                   = \"Esperar VSync en modo interfaz.\"\r\nMsg_Options_NES_Enable                  = \"Mario no es un fontanero gordo.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Idioma establecido al %s\"\r\nMsg_Language_Set_Warning                = \"Nota: se recomienda que reinicie MEKA para actualizar textos.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Empezado salida de sonido dumeado a %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Detenido salida de sonido dumpeado (%2.02f segundos grabados)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Incapaz de encontrar un nombre de fichero valido para salida de sonido dumpeado!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Error abriendo archivo de entrada %s para dumpeo!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"El dumpeo VGM estará ahora con los frames precisos (archivos mas pequeños, voces excluidas)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"El dumpeo VGM estará ahora con el sample preciso (archivos mas grandes, voces dumpeadas)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(El dumpeo VGM tendrá que reempezar para tener en cuenta la nueva precisión)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"PRINCIPAL\"\r\nMsg_Menu_Main_LoadROM                   = \"Cargar ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Liberar ROM\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Salvar estado\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Cargar estado\"\r\nMsg_Menu_Main_Options                   = \"Opciones..\"\r\nMsg_Menu_Main_Language                  = \"Idioma\"\r\nMsg_Menu_Main_Quit                      = \"Salir\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Dump                     = \"Dumpeo\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MAQUINA\"\r\nMsg_Menu_Machine_Power                  = \"Power\"\r\nMsg_Menu_Machine_Power_On               = \"On\"\r\nMsg_Menu_Machine_Power_Off              = \"Off\"\r\nMsg_Menu_Machine_Region                 = \"Pais\"\r\nMsg_Menu_Machine_Region_Export          = \"Europeo/USA\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japonés\"\r\nMsg_Menu_Machine_TVType                 = \"Tipo TV\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Pausa dura\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Reset duro\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Fullscreen\"\r\nMsg_Menu_Video_Themes                   = \"Temas\"\r\nMsg_Menu_Video_Blitters                 = \"Blitters\"\r\nMsg_Menu_Video_Layers                   = \"Capas\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Fondo\"\r\nMsg_Menu_Video_Flickering               = \"Sprite flickering\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Si\"\r\nMsg_Menu_Video_Flickering_No            = \"No\"\r\nMsg_Menu_Video_3DGlasses                = \"Gafas 3-D\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Habilitado\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Mostrar ambos lados\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Mostrar lado izqdo.\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Mostrar lado dcho.\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Usa gafas en el puerto COM\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"SONIDO\"\r\nMsg_Menu_Sound_FM                       = \"Unidad FM\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Habilitdo\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Desactivado\"\r\nMsg_Menu_Sound_FM_Editor                = \"Editor de instrumentos\"\r\nMsg_Menu_Sound_Volume                   = \"Volumen\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Silencio\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Frecuencia\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Canales\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Tono %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Ruidos\"\r\nMsg_Menu_Sound_Capture                     = \"Dumpeo\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"Empezar WAV\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"Parar WAV\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"Empezar VGM\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"Parar VGM\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM Sample Accurate\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"ENTRADA\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Pad de control\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Tableta gráfica (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"TEclado Sega\"\r\nMsg_Menu_Inputs_RapidFire               = \"Fuego rápido\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Jugador %d Botón %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Configuración..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"UTILES\"\r\nMsg_Menu_Tools_Messages                 = \"Mensajes..\"\r\nMsg_Menu_Tools_Palette                  = \"Paletas..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Visor de Retales..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Tech Info..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"AYUDA\"\r\nMsg_Menu_Help_Documentation             = \"Documentación..\"\r\nMsg_Menu_Help_Compat                    = \"Lista de compatibilidad..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Lista de juegos multijugador..\"\r\nMsg_Menu_Help_Changes                   = \"Lista de cambios..\"\r\nMsg_Menu_Help_About                     = \"Acerca de..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Polski]\r\nWIP\r\n; Translation by thr (r AT sledinmay DOT com)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Witaj w %s (c) %s\"\r\nMsg_Window_Title                        = \"MEKA - W Pikslach Ufnosc Pokladamy!\"\r\nMsg_Quit                                = \"Dobrej nocy, dzielny woju. Dobrej nocy, Kraino Potworow...\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"O Meka...\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"by %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Ok                                  = \"Ok\"\r\nMsg_Failed                              = \"Niepowodzenie!\"\r\nMsg_Error_Base                          = \"Blad: %s\"\r\nMsg_Error_Error                         = \"Fatalny blad: nie mozna ustalic typu bledu. Cos jest nie tak.\"\r\nMsg_Error_Memory                        = \"Za malo pamieci!\"\r\nMsg_Error_Param                         = \"Parametr \\\"%s\\\" jest bledny!\\n\"\r\nMsg_Error_Syntax                        = \"Blad skladni!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Nie mozna ustawic zadanego trybu graficznego (%dx%d).\"\r\nMsg_Error_Video_Mode_Back_To_GUI        = \"Przelaczam na powrot do GUI.\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Nie znaleziono pliku!\"\r\nMsg_Error_File_Read                     = \"Nie mozna przeczytac pliku!\"\r\nMsg_Error_File_Empty                    = \"Plik jest pusty!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Ta wersja nie obsluguje plikow ZIP!\"\r\nMsg_Error_ZIP_Loading                   = \"Nie mozna przeczytac pliku ZIP!\"\r\nMsg_Error_ZIP_Internal                  = \"Wewnetrzny blad podczas wczytywania pliku ZIP!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Blad podczas otwierania katalogu!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Zresetuj gre by wprowadzic zmiany.\"\r\nMsg_No_ROM                              = \"Nie wczytano ROM-u!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Inicjalizacja Allegro... \"\r\nMsg_Init_GUI                            = \"Inicjalizacja GUI... \"\r\nMsg_Init_Completed                      = \"[GOTOWY]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\nMsg_Setup_Running                       = \"Uruchamianie konfiguratora... \"\r\nMsg_Setup_Setup                         = \"Konfiguracja\"\r\nMsg_Setup_Video_Driver                  = \"Sterownik ekranu:\"\r\nMsg_Setup_Video_DisplayMode             = \"Tryb graficzny:\"\r\nMsg_Setup_SampleRate_Select             = \"Czestotliwosc probkowania:\"\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Ekran zrzucony do %s\"\r\nMsg_Capture_Error                       = \"Nie udalo sie zrzucic ekranu!\"\r\nMsg_Capture_Error_File                  = \"Nie udalo sie znalezc nazwy pliku do zapisania zrzutu ekranu!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"Wczytano SaveRAM z dysku (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Nie udalo sie wczytac SaveRAM-u z dysku\"\r\nMsg_SRAM_Wrote                          = \"Zapisano SaveRAM na dysk (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Nie udalo sie zapisac SaveRAM-u na dysk (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Resetowanie 93c46\"\r\nMsg_93c46_Loaded                        = \"Wczytano dane 93c46 EEPROM z dysku (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Nie udalo sie wczytac danych 93c46 EEPROM z dysku\"\r\nMsg_93c46_Wrote                         = \"Zapisano dane 93c46 EEPROM na dysk (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Nie udalo sie zapisac danych 93c46 EEPROM na dysk (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"Typ TV to teraz %s\"\r\nMsg_TVType_Info_Speed                   = \"(Oryginalna predkosc to %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Wczytywanie MEKA.BLT (tryby graficzne / blittery)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Nie znaleziono dosc blitterow! Sprawdz plik MEKA.BLT albo przeinstaluj.\"\r\nMsg_Blitters_Error_Not_Found            = \"Nie znaleziono blittera!\"\r\nMsg_Blitters_Error_Missing              = \"W wierszu %d: Nie zdefiniowano nazwy blittera do przechowania wartosci!\"\r\nMsg_Blitters_Error_Unrecognized         = \"W wierszu %d: Nierozpoznana zmienna!\"\r\nMsg_Blitters_Error_Incorrect_Value      = \"W wierszu %d: Niewlasciwa wartosc!\"\r\nMsg_Blitters_Set                        = \"Uzywam blittera pelnoekranowego \\\"%s\\\".\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Uruchomiono tryb grubego hydraulika.\"\r\nMsg_NES_Sucks                           = \"Fatalny blad: uzytkownik lubi Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Niewspierany mapper: %d. Gra nie powinna dzialac.\"\r\nMsg_NES_Deny_Facts                      = \"Nie mozna przeczyc faktom.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Inicjalizacja debuggera... \"\r\nMsg_Debug_Welcome                       = \"Witaj w Debuggerze Meka!\"\r\nMsg_Debug_Not_Available                 = \"Debugger jest niedostepny w tej wersji!\"\r\nMsg_Debug_Trap_Read                     = \"W PC:%04X - Odczyt z %04X\"\r\nMsg_Debug_Trap_Write                    = \"W PC:%04X - Zapis %02X do %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"W PC:%04X - Port [%02X] Odczyt\"\r\nMsg_Debug_Trap_Port_Write               = \"W PC:%04X - Port [%02X] Zapis %02X\"\r\nMsg_Debug_Symbols_Loaded                = \"Wczytano %d symboli z \\\"%s\\\".\"\r\nMsg_Debug_Symbols_Error                 = \"Blad przy wczytywaniu symboli \\\"%s\\\":\"\r\nMsg_Debug_Symbols_Error_Line            = \"W wierszu %d: nierozpoznana skladnia.\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Zrzuty danych beda teraz tworzone w trybie ASCII.\"\r\nMsg_DataDump_Mode_Raw                   = \"Zrzuty danych beda teraz tworzone w trybie surowym.\"\r\nMsg_DataDump_Error                      = \"Blad tworzenia pliku zrzutu %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Nie ma wczytanej pamieci, ktora mozna zrzucic!\"\r\nMsg_DataDump_Error_Palette              = \"Nie ma palety, ktora mozna zrzucic!\"\r\nMsg_DataDump_Error_Sprites              = \"Nie ma duszkow, ktore mozna zrzucic!\"\r\nMsg_DataDump_Main                       = \"Zrzucono %s (%d %s) w trybie %s\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Dokumentacja\"\r\nMsg_Doc_File_Error                      = \"Nie mozna otworzyc dokumentacji!\"\r\nMsg_Doc_Enabled                         = \"Dokumentacja pokazuje sie.\"\r\nMsg_Doc_Disabled                        = \"Dokumentacji juz nie ma.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Migotanie duszkow bedzie obslugiwane automatycznie.\"\r\nMsg_Flickering_Yes                      = \"Wlaczono emulacje migotania duszkow.\"\r\nMsg_Flickering_No                       = \"Wylaczono emulacje migotania duszkow.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Wylaczono odswiezanie tla\"\r\nMsg_Layer_BG_Enabled                    = \"Wlaczono odswiezanie tla\"\r\nMsg_Layer_Spr_Disabled                  = \"Wylaczono odswiezanie duszkow\"\r\nMsg_Layer_Spr_Enabled                   = \"Wlaczono odswiezanie duszkow\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Nieznane polecenie odczytu z dysku %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Nieznane polecenie zapisu na dysk %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Obraz dysku jest wiekszy, niz byc powinien (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Dodatkowe dane zostana zignorowane\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Obraz dysku jest mniejszy, niz byc powinien (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Brakujace dane zostana uznane za puste\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Paleta\"\r\nMsg_Palette_Disabled                    = \"Wylaczono przegladarke palet\"\r\nMsg_Palette_Enabled                     = \"Wlaczono przegladarke palet\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Komunikaty\"\r\nMsg_Message_Disabled                    = \"Okno komunikatow wylaczone\"\r\nMsg_Message_Enabled                     = \"Okno komunikatow wlaczone\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Informacje techniczne\"\r\nMsg_TechInfo_Disabled                   = \"Okno informacji technicznych wylaczone\"\r\nMsg_TechInfo_Enabled                    = \"Okno informacji technicznych wlaczone\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Przegladarka komorek\"\r\nMsg_TilesViewer_Disabled                = \"Wylaczono przegladarke komorek\"\r\nMsg_TilesViewer_Enabled                 = \"Wlaczono przegladarke komorek\"\r\nMsg_TilesViewer_Tile                    = \"Komorka %d ($%X) @ %s\"\r\n\r\n; Memory Editor --------------------------------------------------------------\r\nMsg_MemoryEditor_BoxTitle\t\t\t\t= \"Edytor pamieci\"\r\nMsg_MemoryEditor_Disabled\t\t\t\t= \"Edytor pamieci wylaczony\"\r\nMsg_MemoryEditor_Enabled\t\t\t\t= \"Edytor pamieci wlaczony\"\r\nMsg_MemoryEditor_WriteZ80_Unable\t\t= \"W tej chwili nie mozna zapisac do przestrzeni adresowej Z80!\"\r\nMsg_MemoryEditor_Address_Out_of_Bound\t= \"Adres %s jest poza zakresem %s!\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Autofire wlaczony dla gracza %d przycisku %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Autofire wylaczony dla gracza %d przycisku %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"Wlaczono emulacje jednostki FM (chipset YM-2413)\"\r\nMsg_FM_Disabled                         = \"Wylaczono emulacje jednostki FM (chipset YM-2413)\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Emulowana jest teraz maszyna Europejska/USA\"\r\nMsg_Country_JAP                         = \"Emulowana jest teraz maszyna Japonska\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Wczytuje MEKA.PAT (latki)... \"\r\nMsg_Patch_Missing                       = \"W wierszu %d: Nie zdefiniowano sumy kontrolnej, do ktorej odnosi sie polecenie!\"\r\nMsg_Patch_Unrecognized                  = \"W wierszu %d: Blad skladni lub nierozpoznane polecenie!\"\r\nMsg_Patch_Value_Not_a_Byte              = \"W wierszu %d: Wartosc %s nie pasuje do bajtu bez znaku!\"\r\nMsg_Patch_Out_of_Bound                  = \"Podczas latania %s: adres $%04X jest poza zakresem. Nie nalozono latki.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"Wlaczono emulacje okularow 3D\"\r\nMsg_Glasses_Disabled                    = \"Wylaczono emulacje okularow 3D\"\r\nMsg_Glasses_Show_Both                   = \"Efekt 3D utrzymany bez zmian.\"\r\nMsg_Glasses_Show_Left                   = \"Efekt 3D wylaczony. Pokazywana jest tylko lewa strona.\"\r\nMsg_Glasses_Show_Right                  = \"Efekt 3D wylaczony. Pokazywana jest tylko prawa strona.\"\r\nMsg_Glasses_Com_Port                    = \"Emulacja okularow 3D wlaczona przez port COM %d.\"\r\nMsg_Glasses_Com_Port2                   = \"(edytuj MEKA.CFG, by wybrac uzywany port COM)\"\r\nMsg_Glasses_Com_Port_Open_Error\t\t\t= \"Blad przy otwieraniu portu COM %d. Okulary 3D nie beda dzialac.\"\r\nMsg_Glasses_Unsupported                 = \"Wyglada na to, ze ta gra nie obsluguje okularow 3D.\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Inicjalizacja joysticka... \"\r\nMsg_Inputs_Joy_Init_None                = \"nie znaleziono.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d znaleziono.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Blad kalibracji joysticka. Przerywam.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Urzadzenie wejscia: Pad\"\r\nMsg_Inputs_LightPhaser                  = \"Urzadzenie wejscia: Pistolet swietlny\"\r\nMsg_Inputs_PaddleControl                = \"Urzadzenie wejscia: Pokretlo sterujace\"\r\nMsg_Inputs_SportsPad                    = \"Urzadzenie wejscia: Pad sportowy\"\r\nMsg_Inputs_GraphicBoard                 = \"Urzadzenie wejscia: Karta graficzna Terebi Oekaki\"\r\nMsg_Inputs_Play_Digital                 = \"Kontrola cyfrowym urzadzeniem wejscia\"\r\nMsg_Inputs_Play_Mouse                   = \"Kontrola analogowym urzadzeniem wejscia (mysz)\"\r\nMsg_Inputs_Play_Digital_Unrecommended   = \"Cyfrowe urzadzenie wejscia (np.: klawiatura) jest obslugiwane, ale NIE polecane\"\r\nMsg_Inputs_Play_Pen                     = \"Kontroluj pioro mysza\\nPPM symuluje oderwanie piora od tablicy\"\r\nMsg_Inputs_SK1100_Enabled               = \"Wlaczono emulacje klawiatury Sega (SK-1100)\"\r\nMsg_Inputs_SK1100_Disabled              = \"Wylaczono emulacje klawiatury Sega (SK-1100)\"\r\n\r\n; Input Configuration --------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Konfiguracja wejscia\"\r\nMsg_Inputs_Config_Peripheral_Click      = \"Kliknij, by wybrac urzadzenie\"\r\nMsg_Inputs_Config_Source_Enabled        = \"Wlaczone\"\r\nMsg_Inputs_Config_Source_Player         = \"Kontrola gracza %d\"\r\nMsg_Inputs_Config_Source_Emulate_Joypad = \"Emulowanie pada\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Wczytywanie MEKA.INP (definicje zrodel wejscia)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Nie znaleziono dosc zrodel wejscia! Sprawdz plik MEKA.INP albo przeinstaluj.\"\r\nMsg_Inputs_Src_Missing                  = \"W wierszu %d: nie zdefiniowano zrodla wejscia do zachowania wartosci!\"\r\nMsg_Inputs_Src_Equal                    = \"W wierszu %d: Brakuje znaku rownosci przy przyporzadkowaniu zmiennej!\"\r\nMsg_Inputs_Src_Unrecognized             = \"W wierszu %d: nierozpoznana zmienna \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"W wierszu %d: blad skladni parametru zmiennej!\"\r\nMsg_Inputs_Src_Inconsistency            = \"W wierszu %d: niezgodnosc z poprzednimi ustawieniami!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Wcisnij klawisz, ktory chcesz przyporzadkowac do tej czynnosci\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Czynnosc przyporzadkowana do klawisza \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Wcisnij przycisk/os, ktora chcesz przyporzadkowac do tej czynnosci\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Czynnosc przyporzadkowana do joysticka %i, osi %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Czynnosc przyporzadkowana do przycisku pada %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Wcisnij przycisk, ktory chcesz przyporzadkowac do tej czynnosci\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Czynnosc przyporzadkowana do przycisku myszy %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Osi myszy nie mozna zmienic\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Anulowano przyporzadkowanie!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Wstrzymano emulacje maszyny\"\r\nMsg_Machine_Resume                      = \"Wznowiono emulacje maszyny\"\r\nMsg_Machine_Reset                       = \"Reset maszyny\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\nMsg_FDB_Loading                         = \"Wczytuje MEKA.FDB (baza danych nazw plikow)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Wczytywanie MEKA.NAM (nazwy gier)... \"\r\nMsg_DB_Name_Default                     = \"Ekran gry\"\r\nMsg_DB_Name_NoCartridge                 = \"Brak kartridza\"\r\nMsg_DB_SyntaxError                      = \"W wierszu %d: Blad skladni!\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Wczytywanie %s (konfiguracja)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Wczytywanie MEKA.DAT (zasoby)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatalny blad: Nieznany sterownik maszyny!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\nMsg_OverDump                            = \"Ten ROM zawiera potrzebne dane, powielone %d razy.\\nsciagnij SMS Checker by go wyczyscic (http://www.smspower.org/maxim/smschecker/).\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Inicjalizacja systemu dzwieku...\"\r\nMsg_Sound_Init_Error_Audio              = \" - Blad przy otwieraniu systemu audio. Sprobuj wybrac inna karte lub czestotliwosc probkowania.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - Nie znaleziono zmiennej BLASTER, wylaczono dzwiek FM!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - Zmienna BLASTER nie zawiera adresu (A=xxx), wylaczono dzwiek FM!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Inicjalizacja glosu nie powiodla sie.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Tworzenie glosu #%d nie powiodlo sie.\"\r\nMsg_Sound_Init_Soundcard                = \" - Inicjalizacja karty dzwiekowej @ %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Nie mozna zainicjalizowac dzwieku: nie wybrano karty dzwiekowej!\"\r\nMsg_Sound_Init_SN76496                  = \" - Cyfrowy emulator SN76496:\"\r\nMsg_Sound_Init_YM2413_Digital           = \" - Cyfrowy emulator YM2413:\"\r\nMsg_Sound_Stream_Error                  = \"Zatrzymanie bufora dzwieku. Ponowne puszczanie strumienia.\"\r\nMsg_Sound_Volume_Changed                = \"Zmieniono glosnosc na %d%%.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Wczytywanie MEKA.THM (tematy interfejsu)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Nie znaleziono dosc tematow! Sprawdz plik MEKA.THM albo przeinstaluj.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"W wierszu %d: Nie zdefiniowano nazwy tematu do zachowania wartosci!\"\r\nMsg_Theme_Error_Syntax                  = \"W wierszu %d: blad skladni!\"\r\nMsg_Theme_Error_Attribute_Defined       = \"W wierszu %d: atrybut jest juz zdefiniowany!\"\r\nMsg_Theme_Error_Out_of_Bound            = \"W wierszu %d: wartosc jest spoza zakresu!\"\r\nMsg_Theme_Error_Theme_Missing_Data      = \"W temacie \\\"%s\\\" brakuje danych. Wylaczono go.\"\r\nMsg_Theme_Error_BG_Big                  = \"Obrazek tla jest za maly by go przeskalowac!\"\r\nMsg_Theme_Error_BG                      = \"Blad wczytywania obrazka, skojarzonego z tym tematem!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Wczytywanie ROM-u... \"\r\nMsg_LoadROM_Success                     = \"Udalo sie wczytac %s\"\r\nMsg_LoadDisk_Success                    = \"Udalo sie wczytac %s jako dyskietke\"\r\nMsg_LoadROM_Comment                     = \"Komentarz: %s\"\r\nMsg_LoadROM_SMSGG_Mode_Comment          = \"Ten ROM Game Gear dziala w trybie kompatybilnosci Master System.\"\r\nMsg_LoadROM_Warning                     = \"-Ostrzezenie-\"\r\nMsg_LoadROM_Bad_Dump_Long               = \"Wiadomo, ze ten ROM zostal zle zrzucony.\\nIstnieje mozliwosc, ze nie bedzie dobrze dzialal. Sciagnij SMS Checker by go sprawdzic http://www.smspower.org/maxim/smschecker/).\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Ostrzezenie - Wiadomo, ze ten ROM zostal zle zrzucony.\"\r\nMsg_LoadROM_Product_Num                 = \"Numer produktu: %s\"\r\nMsg_LoadROM_SDSC                        = \"-Naglowek SDSC-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Nazwa: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Wersja: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Data: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Autor: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Notka do wydania: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Nieznany>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Blad>\"\r\nMsg_LoadROM_Reload_Reloaded             = \"Wczytano ROM.\"\r\nMsg_LoadROM_Reload_No_ROM               = \"Nie ma ROM-u do wczytania!\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Wczytaj ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Naped %c]\"\r\nMsg_FileBrowser_Load                    = \"Wczytaj\"\r\nMsg_FileBrowser_Close                   = \"Zamknij\"\r\nMsg_FileBrowser_LoadNames               = \"Wczytaj nazwy\"\r\nMsg_FileBrowser_ReloadDir               = \"Odswiez katalog\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"Edytor instrumentow FM\"\r\nMsg_FM_Editor_Enabled                   = \"Wlaczono edytor instrumentow FM\"\r\nMsg_FM_Editor_Disabled                  = \"Wylaczono edytor instrumentow FM\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Wartosc przeskakiwania klatek ustawiona na: Automatyczne (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Wartosc przeskakiwania klatek ustawiona na: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"Wlaczono Licznik FPS\"\r\nMsg_FPS_Counter_Disabled                = \"Wylaczono Licznik FPS\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"Parametr LOG wymaga nazwy pliku!\"\r\nMsg_Log_Session_Start                   = \"-- Sesja logowania rozpoczeta w %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"Parametr LOAD wymaga numeru stanu zapisu!\"\r\nMsg_Load_Error                          = \"Blad otwierania %s!\"\r\nMsg_Load_Not_Valid                      = \"Plik %s nie jest wlasciwym zapisem gry %s!\"\r\nMsg_Load_Success                        = \"Wczytano stan z %s\"\r\nMsg_Load_Version                        = \"%s jest w nieobslugiwanej wersji zapisu gry!\"\r\nMsg_Load_Wrong_System                   = \"%s nie jest zapisem gry na ten system!\"\r\nMsg_Load_Massage                        = \"Plik jest w formacie MSD - konwertuje\"\r\nMsg_Save_Not_in_BIOS                    = \"Nie mozna zapisac, gdy dziala BIOS!\"\r\nMsg_Save_Error                          = \"Blad zapisu do %s!\"\r\nMsg_Save_Success                        = \"Zapisano stan do %s\"\r\nMsg_Save_Slot                           = \"Obecny numer zapisu gry to: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Opcje\"\r\nMsg_Options_Close                       = \"Zamknij\"\r\nMsg_Options_BIOS_Enable                 = \"Pokazuj logo BIOS-u.\"\r\nMsg_Options_DB_Display                  = \"Pokazuj nazwy, flagi i ikony z bazy danych.\"\r\nMsg_Options_Product_Number              = \"Pokazuj numer produktu z bazy danych.\"\r\nMsg_Options_Bright_Palette              = \"Wlacz jasna palete barw w SMS i GG.\"\r\nMsg_Options_Allow_Opposite_Directions   = \"Pozwol na przeciwstawne kierunki kontrolera.\"\r\nMsg_Options_Load_Close                  = \"Zamknij przegladarke plikow po wczytaniu gry.\"\r\nMsg_Options_Load_FullScreen             = \"Przelacz w tryb pelnoekranowy po wczytaniu gry.\"\r\nMsg_Options_FullScreen_Messages         = \"Pokazuj komunikaty w trybie pelnoekranowym.\"\r\nMsg_Options_GUI_VSync                   = \"Czekaj na synchronizacje pionowa w trybie interfejsu.\"\r\nMsg_Options_Capture_Crop_Align          = \"Przytnij i dopasuj zrzuty ekranowe do formatu 8x8.\"\r\nMsg_Options_NES_Enable                  = \"Mario nie jest grubym hydraulikiem.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Ustawiono jezyk %s\"\r\nMsg_Language_Set_Warning                = \"Uwaga: nalezy zrestartowac MEKA, wtedy na pewno zmieni sie caly tekst.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Rozpoczeto zrzut dzwieku do %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Zatrzymano zrzut dzwieku (%2.02f sekund)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Nie mozna znalezc odpowiedniej nazwy pliku do zrzucenia dzwieku!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Blad przy otwieraniu wyjsciowego pliku %s do zrzutu!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"Zrzuty VGM beda teraz zapisywane z dokladnoscia do klatki (mniejszy plik, bez glosu)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"Zrzuty VGM beda teraz zapisywane z dokladnoscia do sampla (wiekszy plik, zrzut glosu)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(By zastosowac nowy tryb dokladnosci konieczne jest ponowne rozpoczecie zrzucania VGM)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"GLOWNE\"\r\nMsg_Menu_Main_LoadROM                   = \"Wczytaj ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Wyladuj ROM\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Zapisz stan\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Wczytaj stan\"\r\nMsg_Menu_Main_Options                   = \"Opcje..\"\r\nMsg_Menu_Main_Language                  = \"Jezyk\"\r\nMsg_Menu_Main_Quit                      = \"Wyjscie\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Enabled                  = \"Wlaczony..\"\r\nMsg_Menu_Debug_ReloadROM                = \"Ponownie wczytaj ROM\"\r\nMsg_Menu_Debug_Dump                     = \"Zrzut\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MASZYNA\"\r\nMsg_Menu_Machine_Power                  = \"Zasilanie\"\r\nMsg_Menu_Machine_Power_On               = \"Wl\"\r\nMsg_Menu_Machine_Power_Off              = \"Wyl\"\r\nMsg_Menu_Machine_Region                 = \"Region\"\r\nMsg_Menu_Machine_Region_Export          = \"Europa/USA\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japonia\"\r\nMsg_Menu_Machine_TVType                 = \"Typ TV\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Twarda pauza\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Twardy reset\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"WIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Pelny ekran\"\r\nMsg_Menu_Video_Themes                   = \"Tematy\"\r\nMsg_Menu_Video_Blitters                 = \"Blittery\"\r\nMsg_Menu_Video_Layers                   = \"Warstwy\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Duszki\"\r\nMsg_Menu_Video_Layers_Background        = \"Tlo\"\r\nMsg_Menu_Video_Flickering               = \"Migotanie duszkow\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Tak\"\r\nMsg_Menu_Video_Flickering_No            = \"Nie\"\r\nMsg_Menu_Video_3DGlasses                = \"Okulary 3D\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Wlaczone\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Pokazuj obie strony\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Pokazuj lewa strone\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Pokazuj prawa strone\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Uzywaj okularow w porcie COM\"\r\nMsg_Menu_Video_ScreenCapture                  = \"Zrzut\"\r\nMsg_Menu_Video_ScreenCapture_Capture    = \"Zrzut ekranu\"\r\nMsg_Menu_Video_ScreenCapture_CaptureRepeat = \"Zrzut ekranu (wszystko)\"\r\nMsg_Menu_Video_ScreenCapture_IncludeGUI       = \"Dolacz GUI\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"DZWIEK\"\r\nMsg_Menu_Sound_FM                       = \"Jednostka FM\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Wlaczona\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Wylaczona\"\r\nMsg_Menu_Sound_FM_Editor                = \"Edytor instrumentow\"\r\nMsg_Menu_Sound_Volume                   = \"Glosnosc\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Wyciszenie\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Czestotliwosc\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Kanaly\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Ton %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Odglosy\"\r\nMsg_Menu_Sound_Capture                     = \"Zrzut\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"Start WAV\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"Stop WAV\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"Start VGM\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"Stop VGM\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM dokladne sample\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"WEJSCIA\"\r\nMsg_Menu_Inputs_Joypad                  = \"Pad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Pistolet swietlny\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Pokretla sterujace\"\r\nMsg_Menu_Inputs_SportsPad               = \"Pad sportowy\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Karta graficzna (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Klawiatura Sega\"\r\nMsg_Menu_Inputs_RapidFire               = \"Autofire\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Gracz %d Przycisk %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Konfiguracja..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"NARZEDZIA\"\r\nMsg_Menu_Tools_Messages                 = \"Komunikaty..\"\r\nMsg_Menu_Tools_Palette                  = \"Paleta..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Przegladarka plytek..\"\r\nMsg_Menu_Tools_TilemapViewer            = \"Przegladarka map plytek..\"\r\nMsg_Menu_Tools_CheatFinder              = \"Wyszukiwarka cheatow..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Informacje techniczne..\"\r\nMsg_Menu_Tools_MemoryEditor             = \"Edytor pamieci..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"POMOC\"\r\nMsg_Menu_Help_Documentation             = \"Dokumentacja..\"\r\nMsg_Menu_Help_Compat                    = \"Lista kompatybilnosci..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Lista gier dla wielu graczy..\"\r\nMsg_Menu_Help_Changes                   = \"Lista zmian..\"\r\nMsg_Menu_Help_Debugger\t\t\t\t\t= \"Debugger..\"\r\nMsg_Menu_Help_About                     = \"O..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Português]\r\nWIP\r\n; (Portuguese accentued text - UTF Support)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n; Tradução realizada por (Translation done by):\r\n; Rodrigo Campanini Rubio (Elsydeon_Sword) - elsydeon_swrd _@_ hotmail . com\r\n; http://rubiopage.tripod.com\r\n;\r\n; Atenção: Alguns caracteres poderão ser exibidos incorretamente no DOS ou na\r\n; interface devido à problemas de incompatibilidade entre os formatos de\r\n; acentos DOS ANSI e UTF text format. Reporte qualquer erro para\r\n; elsydeon_swrd _@_ hotmail . com indicando a linha de texto exibido de forma errônea.\r\n;\r\n; Warning: Some accentued characters may appear in incorrect form due to incompatibility\r\n; between UTF and ANSI-DOS accentued characters table positions. If you found any\r\n; unreadable or wrong sentences please report it to me.\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Bem vindo a %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - 8-bit ou a morte!\"\r\nMsg_Quit                                = \"Boa noite, bravo guerreiro. Boa noite, terra dos monstros...\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"Sobre Meka...\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"por %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Failed                              = \"Falhou!\"\r\nMsg_Error_Base                          = \"Erro: %s\"\r\nMsg_Error_Error                         = \"Fatal: erro obtendo tipo do erro. Alguma coisa deve estar errada.\"\r\nMsg_Error_Memory                        = \"Mem¢ria insuficiente!\"\r\nMsg_Error_Param                         = \"Parƒmetro \\\"%s\\\" ‚ inv lido!\\n\"\r\nMsg_Error_Syntax                        = \"Erro de sintaxe!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Imposs¡vel alternar para o modo de v¡deo desejado (%dx%d).\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Arquivo nÆo encontrado!\"\r\nMsg_Error_File_Read                     = \"Imposs¡vel ler do arquivo!\"\r\nMsg_Error_File_Empty                    = \"O arquivo est  vazio!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Esta versÆo nÆo suporta arquivos tipo ZIP!\"\r\nMsg_Error_ZIP_Loading                   = \"Impossível ler arquivo ZIP!\"\r\nMsg_Error_ZIP_Internal                  = \"Erro interno enquanto carregando o arquivo ZIP!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Erro abrindo diretório!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Reinicie o jogo para que as mudanças façam efeito\"\r\nMsg_No_ROM                              = \"Nenhuma ROM foi carregada!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Inicializando Allegro...\"\r\nMsg_Init_GUI                            = \"Inicializando interface gr fica com o usu rio (GUI)...\"\r\nMsg_Init_Completed                      = \"[PRONTO!]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Imagem gravada como %s\"\r\nMsg_Capture_Error                       = \"Imposs¡vel capturar imagem!\"\r\nMsg_Capture_Error_File                  = \"Não foi possível encontrar um nome válido para gravar a imagem capturada!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"SaveRAM carregada do disco (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Impossível carregar a SaveRAM do disco\"\r\nMsg_SRAM_Wrote                          = \"SaveRAM gravada no disco (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Impossível gravar a SaveRAM no disco (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Reiniciando 93c46\"\r\nMsg_93c46_Loaded                        = \"EEPROM de dados 93c46 carregada do disco (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Impossível carregar EEPROM de dados 93c46 do disco\"\r\nMsg_93c46_Wrote                         = \"EEPROM de dados 93c46 gravada no disco (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Impossível escrever EEPROM de dados 93c46 no disco (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"Agora o tipo de TV é %s\"\r\nMsg_TVType_Info_Speed                   = \"(Velocidade original: %dhz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Carregando MEKA.BLT (modos de v¡deo / padräes)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"NÆo foram encontrados padräes suficientes! Verifique o arquivo MEKA.BLT ou tente reinstal -lo.\"\r\nMsg_Blitters_Error_Not_Found            = \"PadrÆo nÆo encontrado!\"\r\nMsg_Blitters_Error_Missing              = \"Linha %d: Sem defini‡Æo de nome do padrÆo para armazenamento!\"\r\nMsg_Blitters_Error_Unrecognized         = \"Linha %d: Vari vel desconhecida!\"\r\nMsg_Blitters_Set                        = \"Usando '%s' exibição em tela inteira.\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Ativado modo 'Encanador Gorducho'\"\r\nMsg_NES_Sucks                           = \"Erro fatal: o usu rio gosta de Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Mapeador não suportado: %d. O jogo pode não funcionar.\"\r\nMsg_NES_Deny_Facts                      = \"Você não pode negar fatos!\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Inicializando depurador.\"\r\nMsg_Debug_Welcome                       = \"Bem vindo ao Depurador Meka!\"\r\nMsg_Debug_Not_Available                 = \"Depurador nao esta disponivel nesta versao!\"\r\nMsg_Debug_Trap_Read                     = \"Em PC:%04X - Ler de %04X\"\r\nMsg_Debug_Trap_Write                    = \"Em PC:%04X - Escrever de %02X a %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"Em PC:%04X - Porta [%02X] leitura\"\r\nMsg_Debug_Trap_Port_Write               = \"Em PC:%04X - Porta [%02X] escrita %02X\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Cópia de dados será agora feitas em modo ASCII.\"\r\nMsg_DataDump_Mode_Raw                   = \"Cópia de dados será agora feitas em modo RAW.\"\r\nMsg_DataDump_Error                      = \"Erro ao criar arquivo de cópia %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Não há memória para cópia!\"\r\nMsg_DataDump_Error_Palette              = \"Não há paleta para copiar!\"\r\nMsg_DataDump_Error_Sprites              = \"Não há sprites para copiar!\"\r\nMsg_DataDump_Main                       = \"Copiado(s) %s (%d %s) em modo %s.\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Documentação\"\r\nMsg_Doc_File_Error                      = \"Não foi possível abrir a documentação!\"\r\nMsg_Doc_Enabled                         = \"Exibindo documentação.\"\r\nMsg_Doc_Disabled                        = \"Documentação recolhida.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Tremulação do vídeo será evitada automaticamente.\"\r\nMsg_Flickering_Yes                      = \"Controle de tremulação do vídeo ligado.\"\r\nMsg_Flickering_No                       = \"Controle de tremulação do vídeo desligado.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Atualização do segundo plano desligada\"\r\nMsg_Layer_BG_Enabled                    = \"Atualização do segundo plano ligada\"\r\nMsg_Layer_Spr_Disabled                  = \"Atualização da imagem desligada\"\r\nMsg_Layer_Spr_Enabled                   = \"Atualização da imagem ligada\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Comando desconhecido de leitura do disco %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Comando desconhecido de escrita em disco %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Imagem de disco é maior que o esperado (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Dados adicionais serão ignorados.\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Imagem de disco é menor que o esperado(%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Dados faltantes serão tratados como vazios\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Paleta\"\r\nMsg_Palette_Disabled                    = \"Visualização de paleta desativada\"\r\nMsg_Palette_Enabled                     = \"Visualização de paleta ativa\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Mensagens\"\r\nMsg_Message_Disabled                    = \"Caixa de mensagem desativada\"\r\nMsg_Message_Enabled                     = \"Caixa de mensagem ativa\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Informações Técnicas\"\r\nMsg_TechInfo_Disabled                   = \"Informações técnicas desabilitadas\"\r\nMsg_TechInfo_Enabled                    = \"Informações técnicas ativas\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Visualizador de Tiles\"\r\nMsg_TilesViewer_Disabled                = \"Visualização de tiles desativada\"\r\nMsg_TilesViewer_Enabled                 = \"Visualização de tiles ativa\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Rapid Fire ativado para o jogador %d, botão %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Rapid Fire desativado para o jogador %d, botão %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"Emulação da unidade de FM (chip YM-2413) ligada\"\r\nMsg_FM_Disabled                         = \"Emulação da unidade de FM (chip YM-2413) desligada\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Máquina emulada é Brasileira/Européia/Estados Unidos\"\r\nMsg_Country_JAP                         = \"Máquina emulada é Japonesa\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Carregando MEKA.PAT (altera‡äes/patches)... \"\r\n;Msg_Patch_Missing                       = \"Linha %d: Nenhuma checagem (checksum) definido para esta instru‡Æo!\"\r\n;Msg_Patch_Unrecognized                  = \"Linha %d: Instru‡Æo desconhecida!\"\r\n;Msg_Patch_Out_of_Bound                  = \"Enquanto modificando ROM: tentativa de escrita fora da área permitida, posição $%02X. Cancelando modificações.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"Emulação de óculos 3-D ativa\"\r\nMsg_Glasses_Disabled                    = \"Emulação de óculos 3-D desativada\"\r\nMsg_Glasses_Show_Both                   = \"Efeito 3-D mantido original (duas imagens).\"\r\nMsg_Glasses_Show_Left                   = \"Efeito 3-D desabilitado mostrando apenas lado esquerdo.\"\r\nMsg_Glasses_Show_Right                  = \"Efeito 3-D desabilitado mostrando apenas lado direito.\"\r\nMsg_Glasses_Com_Port                    = \"Emulação de óculos 3-D habilitado através da porta COM %d.\"\r\n;Msg_Glasses_Com_Port2                   = \"(edite MEKA.CFG para mudar a porta de comunicações COM).\"\r\nMsg_Glasses_Unsupported                 = \"Este jogo parece não utilizar óculos 3-D.\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Configuração de entradas\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Inicializando joystick... \"\r\nMsg_Inputs_Joy_Init_None                = \"nenhum encontrado.\"\r\nMsg_Inputs_Joy_Init_Found               = \"encontrado(s) %d joystick(s).\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Erro ao calibrar o joystick. Cancelado.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Periférico de entrada: Controle\"\r\nMsg_Inputs_LightPhaser                  = \"Periférico de entrada: Pistola Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Periférico de entrada: Controle com leme\"\r\nMsg_Inputs_SportsPad                    = \"Periférico de entrada: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Periférico de entrada: Prancheta Gráfica Terebi Oekaki \"\r\nMsg_Inputs_Play_Digital                 = \"Dispositivo de controle com entrada digital\"\r\nMsg_Inputs_Play_Mouse                   = \"Mouse ou outro dispositivo de controle com entrada analógica\"\r\nMsg_Inputs_Play_Pen                     = \"Controlar caneta com o mouse\\nBotão_direito simula remover a caneta da prancheta\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Carregando MEKA.INP (defini‡äes de dispositivos de entrada)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Dispositivos de entrada insuficientes! Verifique o arquivo MEKA.INP ou tente reinstal -lo.\"\r\nMsg_Inputs_Src_Missing                  = \"Linha %d: NÆo h  dispositivo definido para armazenamento!\"\r\nMsg_Inputs_Src_Equal                    = \"Linha %d: Faltando sinal de igual para declara‡Æo da vari vel!\"\r\nMsg_Inputs_Src_Unrecognized             = \"Linha %d: Vari vel desconhecida \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"Linha %d: Erro de sintaxe no parƒmetro da vari vel!\"\r\nMsg_Inputs_Src_Inconsistency            = \"Linha %d: Inconsistˆncia em rela‡Æo … declara‡Æo anterior!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Agora pressione a tecla que você deseja atribuir a esta ação\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Ação designada à tecla \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Agora pressione o botão/eixo a que você deseja atribuir esta ação\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Ação designada ao joypad stick %i, eixo %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Ação designada ao botão %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Agora aperte o botão a que você deseja atribuir esta ação\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Ação designada ao botão %i do mouse.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Desculpe, mas o eixo do mouse não pode ser alterado\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Atribuição cancelada\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Emulação pausada\"\r\nMsg_Machine_Resume                      = \"Continuando emulação\"\r\nMsg_Machine_Reset                       = \"Reiniciando sistema\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\n;Msg_VFN_Loading                         = \"Carregando MEKA.VFN (nomes virtuais dos arquivos)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Carregando MEKA.NAM (nomes dos jogos)... \"\r\nMsg_DB_Name_Default                     = \"Imagem do jogo\"\r\nMsg_DB_Name_NoCartridge                 = \"Sem cartucho\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Carregando %s (configura‡Æo)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Carregando MEKA.DAT (recursos)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatal: Driver de m quina desconhecido!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\n;Msg_OverDump                            = \"Esta ROM possui %d vezes o tamanho necessário de dados.\\nPegue o \"SMS Checker\" para resolver este problema.\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Inicializando dispositivo de som...\"\r\nMsg_Sound_Init_Error_Audio              = \" - Erro ao acessar dispositivo de  udio. Tente outra placa de som ou taxa de\\namostragem.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - vari vel de ambiente BLASTER nÆo encontrada. Desabilitando som FM!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - vari vel de ambiente BLASTER nÆo possui o endere‡o (A=xxx). Desabilitando som FM!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Inicializa‡Æo das vozes falhou.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Falha na cria‡Æo da voz n£mero %d.\"\r\nMsg_Sound_Init_Soundcard                = \" - Inicializando placa de som @ %d Hz...\"\r\nMsg_Sound_Init_Soundcard_No             = \"Imposs¡vel iniciar  udio: nÆo foi selecionada uma placa de som!\"\r\n;Msg_Sound_Init_SN76496_Ok               = \" - Emulador do SN76496: Ok\"\r\n;Msg_Sound_Init_YM2413_Ok                = \" - Emulador do YM2413: Ok\"\r\nMsg_Sound_Stream_Error                  = \"Cache de som parado. Reiniciando sequência\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Carregando MEKA.THM (temas da interface)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Temas insuficientes! Verifique o\\narquivo MEKA.THM ou tente reinstal -lo.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"Linha %d: Nenhum tema definido para armazenamento do valor!\"\r\nMsg_Theme_Error_BG_Big                  = \"Figura de fundo muito pequena para ser dimensionada com escala de inteiros!\"\r\nMsg_Theme_Error_BG                      = \"Erro ao carregar a figura associada ao tema!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Carregando ROM... \"\r\nMsg_LoadROM_Success                     = \"Carregada com sucesso %s\"\r\nMsg_LoadDisk_Success                    = \"carregado %s com sucesso como um disco flexível\"\r\nMsg_LoadROM_Comment                     = \"Comentário: %s\"\r\nMsg_LoadROM_Warning                     = \"-Avisos-\"\r\n;Msg_LoadROM_Bad_Dump_Long               = \"Esta ROM é conhecida como sendo uma cópia com defeito.\\nHá grandes chances de que ela não funcione corretamente.\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Atenção - Esta ROM é conhecida como uma cópia com defeito.\"\r\nMsg_LoadROM_Product_Num                 = \"Número do produto: %s\"\r\nMsg_LoadROM_SDSC_Author                 = \"Autor: %s\"\r\nMsg_LoadROM_SDSC                        = \"-Cabeçalho SDSC-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Nome: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Versão: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Data: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Nota de Lançamento: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Desconhecido>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Erro>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Carrega ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Drive %c]\"\r\nMsg_FileBrowser_Load                    = \"Ok\"\r\nMsg_FileBrowser_Close                   = \"Fechar\"\r\nMsg_FileBrowser_LoadNames               = \"Nomes reais\"\r\nMsg_FileBrowser_ReloadDir               = \"Atualizar\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"Editor de Instrumentos FM\"\r\nMsg_FM_Editor_Enabled                   = \"Editor de voz FM ligado\"\r\nMsg_FM_Editor_Disabled                  = \"Editor de voz FM desligado\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Taxa de quadros : Automática (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Taxa de quadros ajustada para: 1/%d\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"Op‡Æo LOG precisa de um nome de arquivo!\"\r\nMsg_Log_Session_Start                   = \"-- Registrando sessÆo iniciada em %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"A op‡Æo LOAD precisa de um n£mero de estado gravado\"\r\nMsg_Load_Error                          = \"Erro abrindo %s!\"\r\nMsg_Load_Not_Valid                      = \"Arquivo %s não é uma gravação de estado válida!\"\r\nMsg_Load_Success                        = \"Estado carregado de %s\"\r\nMsg_Load_Version                        = \"%s é uma gravação de estado não suportada!\"\r\nMsg_Load_Wrong_System                   = \"%s não é uma gravação de estado para este sistema!\"\r\nMsg_Load_Massage                        = \"Arquivo em formato MSD - convertendo\"\r\nMsg_Save_Not_in_BIOS                    = \"Não é possível gravar enquanto estiver rodando a BIOS!\"\r\nMsg_Save_Error                          = \"Erro gravando em %s!\"\r\nMsg_Save_Success                        = \"Estado gravado em %s\"\r\nMsg_Save_Slot                           = \"Área para gravação de estado atual: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Opções\"\r\nMsg_Options_Close                       = \"Fechar\"\r\n;Msg_Options_BIOS_Enable                 = \"Mostrar logotipo da BIOS, se disponível no sistema.\"\r\n;Msg_Options_Product_Number              = \"Mostrar número de produto do jogo, se disponível.\"\r\n;Msg_Options_Bright_Palette              = \"Paleta brilhante para o Master System/Game Gear.\"\r\nMsg_Options_Load_Close                  = \"Fechar janela dos arquivos após carregar um jogo.\"\r\nMsg_Options_Load_FullScreen             = \"Alternar para tela inteira após carregar um jogo.\"\r\n;Msg_Options_VFN_Support                 = \"Mostrar nomes longos (Win9X) e bandeira dos países.\"\r\nMsg_Options_FullScreen_Messages         = \"Mostrar mensagem em tela inteira.\"\r\nMsg_Options_GUI_VSync                   = \"Aguardar sincronismo vertical no modo interface.\"\r\nMsg_Options_NES_Enable                  = \"Mario não é um encanador gorducho.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Idioma mudado para %s\"\r\nMsg_Language_Set_Warning                = \"Nota: É recomendado que você reinicie MEKA para ter certeza que todo o texto será atualizado.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Iniciada cópia de dados do som para o arquivo %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Término da cópia de dados do som (%2.02f segundos gravados)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Impossível encontrar um nome válido de arquivo para copiar dados do som!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Erro abrindo arquivo de saída %s para cópia de dados!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"Cópia de VGM terá precisão de quadros (arquivos menores, vozes ignoradas)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"Cópia de VGM será fiel ao 'sample' (arquivos maiores, vozes copiadas)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(A cópia de VGM deverá ser reiniciada para vigorar a nova precisão)\"\r\n;-----------------------------------------------------------------------------\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"PRINCIPAL\"\r\nMsg_Menu_Main_LoadROM                   = \"Abre ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Fecha ROM\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Gravar Estado\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Carregar Estado\"\r\nMsg_Menu_Main_Options                   = \"Opções..\"\r\nMsg_Menu_Main_Language                  = \"Idioma\"\r\nMsg_Menu_Main_Quit                      = \"Sair\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEPURAR\"\r\nMsg_Menu_Debug_Dump                     = \"Copiar\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"CONSOLE\"\r\nMsg_Menu_Machine_Power                  = \"Liga/Desliga\"\r\nMsg_Menu_Machine_Power_On               = \"Ligado\"\r\nMsg_Menu_Machine_Power_Off              = \"Desligado\"\r\nMsg_Menu_Machine_Region                 = \"País\"\r\nMsg_Menu_Machine_Region_Export          = \"Europa/EUA/Brasil\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japão\"\r\nMsg_Menu_Machine_TVType                 = \"Tipo de TV\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Pausar\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Reiniciar\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VÍDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Tela Inteira\"\r\nMsg_Menu_Video_Themes                   = \"Temas\"\r\nMsg_Menu_Video_Blitters                 = \"Padrões\"\r\nMsg_Menu_Video_Layers                   = \"Camadas\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Imagem de fundo\"\r\nMsg_Menu_Video_Flickering               = \"Tremulação\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Automático\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Sim\"\r\nMsg_Menu_Video_Flickering_No            = \"Não\"\r\nMsg_Menu_Video_3DGlasses                = \"Óculos 3-D\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Ligado\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Mostrar ambos os lados\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Mostrar lado esquerdo\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Mostrar lado direito\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Usar óculos na porta COM\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"SOM\"\r\nMsg_Menu_Sound_FM                       = \"Unidade de FM\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Ligada\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Desligada\"\r\nMsg_Menu_Sound_FM_Editor                = \"Editor de Instrumentos\"\r\nMsg_Menu_Sound_Volume                   = \"Volume\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Mudo\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Taxa\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Canais\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Tom %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Ruídos\"\r\nMsg_Menu_Sound_Capture                     = \"Gravar\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"Inicia WAV\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"Pára WAV\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"Inicia VGM\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"Pára VGM\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM com sample preciso\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"ENTRADAS\"\r\nMsg_Menu_Inputs_Joypad                  = \"Controle\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Pistola Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Controle Paddle\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Prancheta gráfica (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Teclado Sega\"\r\nMsg_Menu_Inputs_RapidFire               = \"Turbo\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Jogador %d Botão %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Configuração..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"FERRAMENTAS\"\r\nMsg_Menu_Tools_Messages                 = \"Mensagens..\"\r\nMsg_Menu_Tools_Palette                  = \"Paleta..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Visualizador de Tiles..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Informações Técnicas..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"AJUDA\"\r\nMsg_Menu_Help_Documentation             = \"Ajuda..\"\r\nMsg_Menu_Help_About                     = \"Sobre..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Italiano]\r\nWIP\r\n; Translation by A.Ballandino (Adol AT email DOT it)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Benvenuto in %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - 8-bit o morte!\"\r\nMsg_Quit                                = \"Buona notte, valoroso guerriero. Notte, terra dei mostri....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"About Meka..\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"by %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Failed                              = \"Fallito!\"\r\nMsg_Error_Base                          = \"Errore: %s\"\r\nMsg_Error_Error                         = \"Fatale: errore di tipo errore. Qualcosa e' andato storto.\"\r\nMsg_Error_Memory                        = \"Memoria insufficente!\"\r\nMsg_Error_Param                         = \"Parametero \\\"%s\\\" non valido!\\n\"\r\nMsg_Error_Syntax                        = \"Comando non valido!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Impossibile settare il modo video desiderato (%dx%d).\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"File non trovato!\"\r\nMsg_Error_File_Read                     = \"Impossibile leggere dal file!\"\r\nMsg_Error_File_Empty                    = \"File vuoto!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Questa versione non usa il formato ZIP!\"\r\nMsg_Error_ZIP_Loading                   = \"Impossibile leggere il file ZIP!\"\r\nMsg_Error_ZIP_Internal                  = \"Errore interno leggendo il file ZIP!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Errore di apertura directory!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Resetta il gioco per avere le nuove modifiche\"\r\nMsg_No_ROM                              = \"Nessuna ROM caricata!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Initializzo Allegro..\"\r\nMsg_Init_GUI                            = \"Initializzo parti grafiche..\"\r\nMsg_Init_Completed                      = \"[PRONTO]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Schermata salvata come %s\"\r\nMsg_Capture_Error                       = \"Impossibile creare la schermata!\"\r\nMsg_Capture_Error_File                  = \"Impossibile trovare un nome file valido per salvare la schermata!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"Caricata SaveRAM da disco (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Impossibile caricare SaveRAM da disco\"\r\nMsg_SRAM_Wrote                          = \"Salvata SaveRAM su disco (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Impossibile salvare SaveRAM su disco (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Resetto 93c46\"\r\nMsg_93c46_Loaded                        = \"Caricata memoria EEPROM 93c46 da disco (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Impossibile caricare memoria EEPROM 93c46 da disco\"\r\nMsg_93c46_Wrote                         = \"Salvata memoria EEPROM 93c46 su disco (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Impossibile salvare memoria EEPROM 93c46 su disco (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"Tipo di TV e' ora %s\"\r\nMsg_TVType_Info_Speed                   = \"(Frequenza di clock originale %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Carico MEKA.BLT (modi video / blitters)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Non ci sono abbastanza blitter! Controllare MEKA.BLT o reinstallare Meka.\"\r\nMsg_Blitters_Error_Not_Found            = \"Blitter non trovato!\"\r\nMsg_Blitters_Error_Missing              = \"On line %d: Nome blitter non definito!\"\r\nMsg_Blitters_Error_Unrecognized         = \"On line %d: Variabile non riconosciuta!\"\r\nMsg_Blitters_Set                        = \"Uso \\\"%s\\\" Blitter schermo intero.\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Modalita' Idraulico ciccione attivata\"\r\nMsg_NES_Sucks                           = \"Errore fatale: All'utente piace il Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Mappa non supportata: %d. Il gioco non funziona.\"\r\nMsg_NES_Deny_Facts                      = \"Non puoi negare i fatti.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Inizializzo il debugger.. \"\r\nMsg_Debug_Welcome                       = \"Benvenuto nel Debugger di Meka!\"\r\nMsg_Debug_Not_Available                 = \"Debugger non disponibile in questa versione!\"\r\nMsg_Debug_Trap_Read                     = \"At PC:%04X - Leggo da %04X\"\r\nMsg_Debug_Trap_Write                    = \"At PC:%04X - Scrivo %02X to %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"At PC:%04X - Porta [%02X] Leggo\"\r\nMsg_Debug_Trap_Port_Write               = \"At PC:%04X - Porta [%02X] Scrivo %02X\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Dump dei dati in modalita' ASCII.\"\r\nMsg_DataDump_Mode_Raw                   = \"Dump dei dati in modalita' Raw.\"\r\nMsg_DataDump_Error                      = \"Errore creazione del file per il dump %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Insufficiente memoria per il dump!\"\r\nMsg_DataDump_Error_Palette              = \"Nessuna palette per il dump!\"\r\nMsg_DataDump_Error_Sprites              = \"Nessuno sprite per il dump!\"\r\nMsg_DataDump_Main                       = \"Dump %s (%d %s) in modo %s\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Documentazione\"\r\nMsg_Doc_File_Error                      = \"Impossibile aprire la documentazione!\"\r\nMsg_Doc_Enabled                         = \"Apro documentazione.\"\r\nMsg_Doc_Disabled                        = \"Chiudo documentazione.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite Flickering degli sprite automatico.\"\r\nMsg_Flickering_Yes                      = \"Emulazione flickering sprite attivata.\"\r\nMsg_Flickering_No                       = \"Emulazione flickering sprite attivata.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Refresh di background disabilitato\"\r\nMsg_Layer_BG_Enabled                    = \"Refresh di background attivato\"\r\nMsg_Layer_Spr_Disabled                  = \"Refresh degli sprite disabilitato\"\r\nMsg_Layer_Spr_Enabled                   = \"Refresh degli sprite attivato\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Comando lettura disco sconosciuto %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Comando lettura disco sconosciuto %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Immagine disco inaspettata (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Dati addizionali saranno ignorati\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Immagine disco piu' piccola di quella aspettata (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Dati assenti saranno presi come vuoti\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Palette\"\r\nMsg_Palette_Disabled                    = \"Visore Palette disabilitato\"\r\nMsg_Palette_Enabled                     = \"Visore Palette attivato\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Messaggi\"\r\nMsg_Message_Disabled                    = \"Box messaggi disabilitato\"\r\nMsg_Message_Enabled                     = \"Box messaggi attivato\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Informazioni tecniche\"\r\nMsg_TechInfo_Disabled                   = \"Box informazioni tecniche disattivato\"\r\nMsg_TechInfo_Enabled                    = \"Box informazioni tecniche attivato\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Visore Tiles\"\r\nMsg_TilesViewer_Disabled                = \"Visore tile disabilitato\"\r\nMsg_TilesViewer_Enabled                 = \"Visore tile attivato\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Autofuoco attivato per giocatore %d Pulsante %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Autofuoco disattivato per giocatore %d Pulsante %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"Emulazione Unita' FM (YM-2413 chipset) attivata\"\r\nMsg_FM_Disabled                         = \"Emulazione Unita' FM (YM-2413 chipset) disattivata\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Sistema emulato : Europeo/US\"\r\nMsg_Country_JAP                         = \"Sistema emulato : Giapponese\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Carico MEKA.PAT (patches)... \"\r\n;Msg_Patch_Missing                       = \"On line %d: Nessun checksum definito per l'istruzione!\"\r\n;Msg_Patch_Unrecognized                  = \"On line %d: Instruzione sconosciuta!\"\r\n;Msg_Patch_Out_of_Bound                  = \"Patchando la ROM: si sta cercando di scrivere fuori range, alla posizione $%02X. Patch fallito.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"Emulazione occhiali 3-D attivata\"\r\nMsg_Glasses_Disabled                    = \"Emulazione occhiali 3-D disattivata\"\r\nMsg_Glasses_Show_Both                   = \"Effetto 3-D mantenuto.\"\r\nMsg_Glasses_Show_Left                   = \"Effetto 3-D disabilitato visualizzo lato sinistro.\"\r\nMsg_Glasses_Show_Right                  = \"Effetto 3-D disabilitato visualizzo lato destro.\"\r\nMsg_Glasses_Com_Port                    = \"Emulazione Occhiali 3-D attivata su Porta COM %d.\"\r\n;Msg_Glasses_Com_Port2                   = \"(modifica MEKA.CFG per cambiare Porta di comunicazione)\"\r\nMsg_Glasses_Unsupported                 = \"Questo gioco non supporta gli occhiali 3-D.\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Inizializzo joystick.. \"\r\nMsg_Inputs_Joy_Init_None                = \"non trovato.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d Trovato.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Errore calibrazione joystick. Esco.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Periferica Input: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Periferica Input: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Periferica Input: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Periferica Input: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Periferica Input: Terebi Oekaki Graphic Board\"\r\nMsg_Inputs_Play_Digital                 = \"Controllo con periferica input digitale\"\r\nMsg_Inputs_Play_Mouse                   = \"Controllo con periferica input analogica (mouse)\"\r\nMsg_Inputs_Play_Pen                     = \"Controllo con penna+mouse\\nClick-Destro simula la rimozione penna dalla tavola\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Configurazione Input\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Carico MEKA.INP (Definizione sorgenti input)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Non ci sono abbastanza sorgenti di input! Controllare il file MEKA.INP o re-installare.\"\r\nMsg_Inputs_Src_Missing                  = \"On line %d: Nessuna sorgente di input definita per memoria valore!\"\r\nMsg_Inputs_Src_Equal                    = \"On line %d: Manca il segno uguale per l'assegnazione di variabile!\"\r\nMsg_Inputs_Src_Unrecognized             = \"On line %d: Variabile sconosciuta \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"On line %d: Errore di sintassi nel parametro variabile!\"\r\nMsg_Inputs_Src_Inconsistency            = \"On line %d: inconsistenza di settaggio precedente!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Premere il tasto per assegnare azione\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Azione assignata al tasto \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Premere il buttone/asse per assegnare azione\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Azione assegnata al joypad stick %i, asse %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Azione assignata al joypad buttone %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Premere il bottone per assegnare azione\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Azione assegnata al mouse buttone %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Mi spiace - asse Mouse non puo' essere cambiato\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Assegnamento cancellato!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Pausa emulazione sistema\"\r\nMsg_Machine_Resume                      = \"Riprendo l'emulazione\"\r\nMsg_Machine_Reset                       = \"Reset del Sistema\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\n;Msg_VFN_Loading                         = \"Carico MEKA.VFN (Nomi file virtuali)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Carico MEKA.NAM (nomi giochi)... \"\r\nMsg_DB_Name_Default                     = \"Schermata gioco\"\r\nMsg_DB_Name_NoCartridge                 = \"Nessuna Cartuccia Caricata\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Carico %s (configurazione)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Carico MEKA.DAT (risorse)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatale: Driver sistema sconosciuto!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\n;Msg_OverDump                            = \"Questa ROM contiene %d numero/i non necessario di dati.\\nUsa \"SMS Checker\" per ripulirla.\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Inizializzo emulazione sonora..\"\r\nMsg_Sound_Init_Error_Audio              = \" - Errore apertura sistema Audio. Prova una scheda/campione diversi.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER variable non trovata, disabilito suono FM sound!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - BLASTER variabile non contiene indirizzi (A=xxx), disabilito suono FM!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Inizializzazione voci fallita.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Creazione Voce #%d fallita.\"\r\nMsg_Sound_Init_Soundcard                = \" - Inizializzazione scheda sonora @ %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Impossibile inizializzare audio: nessuna scheda sonora scelta!\"\r\n;Msg_Sound_Init_SN76496_Ok               = \" - emulatore SN76496 : Ok\"\r\n;Msg_Sound_Init_YM2413_Ok                = \" - emulatore YM2413  : Ok\"\r\nMsg_Sound_Stream_Error                  = \"Buffer sonoro fermato. Ricomincio il flusso.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Carico MEKA.THM (interfacce temi)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Non ci sono temi! Controlla MEKA.THM o reinstalla Meka.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"On line %d: Il tema non ha nome!\"\r\nMsg_Theme_Error_BG_Big                  = \"Immagine di sfondo troppo piccola per scala di ingrandimento!\"\r\nMsg_Theme_Error_BG                      = \"Errore caricamento immagine associata al tema!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Carico ROM.. \"\r\nMsg_LoadROM_Success                     = \"Caricamento completato %s\"\r\nMsg_LoadDisk_Success                    = \"Caricamento completato %s floppy disk\"\r\nMsg_LoadROM_Comment                     = \"Commento: %s\"\r\nMsg_LoadROM_Warning                     = \"-Attenzione-\"\r\n;Msg_LoadROM_Bad_Dump_Long               = \"Questa ROM ha un dump non esatto.\\nForse non funzionera' correttamente.\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Attenzione - E' risaputo che questa ROM ha un dump non esatto.\"\r\nMsg_LoadROM_Product_Num                 = \"Numero Gioco: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Header-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Nome: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Versione: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Data: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Autore: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Note di rilascita: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Sconosciuto>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Errore>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Quale ROM carico?\"\r\nMsg_FileBrowser_Drive                   = \"[Drive %c]\"\r\nMsg_FileBrowser_Load                    = \"Carica\"\r\nMsg_FileBrowser_Close                   = \"Chiudi\"\r\nMsg_FileBrowser_LoadNames               = \"Carica Nomi\"\r\nMsg_FileBrowser_ReloadDir               = \"Ricarica Dir\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"Editor strumenti FM\"\r\nMsg_FM_Editor_Enabled                   = \"Editor voci FM abilitato\"\r\nMsg_FM_Editor_Disabled                  = \"Editor voci FM disabilitato\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Valore di Frameskip settato in automatico (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Valore di Frameskip settato in: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"Contatore FPS attivato\"\r\nMsg_FPS_Counter_Disabled                = \"Contatore FPS disattivato\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"Opzione LOG, serve un nome-file!\"\r\nMsg_Log_Session_Start                   = \"-- Logging sessione partito %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"All'opzione LOAD serve un numero di file di stato!\"\r\nMsg_Load_Error                          = \"Errore di apertura %s!\"\r\nMsg_Load_Not_Valid                      = \"File %s non Š %s un salvataggio di Stato!\"\r\nMsg_Load_Success                        = \"Stato caricato da %s\"\r\nMsg_Load_Version                        = \"%s non e' un salvataggio supportato!\"\r\nMsg_Load_Wrong_System                   = \"%s non un salvataggio per questo sistema!\"\r\nMsg_Load_Massage                        = \"Formato MSD - converto..\"\r\nMsg_Save_Not_in_BIOS                    = \"Non posso salvare durante il logo del BIOS!\"\r\nMsg_Save_Error                          = \"Errore scrittura su %s!\"\r\nMsg_Save_Success                        = \"Stato salvato in %s\"\r\nMsg_Save_Slot                           = \"Corrente slot di salvataggio : %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Opzioni\"\r\nMsg_Options_Close                       = \"Chiudi\"\r\n;Msg_Options_BIOS_Enable                 = \"Mostra il logo BIOS se disponibile.\"\r\n;Msg_Options_Product_Number              = \"Mostra numero di serie del gioco se in archivio.\"\r\n;Msg_Options_Bright_Palette              = \"Palette chiare per Master System / Game Gear.\"\r\nMsg_Options_Load_Close                  = \"Chiudi il browser dopo il caricamento del gioco.\"\r\nMsg_Options_Load_FullScreen             = \"Schermo intero dopo il caricamento del gioco.\"\r\n;Msg_Options_VFN_Support                 = \"Mostra nomi file lunghi e bandiere degli stati.\"\r\nMsg_Options_FullScreen_Messages         = \"Mostra i messaggi in modalita' schermo intero.\"\r\nMsg_Options_GUI_VSync                   = \"Aspetta il VSync nella modalita' interfaccia.\"\r\nMsg_Options_NES_Enable                  = \"Mario non e' un idraulico ciccione.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Lingua settata : %s\"\r\nMsg_Language_Set_Warning                = \"Nota: Raccomando di riaprire MEKA per essere sicuri delle modifiche.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Comincio dump sonoro di output in %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Fermo dump sonoro di output sound output (%2.02f secondi contati)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Impossibile trovare un nome-file valido per dump sonoro!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Errore di apertura file di output %s per il dump!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"Dump VGM piu' accurato (piccoli files, salto le voci)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"Nel Dump VGM il campione sara' piu' accurato (grandi files, Dump voci)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"Ricomincio Dump VGM (tengo conto delle nuove opzioni)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"PRINCIPALE\"\r\nMsg_Menu_Main_LoadROM                   = \"Carica ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Libera ROM\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Salva  Stato\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Carica Stato\"\r\nMsg_Menu_Main_Options                   = \"Opzioni..\"\r\nMsg_Menu_Main_Language                  = \"Lingua\"\r\nMsg_Menu_Main_Quit                      = \"Chiudi\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Dump                     = \"Dump\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"CONSOLE\"\r\nMsg_Menu_Machine_Power                  = \"Accensione\"\r\nMsg_Menu_Machine_Power_On               = \"On\"\r\nMsg_Menu_Machine_Power_Off              = \"Off\"\r\nMsg_Menu_Machine_Region                 = \"Paese\"\r\nMsg_Menu_Machine_Region_Export          = \"Europa/Stati Uniti\"\r\nMsg_Menu_Machine_Region_Japan           = \"Giappone\"\r\nMsg_Menu_Machine_TVType                 = \"Tipo di TV\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Pausa hardware\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Reset hardware\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Schermo Intero\"\r\nMsg_Menu_Video_Themes                   = \"Temi\"\r\nMsg_Menu_Video_Blitters                 = \"Blitter\"\r\nMsg_Menu_Video_Layers                   = \"Layer\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Fondali\"\r\nMsg_Menu_Video_Flickering               = \"Flickering\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Si\"\r\nMsg_Menu_Video_Flickering_No            = \"No\"\r\nMsg_Menu_Video_3DGlasses                = \"Occhiali 3-D\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Abilitati\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Mostra entrambi i lati\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Mostra lato sinistro\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Mostra lato destro\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Usa Occhiali su Porta COM\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"SONORO\"\r\nMsg_Menu_Sound_FM                       = \"Unita' FM\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Abilitata\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Disabilitata\"\r\nMsg_Menu_Sound_FM_Editor                = \"Editor strumentale\"\r\nMsg_Menu_Sound_Volume                   = \"Volume\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Muto\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Rate\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Canali\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Toni %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Rumori\"\r\nMsg_Menu_Sound_Capture                     = \"Dump\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"Comincia Dump WAV\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"Termina Dump WAV\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"Comincia Dump VGM\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"Termina Dump VGM\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"Campioni VGM accurati\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"INPUT\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddle Control\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Tavoletta grafica (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Tastiera Sega\"\r\nMsg_Menu_Inputs_RapidFire               = \"Fuoco Rapido\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Giocatore %d Buttone %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Configurazione..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"STRUMENTI\"\r\nMsg_Menu_Tools_Messages                 = \"Messaggi..\"\r\nMsg_Menu_Tools_Palette                  = \"Palette..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Visore di Tiles..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Informazioni Tecniche..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"AIUTO\"\r\nMsg_Menu_Help_Documentation             = \"Documentazione..\"\r\nMsg_Menu_Help_Compat                    = \"Lista giochi compatibili..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Lista giochi multiplayer..\"\r\nMsg_Menu_Help_Changes                   = \"Lista cambiamenti..\"\r\nMsg_Menu_Help_About                     = \"About..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Deutsch]\r\nWIP\r\n; Übersetzung / translation to German: T.Hesse (tilman_h AT yahoo DOT de)\r\n; Used accents: äöüÄÖÜß\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main ------------------------------------------------------------------------\r\nMsg_Welcome                             = \"Willkommen in %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - 8-bit oder stirb!\"\r\nMsg_Quit                                = \"Gute Nacht, mutiger Krieger. Gute Nacht, Monsterland...\"\r\n\r\n; About -----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"Über Meka..\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"von %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ----------------------------------------------------------------------\r\nMsg_Failed                              = \"Fehlschlag!\"\r\nMsg_Error_Base                          = \"Fehler: %s\"\r\nMsg_Error_Error                         = \"Abbruch: Unbekannter Fehler!\"\r\nMsg_Error_Memory                        = \"Nicht genug Speicher!\"\r\nMsg_Error_Param                         = \"Parameter \\\"%s\\\" nicht erlaubt!\\n\"\r\nMsg_Error_Syntax                        = \"Syntaxfehler!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Kann gewuenschten Videomodus nicht aktivieren (%dx%d).\"\r\n\r\n; Errors: File ----------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Datei nicht gefunden!\"\r\nMsg_Error_File_Read                     = \"Datei kann nicht gelesen werden!\"\r\nMsg_Error_File_Empty                    = \"Datei ist leer!\"\r\n\r\n; Errors: ZIP File ------------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Diese Version von MEKA unterstützt keine gezippten Dateien!\"\r\nMsg_Error_ZIP_Loading                   = \"Kann ZIP-Datei nicht lesen!\"\r\nMsg_Error_ZIP_Internal                  = \"Interner Fehler beim Laden der ZIP-Datei!\"\r\n\r\n; Errors: Directory -----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Fehler beim Anzeigen des Verzeichnisses!\"\r\n\r\n; Miscellaneous ---------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Die Änderungen werden erst nach einem Reset aktiv.\"\r\nMsg_No_ROM                              = \"Kein ROM geladen!\"\r\n\r\n; Initialization --------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Initialisiere Allegro..\"\r\nMsg_Init_GUI                            = \"Initialisiere grafische Benutzeroberflaeche..\"\r\nMsg_Init_Completed                      = \"[BEREIT]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\n\r\n; Screenshots Capture ---------------------------------------------------------\r\nMsg_Capture_Done                        = \"Screenshot abgelegt in %s\"\r\nMsg_Capture_Error                       = \"Kann Screenshot nicht erzeugen!\"\r\nMsg_Capture_Error_File                  = \"Konnte keinen gültigen Dateinamen für das Screenshot erzeugen!\"\r\n\r\n; On-Board Memory -------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"SaveRAM wurde geladen (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"SaveRAM konnte nicht geladen werden\"\r\nMsg_SRAM_Wrote                          = \"SaveRAM wurde gespeichert (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"SaveRAM konnte nicht gespeichert werden (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Reset 93c46\"\r\nMsg_93c46_Loaded                        = \"93c46-EEPROM-Daten wurden geladen (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"93c46-EEPROM-Daten konnten nicht geladen werden\"\r\nMsg_93c46_Wrote                         = \"93c46-EEPROM-Daten wurden geschrieben (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"93c46-EEPROM-Daten konnten nicht geschrieben werden (%d bytes)\"\r\n\r\n; TV Type ---------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"TV Typ ist jetzt %s\"\r\nMsg_TVType_Info_Speed                   = \"(Geschwindigkeit %d Hz)\"\r\n\r\n; Blitters --------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Lade MEKA.BLT (Videomodi / Blitter)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Nicht genug Blitter gefunden! (Fehler in MEKA.BLT)\"\r\nMsg_Blitters_Error_Not_Found            = \"Blitter nicht gefunden!\"\r\nMsg_Blitters_Error_Missing              = \"Zeile %d: Name für Blitter nicht definiert!\"\r\nMsg_Blitters_Error_Unrecognized         = \"Zeile %d: Unbekannte Variable!\"\r\nMsg_Blitters_Set                        = \"Benutze \\\"%s\\\" Vollbild-Blitter.\"\r\n\r\n; Nintendo --------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Fetter-Klempner-Modus wurde aktiviert.\"\r\nMsg_NES_Sucks                           = \"Abbruch: der Benutzer mag Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Mapper nicht unterstützt: %d. Spiel funktioniert nicht.\"\r\nMsg_NES_Deny_Facts                      = \"Die Fakten sind unbestreitbar!\"\r\n\r\n; Debugger --------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Initialisiere debugger.. \"\r\nMsg_Debug_Welcome                       = \"Willkommen im Meka Debugger!\"\r\nMsg_Debug_Not_Available                 = \"Debugger in dieser Version nicht möglich!\"\r\nMsg_Debug_Trap_Read                     = \"Bei PC:%04X - Lese von %04X\"\r\nMsg_Debug_Trap_Write                    = \"Bei PC:%04X - Schreibe %02X nach %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"Bei PC:%04X - Port [%02X] Lesen\"\r\nMsg_Debug_Trap_Port_Write               = \"Bei PC:%04X - Port [%02X] Schreiben %02X\"\r\n\r\n; Data Dumper -----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Daten werden als ASCII gespeichert.\"\r\nMsg_DataDump_Mode_Raw                   = \"Daten werden als RAW gespeichert.\"\r\nMsg_DataDump_Error                      = \"Fehler: Kann Datei %s nicht erstellen!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Kein on-board Speicher zum Sichern!\"\r\nMsg_DataDump_Error_Palette              = \"Keine Palette zum Sichern!\"\r\nMsg_DataDump_Error_Sprites              = \"Keine Sprites zum Sichern!\"\r\nMsg_DataDump_Main                       = \"Dumped %s (%d %s) als %s\"\r\n\r\n; Documentation ---------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Dokumentation\"\r\nMsg_Doc_File_Error                      = \"Dokumentation kann nicht geöffnet werden!\"\r\nMsg_Doc_Enabled                         = \"Dokumentation wird angezeigt.\"\r\nMsg_Doc_Disabled                        = \"Dokumentation geschlossen.\"\r\n\r\n; Sprite Flickering -----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite-flickering wird automatisch gehandhabt.\"\r\nMsg_Flickering_Yes                      = \"Sprite-flickering: Emulation wurde aktiviert.\"\r\nMsg_Flickering_No                       = \"Sprite-flickering: Emulation wurde deaktiviert.\"\r\n\r\n; Layers ----------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Hintergrund aus\"\r\nMsg_Layer_BG_Enabled                    = \"Hintergrund an\"\r\nMsg_Layer_Spr_Disabled                  = \"Sprites aus\"\r\nMsg_Layer_Spr_Enabled                   = \"Sprites an\"\r\n\r\n; Floppy Disk (FDC-765) -------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Unbekannter Lesezugriff %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Unbekannter Schreibzugriff %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Datei größer als erwartet (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Weitere Daten werden ignoriert\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Disk Image ist kleiner als erwartet (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Fehlende Daten werden als 0 gelesen\"\r\n\r\n; Palette Viewer --------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Palette\"\r\nMsg_Palette_Disabled                    = \"Palettenbetrachter geschlossen\"\r\nMsg_Palette_Enabled                     = \"Palettenbetrachter aktiviert\"\r\n\r\n; Message box -----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Meldungen\"\r\nMsg_Message_Disabled                    = \"Fenster für Meldungen geschlossen\"\r\nMsg_Message_Enabled                     = \"Fenster für Meldungen aktiviert\"\r\n\r\n; Technical Information box ---------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Technische Infos\"\r\nMsg_TechInfo_Disabled                   = \"Infobox geschlossen\"\r\nMsg_TechInfo_Enabled                    = \"Infobox aktiviert\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Kacheln\"\r\nMsg_TilesViewer_Disabled                = \"Kachelbetrachter geschlossen\"\r\nMsg_TilesViewer_Enabled                 = \"Kachelbetrachter aktiviert\"\r\nMsg_TilesViewer_Tile                    = \"Kachel %d ($%X) @ %s\"\r\n\r\n; Rapid Fire ------------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Dauerfeuer für Spieler %d Knopf %d eingeschaltet\"\r\nMsg_RapidFire_JxBx_Off                  = \"Dauerfeuer für Spieler %d Knopf %d ausgeschaltet\"\r\n\r\n; FM Unit (YM-2413 chipset) ---------------------------------------------------\r\nMsg_FM_Enabled                          = \"FM Einheit (YM-2413 chipset) Emulation aktiviert\"\r\nMsg_FM_Disabled                         = \"FM Einheit (YM-2413 chipset) Emulation deaktiviert\"\r\n\r\n; Country ---------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Emuliere europäisches/US Gerät\"\r\nMsg_Country_JAP                         = \"Emuliere japanisches Gerät\"\r\n\r\n; Patching System -------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Lade MEKA.PAT (Patches)... \"\r\n;Msg_Patch_Missing                       = \"Zeile %d: Keine Prüfsumme für Befehl definiert!\"\r\n;Msg_Patch_Unrecognized                  = \"Zeile %d: Unbekannter Befehl!\"\r\n;Msg_Patch_Out_of_Bound                  = \"Der Patch versuchte einen ungültigen Zugriff an Position $%02X. Abbruch.\"\r\n\r\n; 3-D Glasses -----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"3D-Brille: Emulation ein\"\r\nMsg_Glasses_Disabled                    = \"3D-Brille: Emulation aus\"\r\nMsg_Glasses_Show_Both                   = \"3D-Effekt beibehalten.\"\r\nMsg_Glasses_Show_Left                   = \"3D-Effekt deaktiviert, zeige nur linke Seite.\"\r\nMsg_Glasses_Show_Right                  = \"3D-Effekt deaktiviert, zeige nur rechte Seite.\"\r\nMsg_Glasses_Com_Port                    = \"3D-Brille an COM Port %d aktiviert\"\r\n;Msg_Glasses_Com_Port2                   = \"(Anschluß kann in MEKA.CFG geändert werden)\"\r\nMsg_Glasses_Unsupported                 = \"Dieses Spiel unterstützt keine 3D-Brille.\"\r\n\r\n; Inputs Initialization -------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Initialisiere Joystick.. \"\r\nMsg_Inputs_Joy_Init_None                = \"nicht gefunden.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d gefunden.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Fehler während der Kalibrierung. Abbruch.\"\r\n\r\n; Inputs ----------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Eingabegerät: Gamepad\"\r\nMsg_Inputs_LightPhaser                  = \"Eingabegerät: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Eingabegerät: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Eingabegerät: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Eingabegerät: Terabi Oekaki Graphic Board\"\r\nMsg_Inputs_Play_Digital                 = \"Kontrolle über digitales Eingabegerät\"\r\nMsg_Inputs_Play_Mouse                   = \"Kontrolle über analoges Gerät (Maus)\"\r\nMsg_Inputs_Play_Pen                     = \"Kontrolle über Pen mit Maus\\nRechtsklick simuliert Anheben des Stifts.\"\r\n\r\n; Inputs Sources --------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Lade MEKA.INP (Eingabegeraete)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Nicht genug Eingabegeraete definiert! (Fehler in MEKA.INP)\"\r\nMsg_Inputs_Src_Missing                  = \"Zeile %d: Dem Wert kann kein Eingabegeraet zugeordnet werden!\"\r\nMsg_Inputs_Src_Equal                    = \"Zeile %d: Fehlendes Gleichheitszeichen!\"\r\nMsg_Inputs_Src_Unrecognized             = \"Zeile %d: Unbekannte Variable \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"Zeile %d: Syntaxfehler!\"\r\nMsg_Inputs_Src_Inconsistency            = \"Zeile %d: Konflikt mit vorherigen Einstellungen!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Bitte drücken Sie die Taste für diesen Befehl\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Befehl wurde Taste \\\"%s\\\" zugewiesen.\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Bitte drücken Sie Knopf oder Achse für diesen Befehl\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Befehl wurde Gamepad %i, Achse %i, %c zugewiesen.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Befehl wurde Gamepadknopf %i. zugewiesen\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Bitte drücken Sie die Taste für diesen Befehl\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Befehl wurde Mausknopf %i zugewiesen.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Die Mausachse kann leider nicht geändert werden\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Zuweisung abgebrochen!\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Eingabe-Konfiguration\"\r\n\r\n; Machine ---------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Emulation angehalten\"\r\nMsg_Machine_Resume                      = \"Emulation fortgesetzt\"\r\nMsg_Machine_Reset                       = \"Reset\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\n;Msg_VFN_Loading                         = \"Lade MEKA.VFN (Virtuelle Dateinamen)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Lade MEKA.NAM (Spielnamen)... \"\r\nMsg_DB_Name_Default                     = \"Spielbildschirm\"\r\nMsg_DB_Name_NoCartridge                 = \"Keine Cartridge\"\r\n\r\n; Configuration File ----------------------------------------------------------\r\nMsg_Config_Loading                      = \"Lade %s (Konfiguration)... \"\r\n\r\n; Datafile ------------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Lade MEKA.DAT (Ressourcen)... \"\r\n\r\n; Drivers ---------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Abbruch: Unbekannter Treiber!\"\r\n\r\n; Overdump detection ----------------------------------------------------------\r\nMsg_OverDump                            = \"Das ROM enthält die benötigten Daten %d -fach.\\n Der Fehler kann mit dem \\\"SMS Checker\\\" korrigiert werden.\"\r\n\r\n; Sound -----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Initialisiere Soundsystem..\"\r\nMsg_Sound_Init_Error_Audio              = \" - Fehler beim Ansprechen der Soundkarte. Bitte eine andere Karte und/oder Samplerate waehlen.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER Variable nicht gefunden, FM kann nicht benutzt werden!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - Eintrag (A=xxx) fehlt in BLASTER, FM kann nicht benutzt werden!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Stimmeninitialisierung fehlgeschlagen.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Stimme #%d konnte nicht angesprochen werden.\"\r\nMsg_Sound_Init_Soundcard                = \" - Initialisiere Soundkarte @ %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Audio kann nicht initialisiert werden: Es wurde keine Soundkarte gewaehlt!\"\r\n;Msg_Sound_Init_SN76496_Ok               = \" - SN76496 Emulator: Ok\"\r\n;Msg_Sound_Init_YM2413_Ok                = \" - YM2413 Emulator: Ok\"\r\nMsg_Sound_Stream_Error                  = \"Klangpuffer angehalten. Stream wird neu gestartet.\"\r\n\r\n; Theme -----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Lade MEKA.THM (Themen)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Nicht genug Themen gefunden! (Fehler in MEKA.THM)\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"Zeile %d: Variable kann keinem Thema zugeordnet werden!\"\r\nMsg_Theme_Error_BG_Big                  = \"Hintergrundbild zu klein, um korrekt vergrößert zu werden!\"\r\nMsg_Theme_Error_BG                      = \"Fehler beim Laden des Hintergrundbilds!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ----------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Lade ROM.. \"\r\nMsg_LoadROM_Success                     = \"%s wurde erfolgreich geladen\"\r\nMsg_LoadDisk_Success                    = \"%s wurde als Diskette geladen\"\r\nMsg_LoadROM_Comment                     = \"Kommentar: %s\"\r\nMsg_LoadROM_Warning                     = \"-Warnung-\"\r\n;Msg_LoadROM_Bad_Dump_Long               = \"Dieses ROM wurde fehlerhaft gedumpt.\\n Es wird wahrscheinlich nicht richtig funktionieren.\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Warnung - Dieses ROM wurde fehlerhaft gedumpt.\"\r\nMsg_LoadROM_Product_Num                 = \"Produktnummer: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Kopf-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Name: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Version: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Datum: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Autor: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Bemerkungen: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Unbekannt>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Fehler>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Lade ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Laufwerk %c]\"\r\nMsg_FileBrowser_Load                    = \"Lade\"\r\nMsg_FileBrowser_Close                   = \"Abbruch\"\r\nMsg_FileBrowser_LoadNames               = \"Lade Namen\"\r\nMsg_FileBrowser_ReloadDir               = \"Auffrischen\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"FM-Stimmen\"\r\nMsg_FM_Editor_Enabled                   = \"FM-Voice-Editor aktiviert\"\r\nMsg_FM_Editor_Disabled                  = \"FM-Voice-Editor geschlossen\"\r\n\r\n; Video Options ---------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Frameskip: Automatisch (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Frameskip: Wert gesetzt auf: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"FPS-Anzeige ein\"\r\nMsg_FPS_Counter_Disabled                = \"FPS-Anzeige aus\"\r\n\r\n; Logging ---------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"LOG benötigt einen Dateinamen!\"\r\nMsg_Log_Session_Start                   = \"-- Logging gestartet um %s\"\r\n\r\n; Save States -----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"Laden benötigt Nummer des Slots!\"\r\nMsg_Load_Error                          = \"Fehler beim Öffnen von %s!\"\r\nMsg_Load_Not_Valid                      = \"Datei %s ist kein gültiges Savegame für %s!\"\r\nMsg_Load_Success                        = \"Status geladen aus %s\"\r\nMsg_Load_Version                        = \"Die Dateiversion von %s wird nicht unterstützt!\"\r\nMsg_Load_Wrong_System                   = \"%s ist kein Savegame für dieses System!\"\r\nMsg_Load_Massage                        = \"Datei entspricht dem MSD Format - Konvertiere\"\r\nMsg_Save_Error                          = \"Fehler beim Schreiben von %s!\"\r\nMsg_Save_Success                        = \"Spiel gespeichert in %s\"\r\nMsg_Save_Slot                           = \"Slot zum Speichern: %d\"\r\nMsg_Save_Not_in_BIOS                    = \"Speichern im BIOS nicht möglich!\"\r\n\r\n; Options ---------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Optionen\"\r\nMsg_Options_Close                       = \"OK\"\r\n;Msg_Options_BIOS_Enable                 = \"Zeige BIOS-Logo, wenn vom System unterstützt.\"\r\n;Msg_Options_Product_Number              = \"Zeige Produktnummer des Spiels, wenn bekannt.\"\r\n;Msg_Options_Bright_Palette              = \"Helle Palette für Master System / Game Gear.\"\r\nMsg_Options_Load_Close                  = \"Schließe Dateifenster, nachdem Spiel geladen wurde.\"\r\nMsg_Options_Load_FullScreen             = \"Nach Laden automatisch Vollbild aktivieren.\"\r\n;Msg_Options_VFN_Support                 = \"Lange Dateinamen, sowie Länderfahnen anzeigen.\"\r\nMsg_Options_FullScreen_Messages         = \"Meldungen im Vollbildmodus anzeigen.\"\r\nMsg_Options_GUI_VSync                   = \"Auf VSync im Interfacemodus warten.\"\r\nMsg_Options_NES_Enable                  = \"Mario ist kein fetter Klempner.\"\r\n\r\n; Languages / Localization ----------------------------------------------------\r\nMsg_Language_Set                        = \"Sprache für Meldungen ist jetzt %s\"\r\nMsg_Language_Set_Warning                = \"Hinweis: Zum Aktualisieren aller Nachrichten bitte MEKA neu starten.\"\r\n\r\n; Sound Dumping ---------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Sound-Dump in Datei %s wurde begonnen\"\r\nMsg_Sound_Dumping_Stop                  = \"Sound-Dump angehalten. (%2.02f Sekunden gespeichert)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Es konnte kein gültiger Dateiname für den Sound-Dump erzeugt werden!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Fehler beim Öffnen von Datei %s!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"Frame-genaue Sicherung der VGM-Daten (kleinere Dateien, ohne Stimmen)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"Sample-genaue Sicherung der VGM-Daten (größere Dateien, mit Stimmen)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(Der VGM-Dump muß neu gestartet werden, um die geänderte Genauigkeit zu übernehmen)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"DATEI\"\r\nMsg_Menu_Main_LoadROM                   = \"ROM laden..\"\r\nMsg_Menu_Main_FreeROM                   = \"ROM schließen\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Status sichern\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Status laden\"\r\nMsg_Menu_Main_Options                   = \"Optionen..\"\r\nMsg_Menu_Main_Language                  = \"Sprache\"\r\nMsg_Menu_Main_Quit                      = \"Ende\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Dump                     = \"Sichern\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MASCHINE\"\r\nMsg_Menu_Machine_Power                  = \"Power\"\r\nMsg_Menu_Machine_Power_On               = \"An\"\r\nMsg_Menu_Machine_Power_Off              = \"Aus\"\r\nMsg_Menu_Machine_Region                 = \"Land\"\r\nMsg_Menu_Machine_Region_Export          = \"Europa/US\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japanisch\"\r\nMsg_Menu_Machine_TVType                 = \"TV-Typ\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation        = \"Hardwarepause\"\r\n;Msg_Menu_Machine_ResetEmulation        = \"Hardwarereset\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Vollbild\"\r\nMsg_Menu_Video_Themes                   = \"Themen\"\r\nMsg_Menu_Video_Blitters                 = \"Blitter\"\r\nMsg_Menu_Video_Layers                   = \"Layer\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Hintergrund\"\r\nMsg_Menu_Video_Flickering               = \"Flimmern\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Ja\"\r\nMsg_Menu_Video_Flickering_No            = \"Nein\"\r\nMsg_Menu_Video_3DGlasses                = \"3D-Brille\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Ein\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Zeige beide Seiten\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Zeige linke Seite\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Zeige rechte Seite\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Brille an COM-Port\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"SOUND\"\r\nMsg_Menu_Sound_FM                       = \"FM-Chip\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Aktiviert\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Deaktiviert\"\r\nMsg_Menu_Sound_FM_Editor                = \"Instrumente..\"\r\nMsg_Menu_Sound_Volume                   = \"Lautstärke\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Stumm\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Rate\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Kanäle\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Ton %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Rauschen\"\r\nMsg_Menu_Sound_Capture                     = \"Speichern\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"WAV Start\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"WAV Stop\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"VGM Start\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"VGM Stop\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM samplegenau\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"EINGABE\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddle Control\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Graphiktablett (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Sega Keyboard\"\r\nMsg_Menu_Inputs_RapidFire               = \"Dauerfeuer\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Spieler %d Knopf %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Konfiguration..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"WERKZEUGE\"\r\nMsg_Menu_Tools_Messages                 = \"Meldungen..\"\r\nMsg_Menu_Tools_Palette                  = \"Palette..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Kachelbetrachter..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Technische Infos..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"HILFE\"\r\nMsg_Menu_Help_Documentation             = \"Dokumentation..\"\r\nMsg_Menu_Help_Compat                    = \"Unterstützte Spiele..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Multiplayer..\"\r\nMsg_Menu_Help_Changes                   = \"Was ist neu..\"\r\nMsg_Menu_Help_About                     = \"Über..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Swedish]\r\nWIP\r\n; Translation by H.Sankala (hensan-7 AT student DOT ltu.se)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Välkommen till %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - 8-bitar eller dö!\"\r\nMsg_Quit                                = \"God natt, modiga krigare. God natt, monster-land....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"Om Meka..\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"av %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Ok                                  = \"Ok\"\r\nMsg_Failed                              = \"Misslyckades!\"\r\nMsg_Error_Base                          = \"Fel: %s\"\r\nMsg_Error_Error                         = \"Allvarligt fel: Fel vid hämtning av feltyp. Något måste vara fel.\"\r\nMsg_Error_Memory                        = \"Ej tillräckligt med minne!\"\r\nMsg_Error_Param                         = \"Parameter \\\"%s\\\" är ogiltig!\\n\"\r\nMsg_Error_Syntax                        = \"Syntaxfel!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Kan ej byta till önskat videoläge (%dx%d).\"\r\nMsg_Error_Video_Mode_Back_To_GUI        = \"Växlar tillbaka till grafiskt användargränssnitt.\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Kan ej hitta fil!\"\r\nMsg_Error_File_Read                     = \"Kan ej läsa från fil!\"\r\nMsg_Error_File_Empty                    = \"Filen är tom!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Denna version kan ej hantera ZIP filer!\"\r\nMsg_Error_ZIP_Loading                   = \"Kan ej läsa ZIP fil!\"\r\nMsg_Error_ZIP_Internal                  = \"Internt fel vid laddning av ZIP fil!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Fel vid öppning av katalog!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Resetta spelet för att verkställa ändringarna\"\r\nMsg_No_ROM                              = \"Ingen ROM laddades!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Initialiserar Allegro..\"\r\nMsg_Init_GUI                            = \"Initialiserar grafiskt användargränssitt..\"\r\nMsg_Init_Completed                      = \"[REDO]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\nMsg_Setup_Setup                         = \"Inställningar\"\r\nMsg_Setup_SampleRate_Select             = \"Samplingshastighet:\"\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Skärmdump sparad till %s\"\r\nMsg_Capture_Error                       = \"Kan ej skapa skärmdump!\"\r\nMsg_Capture_Error_File                  = \"Kan ej hitta giltigt filnamn för sparande av skärmdump!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"Laddade SaveRAM från disk (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Kan ej ladda SaveRAM från disk\"\r\nMsg_SRAM_Wrote                          = \"Sparade SaveRAM till disk (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Kan ej spara SaveRAM till disk (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Resettar 93c46\"\r\nMsg_93c46_Loaded                        = \"Laddade 93c46 EEPROM data från disk (%d byte)\"\r\nMsg_93c46_Load_Unable                   = \"Kan ej ladda 93c46 EEPROM data från disk\"\r\nMsg_93c46_Wrote                         = \"Sparade 93c46 EEPROM data till disk (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Kan ej spara 93c46 EEPROM data till disk (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"TV typ är nu %s\"\r\nMsg_TVType_Info_Speed                   = \"(Ursprunglig hastighet är %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Laddar MEKA.BLT (video lägen / blitters).. \"\r\nMsg_Blitters_Error_Not_Enough           = \"Kunde ej hitta tillräckligt med Blitters! Kontrollera filen MEKA.BLT eller försök installera om.\"\r\nMsg_Blitters_Error_Not_Found            = \"Kunde ej hitta Blitter!\"\r\nMsg_Blitters_Error_Missing              = \"På rad %d: Inget blitternamn definierat för lagrande av värde!\"\r\nMsg_Blitters_Error_Unrecognized         = \"På rad %d: Okänd variabel!\"\r\nMsg_Blitters_Set                        = \"Använder nu \\\"%s\\\" fullskärmsblitter.\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Fet rörmokare läge aktiverat\"\r\nMsg_NES_Sucks                           = \"Allvarligt fel: Användaren gillar Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Ostödd mapper: %d. Spelet kommer ej att fungera.\"\r\nMsg_NES_Deny_Facts                      = \"Du kan inte förneka fakta.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Initialiserar debugger.. \"\r\nMsg_Debug_Welcome                       = \"Välkommen till Meka Debugger!\"\r\nMsg_Debug_Not_Available                 = \"Debugger ej tillgänglig i denna version!\"\r\nMsg_Debug_Trap_Read                     = \"Vid PC:%04X - Läsning från %04X\"\r\nMsg_Debug_Trap_Write                    = \"Vid PC:%04X - Skrivning %02X till %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"Vid PC:%04X - Port [%02X] Läsning\"\r\nMsg_Debug_Trap_Port_Write               = \"Vid PC:%04X - Port [%02X] Skrivning %02X\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Data dumpar kommer nu att göras i ASCII läge.\"\r\nMsg_DataDump_Mode_Raw                   = \"Data dumpar kommer nu att göras i Raw läge.\"\r\nMsg_DataDump_Error                      = \"Fel vid skapande av fil att dumpa %s till!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Inget on-board minne att dumpa!\"\r\nMsg_DataDump_Error_Palette              = \"Ingen palett att dumpa!\"\r\nMsg_DataDump_Error_Sprites              = \"Inga sprites att dumpa!\"\r\nMsg_DataDump_Main                       = \"Dumpade %s (%d %s) i %s läge\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Dokumentation\"\r\nMsg_Doc_File_Error                      = \"Kan ej öppna dokumentation!\"\r\nMsg_Doc_Enabled                         = \"Dokumentation visas.\"\r\nMsg_Doc_Disabled                        = \"Dokumentation stängd.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite flimmer kommer att hanteras automatiskt.\"\r\nMsg_Flickering_Yes                      = \"Sprite flimmer emulering är nu på.\"\r\nMsg_Flickering_No                       = \"Sprite flimmer emulering är nu av.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Bakgrundsuppdatering av\"\r\nMsg_Layer_BG_Enabled                    = \"Bakgrundsuppdatering på\"\r\nMsg_Layer_Spr_Disabled                  = \"Spriteuppdatering av\"\r\nMsg_Layer_Spr_Enabled                   = \"Spriteuppdatering på\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Okänt diskläsningskommando %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Okänt diskskrivningskommando %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Disk bilden är större än väntat (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Ytterligare data kommer att ignoreras\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Disk bilden är mindre än väntat (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Saknad data kommer att antas vara tomt\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Palett\"\r\nMsg_Palette_Disabled                    = \"Palettgranskare av\"\r\nMsg_Palette_Enabled                     = \"Palettgranskare på\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Meddelanden\"\r\nMsg_Message_Disabled                    = \"Meddelandefönster av\"\r\nMsg_Message_Enabled                     = \"Meddelandefönster på\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Teknisk information\"\r\nMsg_TechInfo_Disabled                   = \"Fönster för Teknisk information av\"\r\nMsg_TechInfo_Enabled                    = \"Fönster för Teknisk information på\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Tilegranskare\"\r\nMsg_TilesViewer_Disabled                = \"Tilegranskare av\"\r\nMsg_TilesViewer_Enabled                 = \"Tilegranskare på\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Automateld är nu aktiverat för spelare %d knapp %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Automateld är nu avaktiverat för spelare %d knapp %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"Emulering av FM enhet (YM-2413 chipset) på\"\r\nMsg_FM_Disabled                         = \"Emulering av FM enhet (YM-2413 chipset) av\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Den emulerade maskinen är nu Europeisk/Amerikansk\"\r\nMsg_Country_JAP                         = \"Den emulerade maskinen är nu Japansk\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Laddar MEKA.PAT (patchar).. \"\r\nMsg_Patch_Missing                       = \"På rad %d: Ingen checksum definierad för att köra kommando på!\"\r\nMsg_Patch_Unrecognized                  = \"På rad %d: Syntaxfel eller okänt kommando!\"\r\nMsg_Patch_Value_Not_a_Byte              = \"På rad %d: Värdet %s rymms inte i en unsigned byte!\"\r\nMsg_Patch_Out_of_Bound                  = \"Under patchning %s: Address $%04X är utanför gränserna. Patch ej applicerad.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"Emulering av 3D glasögon på\"\r\nMsg_Glasses_Disabled                    = \"Emulering av 3D glasögon av\"\r\nMsg_Glasses_Show_Both                   = \"3D effekter oförändrade.\"\r\nMsg_Glasses_Show_Left                   = \"3D effekter av genom att visa endast vänster sida.\"\r\nMsg_Glasses_Show_Right                  = \"3D effekter av genom att visa endast höger sida.\"\r\nMsg_Glasses_Com_Port                    = \"Emulering av 3D glasögon genom COM port %d.\"\r\nMsg_Glasses_Com_Port2                   = \"(Redigera MEKA.CFG för att välja COM port)\"\r\nMsg_Glasses_Com_Port_Open_Error         = \"Fel vid öppnande av COM port %d. 3-D glasögonen kommer ej att fungera.\"\r\nMsg_Glasses_Unsupported                 = \"Detta spel verkar inte stödja 3D glasögon.\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Initialiserar joystick.. \"\r\nMsg_Inputs_Joy_Init_None                = \"hittades ej.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d hittades.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Fel vid kalibrering av joystick. Avbryter.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Styrenhet: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Styrenhet: Ljuspistol\"\r\nMsg_Inputs_PaddleControl                = \"Styrenhet: Paddel Kontroll\"\r\nMsg_Inputs_SportsPad                    = \"Styrenhet: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Styrenhet: Terebi Oekaki Grafikbord\"\r\nMsg_Inputs_Play_Digital                 = \"Kontrollera med digital styrenhet\"\r\nMsg_Inputs_Play_Mouse                   = \"Kontrollera med analog styrenhet (mus)\"\r\nMsg_Inputs_Play_Digital_Unrecommended   = \"Digitala styrenheter (t.ex: tangentbord) stöds men rekommenderas EJ\"\r\nMsg_Inputs_Play_Pen                     = \"Kontrollera penna med mus\\nHöger-klick simulerar att pennan avlägsnas från bordet\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Konfigurering av styrenheter\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Laddar MEKA.INP (definition av källor för styrenheter).. \"\r\nMsg_Inputs_Src_Not_Enough               = \"Kunde ej hitta tillräckligt med styrenhetskällor! Kontrollera filen MEKA.INP eller försök installera om.\"\r\nMsg_Inputs_Src_Missing                  = \"På rad %d: Ingen källa definierad för lagring av värde!\"\r\nMsg_Inputs_Src_Equal                    = \"På rad %d: Likhetstecken saknas för variabeltilldelning!\"\r\nMsg_Inputs_Src_Unrecognized             = \"På rad %d: Okänd variabel \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"På rad %d: Syntaxfel på variabelparameter!\"\r\nMsg_Inputs_Src_Inconsistency            = \"På rad %d: Oförenlighet med föregående inställningar!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Tryck nu på den tangent du vill tilldela denna åtgärd till\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Åtgärden tilldelad till tangent \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Tryck nu på den knapp/axel du vill tilldela denna åtgärd till\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Åtgärden tilldelad till joypad spak %i, axel %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Åtgärden tilldelad till joypad knapp %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Tryck nu på den knapp du vill tilldela denna åtgärd\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Åtgärden tilldelad till musknapp %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Tyvärr - Mus axlarna kan ej ändras\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Tilldelning avbruten!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Maskinemulering pausad\"\r\nMsg_Machine_Resume                      = \"Maskinemulering återupptagen\"\r\nMsg_Machine_Reset                       = \"Maskinen resettad\"\r\n\r\n; Virtual File Names ---------------------------------------------------------\r\n;Msg_VFN_Loading                         = \"Laddar MEKA.VFN (virtuella filnamn).. \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Laddar MEKA.NAM (spelnamn).. \"\r\nMsg_DB_Name_Default                     = \"Spelskärm\"\r\nMsg_DB_Name_NoCartridge                 = \"Ingen spelkassett\"\r\nMsg_DB_SyntaxError                      = \"På rad %d: Syntaxfel!\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Laddar MEKA.CFG (konfiguration).. \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Laddar MEKA.DAT (resurser).. \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Allvarligt fel: Okänd maskindrivrutin!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\n;Msg_OverDump                            = \"Denna ROM innehåller %d gånger mer data än nödvändigt.\\nLadda hem \\\"SMS Checker\\\" för att fixa den (http://www.smspower.org/maxim/smschecker/).\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Initialiserar ljudsystem..\"\r\nMsg_Sound_Init_Error_Audio              = \" - Fel vid öppning av ljudsystem. Försök med ett annat kort och/eller samplingsfrekvens.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER variabel hittades ej, FM ljud av!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - BLASTER variabel innehåller ej adress (A=xxx), FM ljud av!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Röstinitialisering misslyckades.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Skapande av röst #%d misslyckades.\"\r\nMsg_Sound_Init_Soundcard                = \" - Initialiserar ljudkort @ %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Kan ej initialisera ljud: inget ljudkort valt!\"\r\nMsg_Sound_Init_SN76496                  = \" - SN76496 digital emulator:\"\r\nMsg_Sound_Init_YM2413_Digital           = \" - YM2413 digital emulator:\"\r\nMsg_Sound_Stream_Error                  = \"Ljudbuffer stop. Startar om strömmen.\"\r\nMsg_Sound_Volume_Changed                = \"Volym ändrad till %d%%.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Laddar MEKA.THM (gränssnittsteman).. \"\r\nMsg_Theme_Error_Not_Enough              = \"Kunde ej hitta tillräckligt med teman! Kontrollera filen MEKA.THM eller försök installera om.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"På rad %d: Inget temanamn definierat för lagring av värde!\"\r\nMsg_Theme_Error_BG_Big                  = \"Bakgrundsbild för liten för att passa med heltals skalning!\"\r\nMsg_Theme_Error_BG                      = \"Fel vid laddning av bild associerad med temat!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Laddar ROM.. \"\r\nMsg_LoadROM_Success                     = \"Laddade %s\"\r\nMsg_LoadDisk_Success                    = \"Laddade %s som en diskett\"\r\nMsg_LoadROM_Comment                     = \"Kommentar: %s\"\r\nMsg_LoadROM_SMSGG_Mode_Comment          = \"Detta är en Game Gear ROM som körs i Master System-kompatabilitetsläge.\"\r\nMsg_LoadROM_Warning                     = \"-Varning-\"\r\nMsg_LoadROM_Bad_Dump_Long               = \"Denna ROM är en känd dålig dump.\\nDen kan komma att fungera otillfredsställande. Ladda hem SMS Checker för att kontrollera den (http://www.smspower.org/maxim/smschecker/)\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Varning - Denna ROM är felaktigt dumpad.\"\r\nMsg_LoadROM_Product_Num                 = \"Produktnummer: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Header-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Namn: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Version: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Datum: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Författare: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Information: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Okänt>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Fel>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Ladda ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Enhet %c]\"\r\nMsg_FileBrowser_Load                    = \"Ladda\"\r\nMsg_FileBrowser_Close                   = \"Stäng\"\r\nMsg_FileBrowser_LoadNames               = \"Ladda namn\"\r\nMsg_FileBrowser_ReloadDir               = \"Uppdatera\"\r\n\r\n; FM Instruments Editor ------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"FM Instrumentediterare\"\r\nMsg_FM_Editor_Enabled                   = \"FM Instrumentediterare på\"\r\nMsg_FM_Editor_Disabled                  = \"FM Instrumentediterare av\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Frameskip värde satt till: Automatisk (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Frameskip värde satt till: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"FPS-räknare på\"\r\nMsg_FPS_Counter_Disabled                = \"FPS-räknare av\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"LOG valet kräver ett filnamn!\"\r\nMsg_Log_Session_Start                   = \"-- Loggnings session startad på %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"LADDA valet kräver ett savestate nummer!\"\r\nMsg_Load_Error                          = \"Fel vid öppnande av %s!\"\r\nMsg_Load_Not_Valid                      = \"Filen %s är inte en giltig %s savegame!\"\r\nMsg_Load_Success                        = \"Tillstånd laddat från %s\"\r\nMsg_Load_Version                        = \"%s är en ostödd savegame version!\"\r\nMsg_Load_Wrong_System                   = \"%s är inte ett savegame för detta system!\"\r\nMsg_Load_Massage                        = \"Filen är i MSD format - konverterar\"\r\nMsg_Save_Not_in_BIOS                    = \"Kan ej spara när BIOS körs!\"\r\nMsg_Save_Error                          = \"Fel vid skrivning till %s!\"\r\nMsg_Save_Success                        = \"Tillstånd sparat till %s\"\r\nMsg_Save_Slot                           = \"Nuvarande savegame slot är: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Inställningar\"\r\nMsg_Options_Close                       = \"Stäng\"\r\nMsg_Options_BIOS_Enable                 = \"Visa BIOS logo.\"\r\nMsg_Options_DB_Display                  = \"Visa namn, flaggor och ikoner från databasen.\"\r\nMsg_Options_Product_Number              = \"Visa produktnummer från databasen.\"\r\nMsg_Options_Bright_Palette              = \"Aktivera ljus palett på SMS och GG.\"\r\nMsg_Options_Load_Close                  = \"Stäng filgranskaren efter laddning.\"\r\nMsg_Options_Load_FullScreen             = \"Växla till fullskärmsläge efter laddning.\"\r\nMsg_Options_FullScreen_Messages         = \"Visa meddelanden i fullskärm.\"\r\nMsg_Options_GUI_VSync                   = \"Vänta på VSync i interface läge.\"\r\nMsg_Options_NES_Enable                  = \"Mario är inte en fet rörmokare.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Språk satt till %s\"\r\nMsg_Language_Set_Warning                = \"OBS: Du rekommenderas att starta om MEKA för att vara säker på att all text uppdateras.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Började dumpa ljud till %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Slutade dumpa ljud (%2.02f sekunder loggade)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Kan ej hitta giltigt filnamn för att dumpa ljud!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Fel vid öppning av %s för dumpning!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"VGM dumpar kommer nu vara frame exakta (mindre filer, skippa röster)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"VGM dumpar kommer nu vara sampel exakta (större filer, dumpa röster)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(VGM dumpning måste startas om för att ta hänsyn till ny noggranhet)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"ARKIV\"\r\nMsg_Menu_Main_LoadROM                   = \"Ladda ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Frigör ROM\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Spara tillstånd\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Ladda tillstånd\"\r\nMsg_Menu_Main_Options                   = \"Inställningar..\"\r\nMsg_Menu_Main_Language                  = \"Språk\"\r\nMsg_Menu_Main_Quit                      = \"Avsluta\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Enabled                  = \"Aktiverad..\"\r\nMsg_Menu_Debug_Dump                     = \"Dump\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MASKIN\"\r\nMsg_Menu_Machine_Power                  = \"Ström\"\r\nMsg_Menu_Machine_Power_On               = \"På\"\r\nMsg_Menu_Machine_Power_Off              = \"Av\"\r\nMsg_Menu_Machine_Region                 = \"Land\"\r\nMsg_Menu_Machine_Region_Export          = \"Europa/USA\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japan\"\r\nMsg_Menu_Machine_TVType                 = \"TV Typ\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Hård Paus\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Hård Reset\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"BILD\"\r\nMsg_Menu_Video_FullScreen               = \"Fullskärm\"\r\nMsg_Menu_Video_Themes                   = \"Teman\"\r\nMsg_Menu_Video_Blitters                 = \"Blitters\"\r\nMsg_Menu_Video_Layers                   = \"Lager\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Bakgrund\"\r\nMsg_Menu_Video_Flickering               = \"Flimmer\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Ja\"\r\nMsg_Menu_Video_Flickering_No            = \"Nej\"\r\nMsg_Menu_Video_3DGlasses                = \"3D Glasögon\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"På\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Visa båda sidor\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Visa vänster sida\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Visa höger sida\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Använder glasögon på COM port\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"LJUD\"\r\nMsg_Menu_Sound_FM                       = \"FM enhet\"\r\nMsg_Menu_Sound_FM_Enabled               = \"På\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Av\"\r\nMsg_Menu_Sound_FM_Editor                = \"Instrumentediterare\"\r\nMsg_Menu_Sound_Volume                   = \"Volym\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Ljud av\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Kvalitet\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Kanaler\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Ton %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Oljud\"\r\nMsg_Menu_Sound_Capture                     = \"Dump\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"WAV Start\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"WAV Stop\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"VGM Start\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"VGM Stop\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM Sampel exakt\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"STYRENHETER\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Ljuspistol\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddel Kontroll\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Grafikbord (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Sega Tangentbord\"\r\nMsg_Menu_Inputs_RapidFire               = \"Automateld\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Spelare %d Knapp %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Konfiguration..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"VERKTYG\"\r\nMsg_Menu_Tools_Messages                 = \"Meddelanden..\"\r\nMsg_Menu_Tools_Palette                  = \"Palett..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Tilegranskare..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Teknisk information..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"HJÄLP\"\r\nMsg_Menu_Help_Documentation             = \"Dokumentation..\"\r\nMsg_Menu_Help_Compat                    = \"Kompatabilitet..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Multiplayerspel..\"\r\nMsg_Menu_Help_Changes                   = \"Ändringar..\"\r\nMsg_Menu_Help_About                     = \"Om MEKA..\"\r\n\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n[Danish]\r\nWIP\r\n; Translation by M.Klemp (Supreme1 AT gmx DOT co.uk)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n; Main -----------------------------------------------------------------------\r\nMsg_Welcome                             = \"Velkommen til %s (c) %s\"\r\n;Msg_Window_Title                        = \"MEKA - 8-bit eller dø!\"\r\nMsg_Quit                                = \"Godnat modige kriger. Godnat monster-land....\"\r\n\r\n; About ----------------------------------------------------------------------\r\nMsg_About_BoxTitle                      = \"Om Meka..\"\r\nMsg_About_Line_Meka_Date                = \"%s (c) %s\"\r\nMsg_About_Line_Authors                  = \"af %s\"\r\nMsg_About_Line_Homepage                 = \"%s\"\r\n\r\n; Errors ---------------------------------------------------------------------\r\nMsg_Ok                                  = \"Ok\"\r\nMsg_Failed                              = \"Fejlede!\"\r\nMsg_Error_Base                          = \"Fejl: %s\"\r\nMsg_Error_Error                         = \"Fatalt: fejl i hentning af fejltype. Noget må være galt.\"\r\nMsg_Error_Memory                        = \"Ikke tilstraekkeligt med hukommelse\"\r\nMsg_Error_Param                         = \"Parameter \\\"%s\\\" er ugyldig\\n\"\r\nMsg_Error_Syntax                        = \"Syntaksfejl!\"\r\n\r\n; Errors: Video --------------------------------------------------------------\r\nMsg_Error_Video_Mode                    = \"Ikke i stand til at skifte til den oenskede oploesning (%dx%d).\"\r\nMsg_Error_Video_Mode_Back_To_GUI        = \"Skifter tilbage til den grafiske brugergraenseflade.\"\r\n\r\n; Errors: File ---------------------------------------------------------------\r\nMsg_Error_File_Not_Found                = \"Fil ikke fundet!\"\r\nMsg_Error_File_Read                     = \"Ikke i stand til at læse fra fil!\"\r\nMsg_Error_File_Empty                    = \"Filen er tom!\"\r\n\r\n; Errors: ZIP File -----------------------------------------------------------\r\nMsg_Error_ZIP_Not_Supported             = \"Denne version håndterer ikke ZIP filer!\"\r\nMsg_Error_ZIP_Loading                   = \"Ikke i stand til at læse ZIP fil!\"\r\nMsg_Error_ZIP_Internal                  = \"Intern fejl under læsning af ZIP fil!\"\r\n\r\n; Errors: Directory ----------------------------------------------------------\r\nMsg_Error_Directory_Open                = \"Kan ikke åbne biblioteket!\"\r\n\r\n; Miscellaneous --------------------------------------------------------------\r\nMsg_Must_Reset                          = \"Genstart spillet for, at ændringerne skal tage effekt\"\r\nMsg_No_ROM                              = \"Ingen ROM var indlæst!\"\r\n\r\n; Initialization -------------------------------------------------------------\r\nMsg_Init_Allegro                        = \"Initialiserer Allegro..\"\r\nMsg_Init_GUI                            = \"Indlaeser grafisk brugergraenseflade..\"\r\nMsg_Init_Completed                      = \"[KLAR]\"\r\n\r\n; Setup ----------------------------------------------------------------------\r\nMsg_Setup_Setup                         = \"Opsætning\"\r\nMsg_Setup_SampleRate_Select             = \"Sample rate:\"\r\n\r\n; Screenshots Capture --------------------------------------------------------\r\nMsg_Capture_Done                        = \"Skærmbillede gemt som %s\"\r\nMsg_Capture_Error                       = \"Ikke i stand til at gemme skærmbilledet!\"\r\nMsg_Capture_Error_File                  = \"Ikke i stand til at finde et gyldigt navn til skærmbilledet!\"\r\n\r\n; On-Board Memory ------------------------------------------------------------\r\nMsg_SRAM_Loaded                         = \"Indlæst SaveRAM fra disk (%d Kb)\"\r\nMsg_SRAM_Load_Unable                    = \"Ikke i stand til at indlæse SaveRAM fra disk\"\r\nMsg_SRAM_Wrote                          = \"Skrev SaveRAM til disk (%d Kb)\"\r\nMsg_SRAM_Write_Unable                   = \"Ikke i stand til at skrive SaveRAM til disk (%d Kb)\"\r\nMsg_93c46_Reset                         = \"Genstarter 93c46\"\r\nMsg_93c46_Loaded                        = \"Indlæst 93c46 EEPROM data fra disk (%d bytes)\"\r\nMsg_93c46_Load_Unable                   = \"Ikke i stand til at indlæse 93c46 EEPROM data fra disk\"\r\nMsg_93c46_Wrote                         = \"Skrev 93c46 EEPROM data til disk (%d bytes)\"\r\nMsg_93c46_Write_Unable                  = \"Ikke i stand til at skrive 93c46 EEPROM data til disk (%d bytes)\"\r\n\r\n; TV Type --------------------------------------------------------------------\r\nMsg_TVType_Set                          = \"TV-type er nu %s\"\r\nMsg_TVType_Info_Speed                   = \"(Original hastighed er %d Hz)\"\r\n\r\n; Blitters -------------------------------------------------------------------\r\nMsg_Blitters_Loading                    = \"Indlaeser MEKA.BLT (video modes / blitters)... \"\r\nMsg_Blitters_Error_Not_Enough           = \"Ikke tilstraekkelige blitters fundet! Check MEKA.BLT eller proev at geninstallere.\"\r\nMsg_Blitters_Error_Not_Found            = \"Blitter ikke fundet!\"\r\nMsg_Blitters_Error_Missing              = \"I linie %d: Intet blitternavn defineret til lagring!\"\r\nMsg_Blitters_Error_Unrecognized         = \"I linie %d: Ukendt variabel!\"\r\nMsg_Blitters_Set                        = \"Benytter nu \\\"%s\\\" fullskærms-blitter.\"\r\n\r\n; Nintendo -------------------------------------------------------------------\r\nMsg_NES_Activate                        = \"Fed VVS-mands-tilstand aktiveret!\"\r\nMsg_NES_Sucks                           = \"Fatal fejl: Brugeren bryder sig om Nintendo!\"\r\nMsg_NES_Mapper_Unknown                  = \"Ikke understøttet mapper: %d. Spillet burde ikke virke.\"\r\nMsg_NES_Deny_Facts                      = \"Du kan ikke benægte fakta.\"\r\n\r\n; Debugger -------------------------------------------------------------------\r\nMsg_Debug_Init                          = \"Initialiserer debugger.. \"\r\nMsg_Debug_Welcome                       = \"Velkommen til Meka Debugger!\"\r\nMsg_Debug_Not_Available                 = \"Debuggeren findes ikke i denne version!\"\r\nMsg_Debug_Trap_Read                     = \"Ved PC:%04X - Læs fra %04X\"\r\nMsg_Debug_Trap_Write                    = \"Ved PC:%04X - Skriv %02X til %04X\"\r\nMsg_Debug_Trap_Port_Read                = \"Ved PC:%04X - Port [%02X] læs\"\r\nMsg_Debug_Trap_Port_Write               = \"Ved PC:%04X - Port [%02X] Skriv %02X\"\r\n\r\n; Data Dumper ----------------------------------------------------------------\r\nMsg_DataDump_Mode_Ascii                 = \"Datadumps vil nu blive skrevet i ASCII mode.\"\r\nMsg_DataDump_Mode_Raw                   = \"Datadumps vil nu blive skrevet i Raw mode.\"\r\nMsg_DataDump_Error                      = \"Fejl ved oprettelse af fil til dump %s!\"\r\nMsg_DataDump_Error_OB_Memory            = \"Ingen on-board hukommelse at dumpe!\"\r\nMsg_DataDump_Error_Palette              = \"Ingen palette at dumpe!\"\r\nMsg_DataDump_Error_Sprites              = \"Ingen sprites at dumpe!\"\r\nMsg_DataDump_Main                       = \"Dumpet %s (%d %s) i %s mode\"\r\n\r\n; Documentation --------------------------------------------------------------\r\nMsg_Doc_BoxTitle                        = \"Dokumentation\"\r\nMsg_Doc_File_Error                      = \"Ikke i stand til at åbne dokumentationen!\"\r\nMsg_Doc_Enabled                         = \"Dokumentationen vises.\"\r\nMsg_Doc_Disabled                        = \"Dokumentationen vises ikke længere.\"\r\n\r\n; Sprite Flickering ----------------------------------------------------------\r\nMsg_Flickering_Auto                     = \"Sprite flickering vil blive håndteret automatisk.\"\r\nMsg_Flickering_Yes                      = \"Sprite flickering emulation er nu sat til.\"\r\nMsg_Flickering_No                       = \"Sprite flickering emulation er nu slået fra.\"\r\n\r\n; Layers ---------------------------------------------------------------------\r\nMsg_Layer_BG_Disabled                   = \"Baggrundsopdatering slået fra\"\r\nMsg_Layer_BG_Enabled                    = \"Baggrundsopdatering slået til\"\r\nMsg_Layer_Spr_Disabled                  = \"Sprites-opdatering slået fra\"\r\nMsg_Layer_Spr_Enabled                   = \"Sprites-opdatering slået til\"\r\n\r\n; Floppy Disk (FDC-765) ------------------------------------------------------\r\nMsg_FDC765_Unknown_Read                 = \"FDC765: Ukendt disk læsekommando %3i\"\r\nMsg_FDC765_Unknown_Write                = \"FDC765: Ukendt disk skrivekommando %3i\"\r\nMsg_FDC765_Disk_Too_Large1              = \"Diskkopi er større end forventet (%i > %i)\"\r\nMsg_FDC765_Disk_Too_Large2              = \"Yderligere data vil blive ignoreret\"\r\nMsg_FDC765_Disk_Too_Small1              = \"Diskkopi er mindre end forventet (%i < %i)\"\r\nMsg_FDC765_Disk_Too_Small2              = \"Manglende data vil blive regnet som tom\"\r\n\r\n; Palette Viewer -------------------------------------------------------------\r\nMsg_Palette_BoxTitle                    = \"Palette\"\r\nMsg_Palette_Disabled                    = \"Paletteviser slået fra\"\r\nMsg_Palette_Enabled                     = \"Paletteviser slået til\"\r\n\r\n; Message box ----------------------------------------------------------------\r\nMsg_Message_BoxTitle                    = \"Beskeder\"\r\nMsg_Message_Disabled                    = \"Beskeder slået fra\"\r\nMsg_Message_Enabled                     = \"Beskeder slået til\"\r\n\r\n; Technical Information box --------------------------------------------------\r\nMsg_TechInfo_BoxTitle                   = \"Teknisk information\"\r\nMsg_TechInfo_Disabled                   = \"Teknisk information slået fra\"\r\nMsg_TechInfo_Enabled                    = \"Teknisk information slået til\"\r\n\r\n; Tile Viewer ----------------------------------------------------------------\r\nMsg_TilesViewer_BoxTitle                = \"Tile-viser\"\r\nMsg_TilesViewer_Disabled                = \"Tile-viser slået fra\"\r\nMsg_TilesViewer_Enabled                 = \"Tile-viser slået til\"\r\nMsg_TilesViewer_Tile                    = \"Tile %d ($%X) @ %s\"\r\n\r\n; Rapid Fire -----------------------------------------------------------------\r\nMsg_RapidFire_JxBx_On                   = \"Rapid Fire er nu aktiveret for Spiller %d Knap %d\"\r\nMsg_RapidFire_JxBx_Off                  = \"Rapid Fire er nu deaktiveret for Spiller %d Knap %d\"\r\n\r\n; FM Unit (YM-2413 chipset) --------------------------------------------------\r\nMsg_FM_Enabled                          = \"FM-enheds (YM-2413 chipset) emulering slået til\"\r\nMsg_FM_Disabled                         = \"FM-enheds (YM-2413 chipset) emulering slået fra\"\r\n\r\n; Country --------------------------------------------------------------------\r\nMsg_Country_European_US                 = \"Emuleret maskine er nu Europæisk/Amerikansk\"\r\nMsg_Country_JAP                         = \"Emuleret maskine er nu Japansk\"\r\n\r\n; Patching System ------------------------------------------------------------\r\nMsg_Patch_Loading                       = \"Indlaeser MEKA.PAT (patcher)... \"\r\n;Msg_Patch_Missing                       = \"I linie %d: Ingen checksum defineret for instruktion!\"\r\n;Msg_Patch_Unrecognized                  = \"I linie %d: Ukendt instruktion!\"\r\n;Msg_Patch_Out_of_Bound                  = \"Under patching af ROM: prøver at skrive uden for grænsen, ved position $%02X. Afbryder patch.\"\r\n\r\n; 3-D Glasses ----------------------------------------------------------------\r\nMsg_Glasses_Enabled                     = \"3-D brille emulation slået til\"\r\nMsg_Glasses_Disabled                    = \"3-D brille emulation slået fra\"\r\nMsg_Glasses_Show_Both                   = \"3-D effekt uforandret.\"\r\nMsg_Glasses_Show_Left                   = \"3-D effekt slået fra ved kun at vise venstre side.\"\r\nMsg_Glasses_Show_Right                  = \"3-D effekt slået fra ved kun at vise højre side.\"\r\nMsg_Glasses_Com_Port                    = \"3-D brille emulation slået til gennem COM port %d.\"\r\n;Msg_Glasses_Com_Port2                   = \"(editér MEKA.CFG for at ændre COM port)\"\r\nMsg_Glasses_Unsupported                 = \"Det ser ikke ud til at dette spil understøtter 3-D briller.\"\r\n\r\n; Inputs Initialization ------------------------------------------------------\r\nMsg_Inputs_Joy_Init                     = \"Initialiserer joystick.. \"\r\nMsg_Inputs_Joy_Init_None                = \"Intet fundet.\"\r\nMsg_Inputs_Joy_Init_Found               = \"%d fundet.\"\r\nMsg_Inputs_Joy_Calibrate_Error          = \"Fejl under kalibrering af joystick. Afbryder.\"\r\n\r\n; Inputs ---------------------------------------------------------------------\r\nMsg_Inputs_Joypad                       = \"Tilbehør: Joypad\"\r\nMsg_Inputs_LightPhaser                  = \"Tilbehør: Light Phaser\"\r\nMsg_Inputs_PaddleControl                = \"Tilbehør: Paddle Control\"\r\nMsg_Inputs_SportsPad                    = \"Tilbehør: Sports Pad\"\r\nMsg_Inputs_GraphicBoard                 = \"Tilbehør: Terebi Oekaki Graphic Board\"\r\nMsg_Inputs_Play_Digital                 = \"Kontrol med digital styreenhed\"\r\nMsg_Inputs_Play_Mouse                   = \"Kontrol med analog styreenhed (mus)\"\r\nMsg_Inputs_Play_Pen                     = \"Kontrollér pennen med musen\\nHøjre-klik simulerer, at pennen løftes\"\r\n\r\n; Inputs Configuration -------------------------------------------------------\r\nMsg_Inputs_Config_BoxTitle              = \"Input Konfiguration\"\r\n\r\n; Inputs Sources -------------------------------------------------------------\r\nMsg_Inputs_Src_Loading                  = \"Indlaeser MEKA.INP (definering af styreenheder)... \"\r\nMsg_Inputs_Src_Not_Enough               = \"Ikke tilstraekkeligt input af styreenheder! Check MEKA.INP eller proev at geninstallere meka.\"\r\nMsg_Inputs_Src_Missing                  = \"I linie %d: Ingen styreenhed defineret til lagring af vaerdi!\"\r\nMsg_Inputs_Src_Equal                    = \"I linie %d: Lighedstegn savnes til vaerditildeling af variabel!\"\r\nMsg_Inputs_Src_Unrecognized             = \"I linie %d: Ukendt variabel \\\"%s\\\"!\"\r\nMsg_Inputs_Src_Syntax_Param             = \"I linie %d: Syntax-fejl i variabel parameter!\"\r\nMsg_Inputs_Src_Inconsistency            = \"I linie %d: Uforenlighed med tidligere indstillinger!\"\r\nMsg_Inputs_Src_Map_Keyboard             = \"Tryk på den tast, du vil tildele denne handling til\"\r\nMsg_Inputs_Src_Map_Keyboard_Ok          = \"Handling tildelt til tast \\\"%s\\\".\"\r\nMsg_Inputs_Src_Map_Joypad               = \"Tryk på den tast/akse, du vil tildele denne handling til\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_A          = \"Handling tildelt til joypad stik %i, akse %i, %c.\"\r\nMsg_Inputs_Src_Map_Joypad_Ok_B          = \"Handling tildelt til joypad knap %i.\"\r\nMsg_Inputs_Src_Map_Mouse                = \"Tryk på den knap, du vil tildele denne handling til\"\r\nMsg_Inputs_Src_Map_Mouse_Ok_B           = \"Handling tildelt til mus-knap %i.\"\r\nMsg_Inputs_Src_Map_Mouse_No_A           = \"Desværre - mus-akserne kan ikke ændres\"\r\nMsg_Inputs_Src_Map_Cancelled            = \"Tildeling afbrudt!\"\r\n\r\n; Machine --------------------------------------------------------------------\r\nMsg_Machine_Pause                       = \"Maskineemulering pauset\"\r\nMsg_Machine_Resume                      = \"Maskineemulering fortsat\"\r\nMsg_Machine_Reset                       = \"Maskine genstartet\"\r\n\r\n; Filenames Database ---------------------------------------------------------\r\n;Msg_VFN_Loading                         = \"Indlaeser MEKA.VFN (virtuelle filnavne)... \"\r\n\r\n; DataBase / Names -----------------------------------------------------------\r\nMsg_DB_Loading                          = \"Indlaeser MEKA.NAM (spiltitler)... \"\r\nMsg_DB_Name_Default                     = \"Spilskærm\"\r\nMsg_DB_Name_NoCartridge                 = \"Ingen spilkasette\"\r\n\r\n; Configuration File ---------------------------------------------------------\r\nMsg_Config_Loading                      = \"Indlaeser %s (konfiguration)... \"\r\n\r\n; Datafile -------------------------------------------------------------------\r\nMsg_Datafile_Loading                    = \"Indlaeser MEKA.DAT (resourcer)... \"\r\n\r\n; Drivers --------------------------------------------------------------------\r\nMsg_Driver_Unknown                      = \"Fatalt: Ukendt maskinedriver!\"\r\n\r\n; Overdump detection ---------------------------------------------------------\r\n;Msg_OverDump                            = \"Denne ROM indeholder %d gange den nødvendige data.\\nDownload venligst \\\"SMS Checker\\\" for, at checke den (http://www.smspower.org/maxim/smschecker/).\"\r\n\r\n; Sound ----------------------------------------------------------------------\r\nMsg_Sound_Init                          = \"Initialiserer lydsystem..\"\r\nMsg_Sound_Init_Error_Audio              = \" - Fejl under aabning af lydsystem. Proev et andet kort og/eller en anden sample rate.\"\r\nMsg_Sound_Init_Error_Blaster            = \" - BLASTER variabel ikke fundet, slaar FM lyd fra!\"\r\nMsg_Sound_Init_Error_Blaster_A          = \" - BLASTER variabel indeholder ikke adresse (A=xxx), slaar FM lyd fra!\"\r\nMsg_Sound_Init_Error_Voices             = \" - Voices initialisation fejlede.\"\r\nMsg_Sound_Init_Error_Voice_N            = \" - Voice #%d dannelse fejlede.\"\r\nMsg_Sound_Init_Soundcard                = \" - Initialiserer lydkort ved %d Hz\"\r\nMsg_Sound_Init_Soundcard_No             = \"Kan ikke initialisere lyd: intet lydkort valgt!\"\r\nMsg_Sound_Init_SN76496                  = \" - SN76496 digital emulator:\"\r\nMsg_Sound_Init_YM2413_Digital           = \" - YM2413 digital emulator:\"\r\nMsg_Sound_Stream_Error                  = \"Lyd buffer stop. Genstarter datastrømmen.\"\r\nMsg_Sound_Volume_Changed                = \"Volumen ændret til %d%%.\"\r\n\r\n; Theme ----------------------------------------------------------------------\r\nMsg_Theme_Loading                       = \"Indlaeser MEKA.THM (brugergraenseflade temaer)... \"\r\nMsg_Theme_Error_Not_Enough              = \"Ikke tilstraekkelige temaer fundet! Check MEKA.THM eller proev at geninstallere.\"\r\nMsg_Theme_Error_Missing_Theme_Name      = \"I linie %d: Intet tema defineret til lagring af vaerdi!\"\r\nMsg_Theme_Error_BG_Big                  = \"Baggrundsbilledet er for småt til at passe med heltalsskalering!\"\r\nMsg_Theme_Error_BG                      = \"Fejl under indlæsning af billede associeret med temaet!\"\r\nMsg_Theme_Error_BG_FileName             = \"(%s)\"\r\n\r\n; Loading ROM / Disk ---------------------------------------------------------\r\nMsg_LoadROM_Loading                     = \"Indlæser ROM... \"\r\nMsg_LoadROM_Success                     = \"Indlæste %s\"\r\nMsg_LoadDisk_Success                    = \"Indlæste %s som en diskette\"\r\nMsg_LoadROM_Comment                     = \"Kommentar: %s\"\r\nMsg_LoadROM_Warning                     = \"-Advarsel-\"\r\nMsg_LoadROM_Bad_Dump_Long               = \"Denne ROM er kendt som et dårligt dump.\\nDen fungerer muligvis ikke ordentligt. Download venligst SMS Checker for, at checke den (http://www.smspower.org/maxim/smschecker/).\"\r\nMsg_LoadROM_Bad_Dump_Short              = \"Advarsel - Denne ROM er kendt som et dårligt dump.\"\r\nMsg_LoadROM_Product_Num                 = \"Produkt Kode: %s\"\r\nMsg_LoadROM_SDSC                        = \"-SDSC Header-\"\r\nMsg_LoadROM_SDSC_Name                   = \"Navn: %s\"\r\nMsg_LoadROM_SDSC_Version                = \"Version: %d.%02d\"\r\nMsg_LoadROM_SDSC_Date                   = \"Dato: %04d.%02d.%02d\"\r\nMsg_LoadROM_SDSC_Author                 = \"Udvikler: %s\"\r\nMsg_LoadROM_SDSC_Release_Note           = \"Udgivelses Note: %s\"\r\nMsg_LoadROM_SDSC_Unknown                = \"<Ukendt>\"\r\nMsg_LoadROM_SDSC_Error                  = \"<Fejl>\"\r\n\r\n; File Browser ---------------------------------------------------------------\r\nMsg_FileBrowser_BoxTitle                = \"Indlæs ROM\"\r\nMsg_FileBrowser_Drive                   = \"[Drev %c]\"\r\nMsg_FileBrowser_Load                    = \"Indlæs\"\r\nMsg_FileBrowser_Close                   = \"Luk\"\r\nMsg_FileBrowser_LoadNames               = \"Indlæs Navne\"\r\nMsg_FileBrowser_ReloadDir               = \"Opdatér\"\r\n\r\n; FM Editor ------------------------------------------------------------------\r\nMsg_FM_Editor_BoxTitle                  = \"FM Instrument Editor\"\r\nMsg_FM_Editor_Enabled                   = \"FM Instrument Editor slået til\"\r\nMsg_FM_Editor_Disabled                  = \"FM Instrument Editor slået fra\"\r\n\r\n; Video Options --------------------------------------------------------------\r\nMsg_Frameskip_Auto                      = \"Frameskip værdi sat til: Automatisk (%d Hz)\"\r\nMsg_Frameskip_Standard                  = \"Frameskip værdi sat til: 1/%d\"\r\nMsg_FPS_Counter_Enabled                 = \"FPS tæller slået til\"\r\nMsg_FPS_Counter_Disabled                = \"FPS tæller slået fra\"\r\n\r\n; Logging --------------------------------------------------------------------\r\nMsg_Log_Need_Param                      = \"LOG-mulighed behoever et filnavn!\"\r\nMsg_Log_Session_Start                   = \"-- Logning startet %s\"\r\n\r\n; Save States ----------------------------------------------------------------\r\nMsg_Load_Need_Param                     = \"LOAD-muligheden har brug for et tilstandsnummer!\"\r\nMsg_Load_Error                          = \"Fejl under åbning af %s!\"\r\nMsg_Load_Not_Valid                      = \"Filen %s er ikke en gyldig %s spiltilstand!\"\r\nMsg_Load_Success                        = \"Tilstand indlæst fra %s\"\r\nMsg_Load_Version                        = \"%s er ikke en understøttet spiltilstand version!\"\r\nMsg_Load_Wrong_System                   = \"%s er ikke en spiltilstand for dette system!\"\r\nMsg_Load_Massage                        = \"Filen er i MSD format - konverterer\"\r\nMsg_Save_Not_in_BIOS                    = \"Kan ikke gemme under kørsel af BIOS!\"\r\nMsg_Save_Error                          = \"Fejl under skrivning til %s!\"\r\nMsg_Save_Success                        = \"Tilstand gemt som %s\"\r\nMsg_Save_Slot                           = \"Nuværende spiltilstands-nummer er: %d\"\r\n\r\n; Options --------------------------------------------------------------------\r\nMsg_Options_BoxTitle                    = \"Indstilninger\"\r\nMsg_Options_Close                       = \"Luk\"\r\n;Msg_Options_BIOS_Enable                 = \"Vis internt BIOS logo hvis tilgængeligt i systemet.\"\r\n;Msg_Options_Product_Number              = \"Vis spillets produkt kode hvis tilgængeligt.\"\r\n;Msg_Options_Bright_Palette              = \"Lys palette for Master System / Game Gear.\"\r\nMsg_Options_Load_Close                  = \"Luk filbrowseren efter åbning af et spil.\"\r\nMsg_Options_Load_FullScreen             = \"Skift til fuld skærm efter åbning af et spil.\"\r\n;Msg_Options_VFN_Support                 = \"Vis lange filnavne og landeflag.\"\r\nMsg_Options_FullScreen_Messages         = \"Vis beskeder i fuldskærms mode.\"\r\nMsg_Options_GUI_VSync                   = \"Vent på VSync i interface mode.\"\r\nMsg_Options_NES_Enable                  = \"Mario er ikke en fed VVS-mand.\"\r\n\r\n; Languages / Localization ---------------------------------------------------\r\nMsg_Language_Set                        = \"Sprog sat til %s\"\r\nMsg_Language_Set_Warning                = \"NB: det er anbefalet at du genstarter MEKA for at være sikker på at al tekst opdateres.\"\r\n\r\n; Sound Dumping --------------------------------------------------------------\r\nMsg_Sound_Dumping_Start                 = \"Startede dumpning af lyd til %s\"\r\nMsg_Sound_Dumping_Stop                  = \"Stoppede dumpning af lyd (%2.02f sekunder logget)\"\r\nMsg_Sound_Dumping_Error_File_1          = \"Kan ikke finde et gyldigt filnavn til lyd-dump!\"\r\nMsg_Sound_Dumping_Error_File_2          = \"Fejl under åbning af skrive-filen %s for dumpning!\"\r\nMsg_Sound_Dumping_VGM_Acc_Frame         = \"VGM dumps vil nu være frame-eksakte (mindre filer, undgå voices)\"\r\nMsg_Sound_Dumping_VGM_Acc_Sample        = \"VGM dumps vil nu være sample-eksakte (større filer, dump voices)\"\r\nMsg_Sound_Dumping_VGM_Acc_Change        = \"(VGM dumpning bliver nødt til at blive genstartet for at tage hensyn til den nye kvalitet)\"\r\n\r\n; Menu: Main -----------------------------------------------------------------\r\nMsg_Menu_Main                           = \"FILER\"\r\nMsg_Menu_Main_LoadROM                   = \"Indlæs ROM..\"\r\nMsg_Menu_Main_FreeROM                   = \"Frigør ROM\"\r\nMsg_Menu_Main_SaveState_Save                 = \"Gem Savestate\"\r\nMsg_Menu_Main_SaveState_Load                 = \"Hent Savestate\"\r\nMsg_Menu_Main_Options                   = \"Indstilninger..\"\r\nMsg_Menu_Main_Language                  = \"Sprog\"\r\nMsg_Menu_Main_Quit                      = \"Afslut\"\r\n\r\n; Menu: Debug ----------------------------------------------------------------\r\nMsg_Menu_Debug                          = \"DEBUG\"\r\nMsg_Menu_Debug_Dump                     = \"Dump\"\r\n\r\n; Menu: Machine --------------------------------------------------------------\r\nMsg_Menu_Machine                        = \"MASKINE\"\r\nMsg_Menu_Machine_Power                  = \"Strøm\"\r\nMsg_Menu_Machine_Power_On               = \"Tænd\"\r\nMsg_Menu_Machine_Power_Off              = \"Sluk\"\r\nMsg_Menu_Machine_Region                 = \"Land\"\r\nMsg_Menu_Machine_Region_Export          = \"Europæisk/Amerikansk\"\r\nMsg_Menu_Machine_Region_Japan           = \"Japansk\"\r\nMsg_Menu_Machine_TVType                 = \"TV Type\"\r\nMsg_Menu_Machine_TVType_NTSC            = \"NTSC\"\r\nMsg_Menu_Machine_TVType_PALSECAM        = \"PAL/SECAM\"\r\n;Msg_Menu_Machine_PauseEmulation         = \"Hardware Pause\"\r\n;Msg_Menu_Machine_ResetEmulation         = \"Hardware Genstart\"\r\n\r\n; Menu: Video ----------------------------------------------------------------\r\nMsg_Menu_Video                          = \"VIDEO\"\r\nMsg_Menu_Video_FullScreen               = \"Fuld skærm\"\r\nMsg_Menu_Video_Themes                   = \"Temaer\"\r\nMsg_Menu_Video_Blitters                 = \"Blitters\"\r\nMsg_Menu_Video_Layers                   = \"Lag\"\r\nMsg_Menu_Video_Layers_Sprites           = \"Sprites\"\r\nMsg_Menu_Video_Layers_Background        = \"Baggrund\"\r\nMsg_Menu_Video_Flickering               = \"Flickering\"\r\nMsg_Menu_Video_Flickering_Auto          = \"Auto\"\r\nMsg_Menu_Video_Flickering_Yes           = \"Ja\"\r\nMsg_Menu_Video_Flickering_No            = \"Nej\"\r\nMsg_Menu_Video_3DGlasses                = \"3-D Briller\"\r\nMsg_Menu_Video_3DGlasses_Enabled        = \"Slået til\"\r\nMsg_Menu_Video_3DGlasses_ShowBothSides  = \"Vis begge sider\"\r\nMsg_Menu_Video_3DGlasses_ShowLeftSide   = \"Vis venstre side\"\r\nMsg_Menu_Video_3DGlasses_ShowRightSide  = \"Vis højre side\"\r\nMsg_Menu_Video_3DGlasses_UsesCOMPort    = \"Benytter briller via COM Port\"\r\n\r\n; Menu: Sound ----------------------------------------------------------------\r\nMsg_Menu_Sound                          = \"LYD\"\r\nMsg_Menu_Sound_FM                       = \"FM Enhed\"\r\nMsg_Menu_Sound_FM_Enabled               = \"Slået til\"\r\nMsg_Menu_Sound_FM_Disabled              = \"Slået fra\"\r\nMsg_Menu_Sound_FM_Editor                = \"Instrument Editor\"\r\nMsg_Menu_Sound_Volume                   = \"Volume\"\r\nMsg_Menu_Sound_Volume_Mute              = \"Mute\"\r\nMsg_Menu_Sound_Volume_Value             = \"%d%%\"\r\nMsg_Menu_Sound_Rate                     = \"Rate\"\r\nMsg_Menu_Sound_Rate_Hz                  = \"%d Hz\"\r\nMsg_Menu_Sound_Channels                 = \"Kanaler\"\r\nMsg_Menu_Sound_Channels_Tone            = \"Tone %d\"\r\nMsg_Menu_Sound_Channels_Noises          = \"Noises\"\r\nMsg_Menu_Sound_Capture                     = \"Dump\"\r\nMsg_Menu_Sound_Capture_WAV_Start           = \"WAV Start\"\r\nMsg_Menu_Sound_Capture_WAV_Stop            = \"WAV Stop\"\r\nMsg_Menu_Sound_Capture_VGM_Start           = \"VGM Start\"\r\nMsg_Menu_Sound_Capture_VGM_Stop            = \"VGM Stop\"\r\nMsg_Menu_Sound_Capture_VGM_SampleAccurate  = \"VGM Sample-Eksakt\"\r\n\r\n; Menu: Inputs ---------------------------------------------------------------\r\nMsg_Menu_Inputs                         = \"STYREENHEDER\"\r\nMsg_Menu_Inputs_Joypad                  = \"Joypad\"\r\nMsg_Menu_Inputs_LightPhaser             = \"Light Phaser\"\r\nMsg_Menu_Inputs_PaddleControl           = \"Paddle Control\"\r\nMsg_Menu_Inputs_SportsPad               = \"Sports Pad\"\r\nMsg_Menu_Inputs_GraphicBoard            = \"Graphic Board (Terebi Oekaki)\"\r\nMsg_Menu_Inputs_SK1100                  = \"Sega Keyboard\"\r\nMsg_Menu_Inputs_RapidFire               = \"Rapid Fire\"\r\nMsg_Menu_Inputs_RapidFire_PxBx          = \"Spiller %d Knap %d\"\r\nMsg_Menu_Inputs_Configuration           = \"Konfiguration..\"\r\n\r\n; Menu: Tools ----------------------------------------------------------------\r\nMsg_Menu_Tools                          = \"VÆRKTØJER\"\r\nMsg_Menu_Tools_Messages                 = \"Beskeder..\"\r\nMsg_Menu_Tools_Palette                  = \"Palette..\"\r\nMsg_Menu_Tools_TilesViewer              = \"Tiles..\"\r\nMsg_Menu_Tools_TechInfo                 = \"Teknisk Info..\"\r\n\r\n; Menu: Help -----------------------------------------------------------------\r\nMsg_Menu_Help                           = \"HJÆLP\"\r\nMsg_Menu_Help_Documentation             = \"Dokumentation..\"\r\nMsg_Menu_Help_Compat                    = \"Kompatibilitetsliste..\"\r\nMsg_Menu_Help_Multiplayer_Games         = \"Multiplayer-spilsliste..\"\r\nMsg_Menu_Help_Changes                   = \"Ændringer..\"\r\nMsg_Menu_Help_About                     = \"Om..\"\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n; [Test Accents]\r\n; WIP\r\n; Msg_Welcome                           = \"Test accent: eéèêë aàâä iîï uù ç\"\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/meka.nam",
    "content": ";-----------------------------------------------------------------------------\r\n; MEKA - Software Database\r\n; Last updated 2025/10/12\r\n;-----------------------------------------------------------------------------\r\n; Database maintained by Omar Cornut (Bock).\r\n; This file relates to an important part of the MEKA / SMS Power projects,\r\n; that is to dump, archive, label and version ROM images properly based\r\n; mostly on verified sources (aka real cartridges) and reverse engineering.\r\n; See dumping logs thread\r\n; http://www.smspower.org/forums/viewtopic.php?t=8087\r\n;-----------------------------------------------------------------------------\r\n; Note about data preprocessing that is done by MEKA before applying CRCs:\r\n; - Duplicated data removed (2x/3x/4x+ overdumps)\r\n; - Sega 8-bits:\r\n;   - 512-bytes header removed\r\n;   -  64-bytes footer removed\r\n; - ColecoVision:\r\n;   - 128-bytes header removed\r\n;   - 512-bytes footer removed\r\n; Dumps nowadays shouldn't have any of those, but old may.\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Cartridge Hardware (\"Mapper\") Identifiers\r\n; From MEKA sources in srcs/mappers.h\r\n;-----------------------------------------------------------------------------\r\n;   0 : standard sms/gg sega mapper, optional SRAM\r\n;   1 : 32KB of RAM mapped at 0x8000-0xFFFF\r\n;   2 : colecovisions\r\n;   3 : code masters mapper, registers at 0x0000, 0x4000, 0x8000\r\n;   4 : sega mapper with 93c46 eeprom\r\n;   5 : sg-1000 (currently incorrectly emulating 4KB of RAM instead of 2KB)\r\n;   6 : master system action replay\r\n;   7 : terebi oekaki (graphic tablet)\r\n;   8 : sf-7000\r\n;   9 : sms korean mapper, mapping register at 0xA000\r\n;  10 : sms display unit BIOS\r\n;  11 : no mapper, ROM up to 48KB (typically 32KB)\r\n;  12 : sms korean msx type 8KB banks, registers at 0x0000->0x0003\r\n;  13 : sms korean for Janggun-ui Adeul\r\n;  14 : sms 4 Pak All Action\r\n;  15 : sg-1000 II with taiwanese memory expansion adapter, 8KB RAM from 0x2000->0x3FFF + regular 2KB RAM mapped at 0xC000-0xFFFF\r\n;  16 : sms korean xx-in-1, register at 0xFFFF mapping 32 KB at 0x0000->0x8000 (hi-com cartridges)\r\n;  17 : sc-3000 survivors multicart.\r\n;  18 : sms korean xx-in-1, register at 0x0000 mapping 8 KB at 0x8000, register at 0x0100 mapping 8 KB at 0x4000, register at 0x0200 mapping 8 KB at 0xA000, register at 0x0300 mapping 8 KB at 0x6000\r\n;  19 : sms korean xx-in-1, register at 0x2000 mapping 8x4 KB 0x4000-0xBFFF using register xored with 0x1F, 0x1E, 0x1D, 0x1C. 0x0000-0x3FFF stuck on bank 0.\r\n;  20 : sms korean xx-in-1, register at 0xBFFC, sms+msx\r\n;  21 : sms korean xx-in-1, register at 0xFFFE\r\n;  22 : sms korean xx-in-1, register at 0xFFF3 and 0xFFFC (mirrored 0xBFF3, 0xBFFC)\r\n;  23 : sms korean xx-in-1, register at 0x0000, xored with 0xFF\r\n;  24 : sms korean xx-in-1, register at 0xFFF0, 0xFFFE, 0xFFFE (used in MD multicart with SMS games)\r\n;  25 : sms korean xx-in-1, register at 0xFFF5, 0xFFFE, 0xFFFE (used in MD multicart with SMS games)\r\n;  26 : sms korean xx-in-1, register at 0xFFFA, 0xFFFE, 0xFFFE (used in MD multicart with SMS games)\r\n;  27 : sms korean xx-in-1, register at 0x2000\r\n;  39 : sms korean xx-in-1, register at 0x2000 (11 Hap Gam-Boy)\r\n;  40 : sms korean xx-in-1, register at 0x8000\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; State of the Database:\r\n;-----------------------------------------------------------------------------\r\n; All data are now being converted to a new, better format. In addition,\r\n; extended analysis and verification will be made on a case by case basis,\r\n; before adding entries to the new format.\r\n; - Names are verified based on original media/cartridge, box and manuals.\r\n;   I am now paying particular attention to exact casing.\r\n; - Every cartridge is being redumped and verified.\r\n; - Each ROM is properly associated to countries where it has been released.\r\n;   In some case, not all country version were dumped and some countries are\r\n;   being associated to a ROM under the assumption that the version of this\r\n;   country contains the same data as the other one.\r\n;     e.g.: European game dumped, Brazilian version assumed to be the same.\r\n;   Whenever possible, everything is being dumped, and country association\r\n;   are confirmed or corrected as new cartridges are being dumped.\r\n; Entries in the new format are therefore to be all considered as GOOD and\r\n; associated to GOOD dumps.\r\n; Of course, it could always happen that errors were left, but in overall\r\n; the new database content will be more much exhaustive and accurate than\r\n; any existing database.\r\n;-----------------------------------------------------------------------------\r\n; Approximately 95% of the database was converted.\r\n;-----------------------------------------------------------------------------\r\n; The top part of this file consists in verified entries in the new format.\r\n; The bottom part consists in entries in the old format. Once every entries\r\n; will be verified and converted, the old format will be made obsolete.\r\n; ColecoVision entries will most likely not be updated.\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; DATA - SEGA MASTER SYSTEM (SMS)\r\n;-----------------------------------------------------------------------------\r\n\r\nSMS ba5ec0e3 0707EB856DC38BC7   128 Hap (KR)/COUNTRY=KR/EMU_MAPPER=19\r\nSMS 1b3e032e 8479DA42A3D4F67A   2 Hap in 1 (Moai-ui bomul, David-2)/COUNTRY=KR/EMU_MAPPER=27\r\nSMS 4342db9d CE8A9AB977B6FE2A   11 Hap Gam-Boy (KR)/COUNTRY=KR/EMU_MAPPER=39\r\nSMS f0f35c22 02079D9D9AF6B27B   20 em 1/COUNTRY=BR\r\nSMS 56dcb2d4 9FA930C396F93600   3D Gunner [Proto]/EMU_MAPPER=0/EMU_INPUTS=LIGHTPHASER/EMU_3D/EMU_LP_FUNC=2/COMMENT=Prototype version of the unreleased game.\r\nSMS a67f2a5c 4EB5F14E8488C9E9   4 PAK All Action/COUNTRY=AU/EMU_MAPPER=14\r\nSMS 060d6a7c 89A31578AA7C44DD   94 Super World Cup Soccer/COUNTRY=KR/PRODUCT_NO=DS-G403\r\nSMS 887d9f6b 9EB1F06967AA8DBA   Ace of Aces/COUNTRY=EU/PRODUCT_NO=7054\r\nSMS e2d765ad EF9CEC3C51B11338   Action Fighter [v0] [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS d91b340d 2CCEA6A00321A4F8   Action Fighter [v1]/COUNTRY=JP,DE,IT/PRODUCT_NO=G-1305,41008,5055\r\nSMS 3658f3e0 2BCDA99F0321A4F8   Action Fighter [v2]/COUNTRY=US,EU,IT,BR,KR/PRODUCT_NO=5055,GB-1305\r\nSMS 8418f438 9D9BC6348F4446B5   Action Fighter/COUNTRY=TW/PRODUCT_NO=M-1216\r\nSMS 72420f38 40698151916E7D09   Addams Family, The/COUNTRY=EU/PRODUCT_NO=MK-27067-50/EMU_TVTYPE=PAL\r\nSMS 15576613 AFA2AEA50041A17A   Aerial Assault/COUNTRY=US,BR/PRODUCT_NO=7041\r\nSMS ecf491cf 8BB24BB9F2B8E62F   Aerial Assault/COUNTRY=EU/PRODUCT_NO=7041\r\nSMS 6630e5fd 63D7FA2EFB6F6BC9   Aerial Assault [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-11/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 1c951f8e 69AAC8EBB8D1F6BB   After Burner/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1340,9001\r\nSMS 4f1be9fa 3B58EA21D5D9EDC7   Agigongnyong Dooly/COUNTRY=KR/COMMENT=Korean language version of \"The Dinosaur Dooley\" (also a Korean cartridge). Music tracks and a few artworks are different.\r\nSMS 8b43d21d 656A7A10AFC7AD84   Air Rescue/COUNTRY=EU,BR,KR/PRODUCT_NO=7102,GB2018JG\r\nSMS c8718d40 836571585D162CB0   Aladdin (Disney's)/COUNTRY=EU,BR,AU,KR/PRODUCT_NO=9027,028420,GB94001JG\r\nSMS d8c4165b 7AF7BA94F1EB0263   Aleste/COUNTRY=JP/PRODUCT_NO=G-1352/COMMENT=Japanese version of \"Power Strike\".\r\nSMS 013c0a94 02B8FA4E6DCA25A2   Alex Kidd: High-Tech World/COUNTRY=US,EU,BR/PRODUCT_NO=5116,023020/COMMENT=Export version of \"Anmitsu Hime\".\r\nSMS 2d7fabb2 19B9164073CE1483   Alex Kidd: High-Tech World [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS c13896d5 FCA1E2B346E4B6EE   Alex Kidd: The Lost Stars/COUNTRY=JP,US,EU,BR,KR/PRODUCT_NO=G-1347,7005,GB-2347/COMMENT=English label has a typo, saying \"Alex Kidd: The Lost Star\".\r\nSMS 17a40e29 7D8119AF99740429   Alex Kidd in Miracle World [v0]/COUNTRY=US,IT,DE/PRODUCT_NO=5067,41013\r\nSMS aed9aac4 9E9ACFFA4B7344FD   Alex Kidd in Miracle World [v1]/COUNTRY=US,EU,BR/PRODUCT_NO=5067\r\nSMS 08c9ec91 8F4496EF846F02B3   Alex Kidd no Miracle World/COUNTRY=JP/PRODUCT_NO=G-1306\r\nSMS 6f8e46cf B20081B6495EBAB6   Alex Kidd in Miracle World [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-10,HG 202-01/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Alex Kido\".\r\nSMS d2417ed7 7ACEE06A678FF583   Alex Kidd in Shinobi World/COUNTRY=US,EU,BR/PRODUCT_NO=7044\r\nSMS 82038ad4 8C8CBA6269074D0F   Alf/COUNTRY=US,BR/PRODUCT_NO=5111\r\nSMS 08bf3de3 99C9E641B75585E6   Alibaba and 40 Thieves/COUNTRY=KR/EMU_COUNTRY=1   ; [EDITOR-NOTE] May run on export system, haven't tested yet but the game requires a non-zero RAM clearing pattern typically left over of Japanese BIOS.\r\nSMS b618b144 2C339F1D709F32A4   Alien 3/COUNTRY=EU,BR/PRODUCT_NO=MK-27043-50\r\nSMS 7f30f793 122165765570939A   Alien Storm/COUNTRY=EU,BR/PRODUCT_NO=7075\r\nSMS 5cbfe997 468211BFBE1EC3C9   Alien Syndrome/COUNTRY=US,EU,BR/PRODUCT_NO=7006\r\nSMS 4cc11df9 DCF4C5DA46B94250   Alien Syndrome/COUNTRY=JP/PRODUCT_NO=G-1339\r\nSMS c148868c C6BA17CDFFEE6748   Alien Syndrome [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS bba2fe98 B604DAE9BC58B6B9   Altered Beast/COUNTRY=US,EU,BR/PRODUCT_NO=7018\r\nSMS f499034d EC195693CDC41170   Andre Agassi Tennis/COUNTRY=EU,BR/PRODUCT_NO=MK-27051-50,025420\r\nSMS fff63b0b 706FE01391B816CF   Anmitsu Hime/COUNTRY=JP/PRODUCT_NO=G-1328/COMMENT=Japanese version of \"Alex Kidd: High-Tech World\".   ; [EDITOR NOTE] SMS checksum is wrong, was verified on original cartridge.\r\nSMS 7b27202f C546819D9058925D   American Baseball/COUNTRY=EU,BR/PRODUCT_NO=7019\r\nSMS 3727d8b2 F5E365059B891882   American Pro Football/COUNTRY=EU/PRODUCT_NO=7020/COMMENT=European version of \"Walter Payton Football\".\r\nSMS e4163163 52E64F6379BC4E93   Arcade Smash Hits/COUNTRY=EU/PRODUCT_NO=27032-50\r\nSMS bae75805 B1B3520AE6A57C39   Argos no Juujiken/COUNTRY=JP/PRODUCT_NO=001/COMMENT=Also known in the west as \"Rygar\".\r\nSMS 5e4b454e 3E5F1176876F3DA9   Argos no Juujiken [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-02/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Alocos\".\r\nSMS f4b3a7bd A7AF89DB1688A107   Ariel - The Little Mermaid (Disney's)/COUNTRY=BR/PRODUCT_NO=026350/COMMENT=This is a port from the Game Gear version.\r\nSMS ae705699 8A53E8116C3E95EB   Ashura/COUNTRY=JP/PRODUCT_NO=G-1307/COMMENT=Japanese version of \"Secret Command\" (Europe) and \"Rambo - First Blood Part II\" (USA).\r\nSMS 0bd8da96 61A53B8B8924BFC8   Assault City/COUNTRY=EU/PRODUCT_NO=7034/COMMENT=A Light Phaser version also exists.\r\nSMS 861b6e79 3192D86747C4C62D   Assault City [Light Phaser]/COUNTRY=EU,BR/PRODUCT_NO=7040/EMU_INPUTS=LIGHTPHASER/COMMENT=A Joypad version also exists.\r\nSMS 147e02fa B6F98801021AA804   Astérix [v0]/COUNTRY=EU,BR/PRODUCT_NO=9008\r\nSMS 8c9d5be8 C3FA970F111DBEB1   Astérix [v1]/COUNTRY=EU,BR,AU/PRODUCT_NO=9008\r\nSMS f9b7d26b B3825A1E4E13AD45   Astérix and the Great Rescue/COUNTRY=EU,BR,PT/PRODUCT_NO=9032,028490\r\nSMS def9b14e 5861B70BCC1B2A74   Astérix and the Secret Mission/COUNTRY=EU/PRODUCT_NO=9023,9023-50\r\nSMS c795182d 041B1627D5288324   Astro Flash/COUNTRY=JP/PRODUCT_NO=C-503/COMMENT=Japanese version of \"TransBot\".\r\nSMS 299cbb74 E41681744EF7FAD2   Astro Warrior/COUNTRY=JP,US,BR/PRODUCT_NO=G-1312,5069,023.040\r\nSMS 69efd483 35006A2A22FE0710   Astro Warrior \\/ Pit Pot/COUNTRY=EU,DE,IT/PRODUCT_NO=6081,41011\r\nSMS 69efd483 35006A2A22FE0710   Astro Warrior \\/ Pit Pot/COUNTRY=EU,DE,IT/PRODUCT_NO=6081,41011\r\nSMS 3da7f1ce 37FE6B2A21FE0710   Astro Warrior & Pit Pot [Proto]/COUNTRY=DE/COMMENT=Early Red artwork German version. Only 2 header bytes differs from final release.\r\nSMS 0eb430ff F5F159BFDF8F9DF7   A-Team, The [Music] [Proto]/FLAGS=PROTO/COUNTRY=EU/COMMENT=Sound driver and music tracks by Jeroen Tel, for the unreleased \"The A-Team\" game.\r\nSMS ff614eb3 C0065F686A4316B0   Aztec Adventure/NAME_JP=Nazca '88/COUNTRY=JP,US,EU,KR/PRODUCT_NO=G-1335,5100,GB-1335\r\nSMS 7ca37320 9DB2430423F679D8   Aztec Adventure [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-26/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS e5ff50d8 D2BE59AA0185BE29   Back to the Future Part II/COUNTRY=EU,BR/PRODUCT_NO=27010-50\r\nSMS 2d48c1d3 84C9B8E5194A882B   Back to the Future Part III/COUNTRY=EU/PRODUCT_NO=MK-27020-50/EMU_TVTYPE=PAL\r\nSMS 35d84dc2 BE8D0BC44B5555F1   Baku Baku/COUNTRY=BR/PRODUCT_NO=025470/COMMENT=Also referred to as \"Baku Baku Animal\" in-game. This is a port from the Game Gear version.\r\nSMS 655fb1f4 D8A13BCA59CD77E5   Bank Panic/COUNTRY=EU,DE,IT,BR/PRODUCT_NO=4084,41022,4584,4006\r\nSMS d1cc08ee 4220E6AA3FBBA074   Bart vs. The Space Mutants (The Simpsons)/COUNTRY=EU,BR,PT/PRODUCT_NO=MK-27031-50\r\nSMS f6b2370a 98430D51443E0D38   Bart vs. The World (The Simpsons)/COUNTRY=EU,BR/PRODUCT_NO=MK 27053-50,027210\r\nSMS 0df8597f 0C2223DC0ECAB348   Basketball Nightmare/COUNTRY=EU,BR/PRODUCT_NO=7025\r\nSMS 4e3ebb55 904F50BB23862D40   Basketball Nightmare [Proto 0]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS e5b3573e A8E366425A4D55D1   Basketball Nightmare [Proto 1]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS b154ec38 35A2509E003333D5   Batman Returns/COUNTRY=EU,BR/PRODUCT_NO=7112,7112-50\r\nSMS 1cbb7bf1 D1A8660091BC1ABA   Battlemaniacs/COUNTRY=BR/PRODUCT_NO=027376/EMU_TVTYPE=PAL/COMMENT=This game was developed by RARE (UK) but only released in Brazil. It seems to have been 95% completed with some glitchs left and a quite easy ending sequence.\r\nSMS c19430ce 2063D1C61FABFC20   Battle Out Run/COUNTRY=EU,BR/PRODUCT_NO=7033\r\nSMS fae0ade7 18ED1D60B2659ACD   Battle Wings [Proto]/FLAGS=PROTO/COMMENT=Prototype of \"Bomber Raid\".\r\nSMS da3a2f57 23DA1C4AC46CB8B5   Black Belt/COUNTRY=US,EU,BR,KR/PRODUCT_NO=5054,GB-1005/COMMENT=Export adaptation of \"Hokuto no Ken\". The original Japanese game is based on the \"Fist of the North Star\" manga. Characters and levels were replaced for the export version.\r\nSMS 98f64975 0E67FD07904D5B4F   Black Belt [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-19/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 8ecd201c 95A173467C000C89   Blade Eagle 3-D/NAME_JP=Blade Eagle/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1351,8005/EMU_3D\r\nSMS 58d5fc48 C1001AE980334148   Blade Eagle 3-D [Proto 0]/FLAGS=PROTO/COUNTRY=US/EMU_3D/COMMENT=Prototype version of the game. Level differences are very clear from the beginning.\r\nSMS c127cc9c 1B4F7D1D0B814E22   Blade Eagle 3-D [Proto 1]/FLAGS=PROTO/EMU_3D/COMMENT=Prototype version of the game.\r\nSMS 643b6b76 97766D7F4D91D752   Block Hole/COUNTRY=KR/EMU_COUNTRY=1               ; [EDITOR-NOTE] May run on export system, haven't tested yet but the game requires a non-zero RAM clearing pattern.\r\nSMS f9dbb533 7F77195ABBCB050C   BMX Trial - Alex Kidd/COUNTRY=JP/PRODUCT_NO=G-1330/EMU_INPUTS=PADDLE\r\nSMS caea8002 DC830766ED4115F1   Bonanza Bros./NAME_BR=Bonanza Brothers/COUNTRY=EU,BR/PRODUCT_NO=7073/COMMENT=Also referred to as \"Bonanza Brothers\".\r\nSMS b3768a7a 1A817AD5D227C35A   Bonkers Wax Up!/COUNTRY=BR/PRODUCT_NO=028600/COMMENT=This is a port from the Game Gear version.\r\nSMS 3084cf11 BD3F8777A78138A6   Bomber Raid/COUNTRY=JP,US,EU/PRODUCT_NO=G-1373,QC-003,27006\r\nSMS 25eb9f80 18927BF53F0AF7A6   Bobble Bobble [Clover]/COUNTRY=KR/COMMENT=Unlicensed clone of \"Bubble Bobble\".\r\nSMS e843ba7e 9DCEFDF112FC2D6C   Bubble Bobble/NAME_BR=Dragon Maze/COUNTRY=EU,BR,KR/PRODUCT_NO=7077,GB-2005/COMMENT=Export version of \"Final Bubble Bobble\".\r\nSMS b0fc4577 C10FA02711E01C5C   Buggy Run/COUNTRY=EU,BR/PRODUCT_NO=9025,028340\r\nSMS ac6009a7 CF790CF50722A0EE   California Games/NAME_BR=Jogos de Verão/COUNTRY=US,EU,BR/PRODUCT_NO=7014\r\nSMS c0e25d62 53E11D9FBBD9FB81   California Games II [50 Hz]/COUNTRY=EU/PRODUCT_NO=7105/EMU_TVTYPE=PAL\r\nSMS 45c50294 CE99027ABB34D757   California Games II [50-60 Hz]/NAME_BR=Jogos de Verão II/COUNTRY=BR,KR/PRODUCT_NO=025190,GB93006JG\r\nSMS a4852757 DE36EE3D634864B2   Captain Silver/COUNTRY=JP,EU,BR/PRODUCT_NO=G-1356,7008/COMMENT=This is the full 256 KB original version of the game as released in Japan and Europe (6 levels).\r\nSMS b81f6fa5 ED86FC925D8967B2   Captain Silver/COUNTRY=US/PRODUCT_NO=5117/COMMENT=This is the stripped out 128 KB version of the game as released in USA (4 levels out of 6).\r\nSMS 2532a7cd 799E5661199B700E   Captain Silver [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Based on the 128 KB version.\r\nSMS 3cff6e80 CA4954F3D05891ED   Casino Games/COUNTRY=US,EU/PRODUCT_NO=7021\r\nSMS 31ffd7c3 FC9BB664160566CE   Castelo Rá-Tim-Bum/COUNTRY=BR/PRODUCT_NO=028720\r\nSMS b9db4282 DA621A73F5D66606   Castle of Illusion - Starring Mickey Mouse [v0]/COUNTRY=US,BR/PRODUCT_NO=7053\r\nSMS 953f42e1 6A279D3154CF1D61   Castle of Illusion - Starring Mickey Mouse [v1]/COUNTRY=US,EU,BR/PRODUCT_NO=7053\r\nSMS bd610939 32DB3D9E840A6D1D   Castle of Illusion - Starring Mickey Mouse [Demo]/FLAGS=PROTO/COUNTRY=US/COMMENT=Rolling non-interactive demo to advertise the game.\r\nSMS 59840fd6 CCD28DCAC9AC7C1A   Castle of Illusion - Starring Mickey Mouse [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=US,EU,BR/PRODUCT_NO=2401,012130\r\nSMS 9942b69b 98C6E58711A96715   Castle of Illusion - Starring Mickey Mouse [SMS-GG]/NAME_JP=Mickey Mouse no Castle Illusion/FLAGS=SMSGG_MODE/COUNTRY=JP/PRODUCT_NO=G-3301\r\nSMS cc521975 BA6D435009B8ADD8   Cave Dude [Proto] [SMS-GG]/FLAGS=SMSGG_MODE,PROTO/COUNTRY=US/COMMENT=Prototype version of the game. Same as the version in '4 Pak All Action' except this version has copyright information.\r\nSMS 23163a12 F15F4C92401D6312   Champions of Europe/COUNTRY=EU,BR/PRODUCT_NO=27034-50,025430\r\nSMS 7e5839a0 C7A7D1085D01ABB0   Championship Hockey/COUNTRY=EU/PRODUCT_NO=27084-50\r\nSMS 492c7c6e 2F6E3B854AD2C1C6   Chapolim x Drácula - Um Duelo Assustador/COUNTRY=BR/PRODUCT_NO=023430/COMMENT=Brazilian hacked version of \"Ghost House\", released by Tec Toy.\r\nSMS 46340c41 5F5124D60E874C75   Cheese Cat-Astrophe - Starring Speedy Gonzales/NAME_PT=Cheese Cat-Astrophe - Com Speedy Gonzales/COUNTRY=EU,BR,PT/PRODUCT_NO=9033-50,028550\r\nSMS 4a21c15f BA03F66F1CEFB221   Choplifter/COUNTRY=US,EU,DE,IT,BR/PRODUCT_NO=5051,41001\r\nSMS 55f929ce 5CC5DB32E6CF130A   Choplifter [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-15/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS fd981232 1DD493C4BDB5AD99   Choplifter [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 16ec3575 59B7B528A8C7DFC5   Choplifter [Proto]/COUNTRY=JP/FLAGS=PROTO/COMMENT=Prototype version of the game, found on a Japanese-format cartridge.\r\nSMS e421e466 8854D3291643319E   Chouon Senshi Borgman/COUNTRY=JP/PRODUCT_NO=G-1371/COMMENT=Japanese version of \"Cyborg Hunter\".\r\nSMS 86f49ae9 81DD037E1B473887   Chouon Senshi Borgman [Proto]/FLAGS=PROTO/COUNTRY=JP/COMMENT=Prototype version of the game.\r\nSMS dd0e2927 8CFE7B6CC112B903   Chuck Rock/COUNTRY=EU,BR/PRODUCT_NO=MK-29004-50,028040\r\nSMS c30e690a B2D10AB51B1C5136   Chuck Rock II: Son of Chuck/COUNTRY=EU/PRODUCT_NO=MK-29019-50\r\nSMS 87783c04 DE902135694BC6C2   Chuck Rock II: Son of Chuck/COUNTRY=BR/PRODUCT_NO=028440/COMMENT=This version is an earlier build than the European version.\r\nSMS 8fb75994 2AB04A10D714A23F   Circuit, The/COUNTRY=JP/PRODUCT_NO=G-1304/COMMENT=Japanese version of \"World Grand Prix\".\r\nSMS 1df0fc90 198269AF6F442C6E   Circuit, The/COUNTRY=TW/PRODUCT_NO=G-1304\r\nSMS e7f62e6d BA12C9527CEE0DA2   Cloud Master/NAME_JP=Chuka Taisen/COUNTRY=US,EU,BR/PRODUCT_NO=7027\r\nSMS 603c39aa C87A5AECCFB47D78   Cloud Master [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-26/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 9d549e08 59868AC9BD4815B4   Comical Machine Gun Joe/COUNTRY=JP/PRODUCT_NO=C-511\r\nSMS 84ad5ae4 A9567EC5B94513AD   Comical Machine Gun Joe/COUNTRY=TW/PRODUCT_NO=K-317\r\nSMS 643f6bfc 937293CB9A4A16A3   Comical Machine Gun Joe/COUNTRY=KR/PRODUCT_NO=G-40\r\nSMS 7778e256 16402857F8E8EC5F   Comic Bakery/COUNTRY=KR\r\nSMS 1e1b9f59 2F0FA880482CC066   Con-Dori/COUNTRY=KR\r\nSMS 7253c3ec DF1EDD826F58CE0F   Color & Switch Test/FLAGS=PROTO/COMMENT=Official test cartridge. Also referred to as \"M4 PAD CHK\". The ROM contains a \"POWER BASE CHECK\" string.\r\nSMS 665fda92 AA7CEDD6C88CA221   Columns/NAME_BR=Shapes and Columns/COUNTRY=US,EU,BR,KR/PRODUCT_NO=5120,GB-1001,GB-1002JG\r\nSMS 3fb40043 8418F6420CFBF035   Columns [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 13ac9023 7269A76D348E66E9   Cool Spot/COUNTRY=EU/PRODUCT_NO=MK-27068-50\r\nSMS 29822980 AA098A4FE1EB594F   Cosmic Spacehead/COUNTRY=EU/PRODUCT_NO=MK-27074-50/EMU_MAPPER=3/EMU_TVTYPE=PAL/EMU_SPRITE_FLICKER\r\nSMS 0918fba0 AC5C1E17C758A7FD   C_So! [MSX]/COUNTRY=KR\r\nSMS 1350e4f8 54D5553AF5264FDE   Cyber Shinobi, The/COUNTRY=EU,BR/PRODUCT_NO=7050\r\nSMS dac00a3a 3FAB87D3FDD61FCA   Cyber Shinobi, The [Proto]/FLAGS=PROTO\r\nSMS ad9ff469 4CCE5139F3214CFC   Cyber Shinobi, The [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-33/COMMENT=Taiwanese HTH release for Game Gear. Box also says \"Space no Ninja\".\r\nSMS 908e7524 48CF176FE2E9692F   Cyborg Hunter/COUNTRY=US,EU,BR/PRODUCT_NO=QC-002,25003/COMMENT=Export version of \"Chouon Senshi Borgman\".\r\nSMS 691211a1 61DA346DEFEE64E3   Cyborg Hunter [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 77efe84a 38F62FF22B9B34B7   Cyborg Z/COUNTRY=KR/EMU_MAPPER=12\r\nSMS 71abef27 8C16E13E120E48D7   Daffy Duck in Hollywood/COUNTRY=EU,BR,AU/PRODUCT_NO=9031,028360/EMU_TVTYPE=NTSC\r\nSMS 89b79e77 E3D53E738DD294A4   Dallyeora Pigu-Wang/COUNTRY=KR/PRODUCT_NO=G9511-RP4/EMU_MAPPER=9/COMMENT=Name translate as \"Run Dodgeball King\"\r\nSMS ae4a28d7 573DC782B785EDFA   Danan: The Jungle Fighter/NAME_BR=Danan/COUNTRY=EU,BR/PRODUCT_NO=7049\r\nSMS 1d835eb3 3B19BD76B173DA7B   Danan: The Jungle Fighter [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-32/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS e2f7193e D57FCD7C1E815D67   Dead Angle/COUNTRY=US,EU,BR/PRODUCT_NO=7030\r\nSMS f9271c3d 1B549F5E634E10D3   Dead Angle [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 42fc3a6e E705BC457D04D7BB   Deep Duck Trouble - Starring Donald Duck/COUNTRY=EU,BR/PRODUCT_NO=9022\r\nSMS b137007a F82AE98027F45A00   Desert Speedtrap - Starring Road Runner and Wile E. Coyote/NAME_BR=Desert Speedtrap/COUNTRY=EU,BR,PT/PRODUCT_NO=7122,027250\r\nSMS 6c1433f9 F0BF995E2C2E5FA1   Desert Strike/COUNTRY=EU/PRODUCT_NO=MK 29010-50\r\nSMS f6fab48d E2628BCB39487174   Dick Tracy/COUNTRY=US,EU,BR/PRODUCT_NO=7057\r\nSMS ea5c3a6f 31C90A07943577B5   Dinobasher - Starring Bignose the Caveman [Proto]/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of the unreleased game.\r\nSMS 32f4b791 AEC0BB10E75FCFB2   Dinosaur Dooley, The/COUNTRY=KR/COMMENT=English language version of \"Agigongnyong Dooly\" (also a Korean cartridge). Music tracks and a few artworks are different.\r\nSMS 2bcdb8fa 9A7D6603682DA249   Doki Doki Penguin Land - Uchuu Daibouken/COUNTRY=JP/PRODUCT_NO=G-1334/COMMENT=Japanese version of \"Penguin Land\".\r\nSMS fb163003 94FB507C17030883   Doki Doki Penguin Land - Uchuu-Daibouken [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-03/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Astro Adventure\".\r\nSMS 56bd2455 BF5D696ADE34916E   Doki Doki Penguin Land - Uchuu Daibouken [Proto]/FLAGS=PROTO/COUNTRY=JP/COMMENT=Prototype version of the game.\r\nSMS a55d89f3 3488F258EC375C7B   Double Dragon/COUNTRY=JP,US,EU,BR,KR/PRODUCT_NO=G-1369,7012,GB-2369\r\nSMS aeacfca7 E846E84DC813566C   Double Dragon/COUNTRY=KR/COMMENT=Only differ from original version by a blanked out Sega logo.\r\nSMS f4f848c2 8AE7B5E174DDF3B5   Double Dragon [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-02/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 8370f6cd 128E2488C291E978   Double Hawk/COUNTRY=EU/PRODUCT_NO=7036\r\nSMS f76d5cee 932160B3D0411315   Double Hawk [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 52b83072 06C09D75451032A1   Double Target - Cynthia no Nemuri/COUNTRY=JP,TW/PRODUCT_NO=G-1314/COMMENT=Japanese version of \"Quartet\".\r\nSMS 1b10a951 1AF283FD7C694E41   Dracula (Bram Stoker's)/COUNTRY=EU/PRODUCT_NO=MK-27065-50/EMU_TVTYPE=PAL\r\nSMS 9549fce4 6C4E00641D7F6ADC   Dragon Crystal/COUNTRY=EU,BR/PRODUCT_NO=5123,023440\r\nSMS c88a5064 71FD7E5B59B78722   Dragon: The Bruce Lee Story/COUNTRY=EU/PRODUCT_NO=MK-27079-50\r\nSMS 16537865 CAB3012EDD748A79   Dr. HELLO/COUNTRY=KR\r\nSMS 6c696221 4F253839D8443AC5   Dr. Robotnik's Mean Bean Machine/COUNTRY=EU,BR/PRODUCT_NO=7123,025360\r\nSMS 07306947 D8735FD26D415482   Dynamite Duke/COUNTRY=EU,BR/PRODUCT_NO=7067\r\nSMS 0e1cc1e0 4002AEAA680311EA   Dynamite Dux/COUNTRY=EU,BR/PRODUCT_NO=7029\r\nSMS 4e59175e A039A522C6B4F0F6   Dynamite Dux [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 7db5b0fa 8B7CE5483E4F1B24   Dynamite Headdy/COUNTRY=BR/PRODUCT_NO=028570/COMMENT=This is a port from the Game Gear version. It was apparently ported to the Master System by a division of SEGA outside Japan, but never released at the time. Tec Toy later released it.\r\nSMS f06f2ccb BBFF73681C587186   Eagles 5/COUNTRY=KR\r\nSMS c4d5efc5 65DF0FAE9B9BD8F1   Earthworm Jim/COUNTRY=BR/PRODUCT_NO=028690/EMU_TVTYPE=NTSC/COMMENT=This is a port from the Game Gear version. It has a status bar display bug on early Master System 1.\r\nSMS 6687fab9 83074B5C0E7C3A0B   Ecco the Dolphin/COUNTRY=EU,BR,AU/PRODUCT_NO=9029\r\nSMS 7c28703a B26E818E12334547   Ecco - The Tides of Time/COUNTRY=BR/PRODUCT_NO=028630/COMMENT=The in-game demonstration has timing problems making it buggy.\r\nSMS dd74bcf1 1D8FA00A8C616558   E.I. - Exa Innova/COUNTRY=KR\r\nSMS 00e73541 93D3417EE009757D   Enduro Racer/NAME_BR=Super Cross/COUNTRY=US,EU,BR/PRODUCT_NO=5077/COMMENT=This is the limited 128 KB version of the game as released outside of Japan (5 different level layout instead of 10 in the Japanese version).\r\nSMS 5d5c50b3 6038C2516F841949   Enduro Racer/COUNTRY=JP/PRODUCT_NO=G-1322/COMMENT=This is the full original 256 KB version of the game as released in Japan (10 different level layout).\r\nSMS c4bb1676 C12FD315320E1CCC   E-SWAT [v0]/COUNTRY=EU,BR/PRODUCT_NO=7042\r\nSMS c10fce39 CAEDD39267EAE1B2   E-SWAT [v1]/COUNTRY=US,EU/PRODUCT_NO=7042\r\nSMS 96e16fe4 4239547D58D3D0B9   E-SWAT [v1] [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-12/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 4f20694a A67EA404D88A5F73   E-SWAT [Proto 0]/FLAGS=PROTO\r\nSMS f7ca9801 E58073DF458CD4A4   E-SWAT [Proto 1]/FLAGS=PROTO\r\nSMS fd91cc7e BC2FD215320C1DD3   E-SWAT [Proto 2]/FLAGS=PROTO\r\nSMS aa140c9c 0E423CDBCAD3E01C   Excellent Dizzy Collection, The [SMS-GG]/COUNTRY=EU/FLAGS=SMSGG_MODE/EMU_TVTYPE=PAL/EMU_MAPPER=3\r\nSMS 8813514b B7049344859B9CB2   Excellent Dizzy Collection, The [Proto]/FLAGS=PROTO/EMU_TVTYPE=PAL/EMU_MAPPER=3/COMMENT=Prototype version of the game. Seems incomplete. The prototype was submitted as a 256 KB EPROM, while the full Game Gear version is twice as big. It's possible to run this version a bit further by appending the second half from the Game Gear version, but it'll eventually crash.\r\nSMS ec788661 066B34EF6BEC0411   F1/NAME_BR=Fórmula-1/COUNTRY=EU,BR/PRODUCT_NO=MK-27072-50,026330\r\nSMS 06965ed9 0942E34E2B1B46F8   F-1 Spirit - The way to Formula-1/COUNTRY=KR/EMU_MAPPER=12\r\nSMS eaebf323 A14F71C94A96B145   F-16 Fighter/COUNTRY=US,EU,DE,IT,BR/PRODUCT_NO=4005M,4081,4581,41005/COMMENT=US version is sometimes labelled \"F-16 Fighting Falcon\" but has a \"F-16 Fighter\" title screen.\r\nSMS 7ce06fce 41BC24AC74DB9252   F-16 Fighting Falcon/COUNTRY=JP,KR/PRODUCT_NO=C-508\r\nSMS 184c23b7 8B5072C94E9DBB44   F-16 Fighting Falcon/COUNTRY=US/PRODUCT_NO=4005\r\nSMS c4c53226 A7DEDC9F65CA8B46   F-16 Fighting Falcon/COUNTRY=TW/PRODUCT_NO=K-313\r\nSMS 7abc70e9 BAB2C9BE74870012   Family Games (Party Games)/COUNTRY=JP,KR/PRODUCT_NO=G-1342,GB-1342/COMMENT=Japanese version of \"Parlour Games\". When ran on an export Master System, the game title screen says \"Party Games\". This later name was however never used officially in any country, since the export release is named \"Parlour Games\".\r\nSMS b9664ae1 914DC1AEAC3729A7   Fantastic Dizzy/COUNTRY=EU/EMU_MAPPER=3/EMU_TVTYPE=PAL/PRODUCT_NO=MK-27074-50\r\nSMS c888222b 42A62B8FE6E5DCB7   Fantastic Dizzy [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=EU/EMU_MAPPER=3/EMU_TVTYPE=PAL\r\nSMS 0ffbcaa3 4EC2794265F92BAC   Fantasy Zone [v0]/COUNTRY=JP/PRODUCT_NO=G-1301\r\nSMS f46264fe 773B84D6E509778F   Fantasy Zone [v1] [Proto]/FLAGS=PROTO/COMMENT=ROM found in a prototype cartridge, but it might have been used in production cartridges.\r\nSMS 65d7e4e0 6D3986E0E6097F86   Fantasy Zone [v2]/COUNTRY=JP,US,EU,DE,IT/PRODUCT_NO=G-1301,5052,41002\r\nSMS 5fd48352 826AD3352101E604   Fantasy Zone [v2]/COUNTRY=TW/PRODUCT_NO=G-1301\r\nSMS b8b141f9 822C747C6F162BB2   Fantasy Zone II - The Tears of Opa-Opa/COUNTRY=US,EU,BR,KR/PRODUCT_NO=7004\r\nSMS c722fb42 670E9195613A25A5   Fantasy Zone II - Opa-Opa no Namida/COUNTRY=JP/PRODUCT_NO=G-1329\r\nSMS d29889ad 732FC6FC6BDC0A4B   Fantasy Zone: The Maze/COUNTRY=US,EU,BR/PRODUCT_NO=5108/COMMENT=Export version of \"Opa Opa\".\r\nSMS b28b9f97 F06C2103FE689F7B   Fantasy Zone: The Maze [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 17ab6883 866A225E7803D045   FA Tetris/COUNTRY=KR/EMU_MAPPER=11\r\nSMS bf6c2e37 5C434F34BA4434AC   Férias Frustradas do Pica Pau/COUNTRY=BR/PRODUCT_NO=028660\r\nSMS 9bb3b5f9 78A312E98554F41D   FIFA International Soccer/COUNTRY=BR/PRODUCT_NO=028670/COMMENT=This is a port from the Game Gear version.\r\nSMS 3ebb7457 1812E0F53178AFA9   Final Bubble Bobble/COUNTRY=JP/PRODUCT_NO=G-1362/COMMENT=Japanese version of \"Bubble Bobble\".\r\nSMS b948752e E04A9E63784D2CE4   Final Bubble Bobble [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-01/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Bubble Dragon\".\r\nSMS f6ad7b1d E356BEF0D3941C96   Fire & Forget II/COUNTRY=EU/PRODUCT_NO=27009-50/COMMENT=Other versions of the game are subtitled \"The Death Convoy\", but not the Master System version. Note that it is the original version of the game. Amiga and Atari ST versions are actually ports based on the SMS version.\r\nSMS 8b24a640 C9A68D7C60D1C196   Fire & Ice/COUNTRY=BR/PRODUCT_NO=027360/COMMENT=This game was developed and planned for release in Europe, then was cancelled. Tec Toy later released the game in Brazil.\r\nSMS be31d63f 087CCA33EB554EF1   Flash, The/COUNTRY=EU,BR/PRODUCT_NO=7506,7506-50\r\nSMS 61e8806f 0909D2F70850EDE0   Flashpoint/COUNTRY=KR/EMU_MAPPER=11/EMU_SPRITE_FLICKER\r\nSMS ca5c78a5 BD9E05F283723B7E   Flintstones, The/COUNTRY=EU,BR/PRODUCT_NO=MK-27013-50\r\nSMS 38c53916 4589A9BD05075E62   Forgotten Worlds/COUNTRY=EU,BR,AU,KR/PRODUCT_NO=7056,GB-2005JG\r\nSMS 44136a72 269D69A7F7DD4E0B   Forgotten Worlds [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-46/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS e6795c53 B637976CB4B28D1D   Fushigi no Oshiro Pit Pot/COUNTRY=JP,KR/PRODUCT_NO=C-507\r\nSMS 73c76d15 A33D9F71B7AF8822   Fushigi no Oshiro Pit Pot [Proto]/COUNTRY=JP/COMMENT=Prototype version of the game.\r\nSMS 8b40f6bf 8CE87C3FDC15F4EC   Gaegujangi Kkachi/COUNTRY=KR/PRODUCT_NO=GB-4001/COMMENT=Name translate as \"Kkachi, a naughty boy\".\r\nSMS 3ec5e627 C00413DAC7946A8A   Gain Ground/COUNTRY=EU,BR/PRODUCT_NO=7045\r\nSMS d40d03c7 CC0D11E2CB947461   Gain Ground [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS a6fa42d0 A5FA6D631981688F   Galactic Protector/COUNTRY=JP/PRODUCT_NO=G-1348/EMU_INPUTS=PADDLE\r\nSMS 577ec227 643F1CDBAB470272   Galaxian/COUNTRY=KR\r\nSMS 6c827520 1B819E859D0C3860   Galaxy Force/COUNTRY=US/EMU_TVTYPE=NTSC/PRODUCT_NO=QC-004-02\r\nSMS a4ac35d8 0B932CEAD9975587   Galaxy Force/COUNTRY=EU,BR/PRODUCT_NO=29001\r\nSMS 5fc74d2a 1EE251A5D9687455   Gangster Town/COUNTRY=US,EU,BR/EMU_INPUTS=LIGHTPHASER/EMU_IPERIOD=258/PRODUCT_NO=5074,023120   ; [EDITOR-NOTE] BR blue box version is 023120. BR cardboard version has no product_no.\r\nSMS 1890f407 EF924BC5AE023A85   Game Box Série Esportes Radicais/COUNTRY=BR/PRODUCT_NO=023480/COMMENT=Hacked version of \"California Games\" with only two events left. Released by Tec Toy.\r\nSMS 38b3a72f 63B3EE2924E6EFDA   Game Chongjiphap 200/COUNTRY=KR/EMU_MAPPER=18\r\nSMS 9afab511 F87F393D06469C2B   Game De Check! Koutsuu Anzen [Proto]/COUNTRY=JP/COMMENT=Unreleased not-for-sale educative game.\r\nSMS c0e098a6 9A232DF2D8AB4A57   Game Jiphap 30 Hap [SMS-MD]/COUNTRY=KR/EMU_MAPPER=26\r\nSMS 380d7400 DD6520742A9CBCA8   Game Mo-eumjip 188 Hap [v0]/COUNTRY=KR/EMU_MAPPER=19\r\nSMS c76601e0 DE651F732B9CBCA8   Game Mo-eumjip 188 Hap [v1]/COUNTRY=KR/EMU_MAPPER=19/COMMENT=Minor variation affecting the starting level of entries 101 to 104.\r\nSMS ad522efd 8D03BD7E1EFB021A   Gangcheol RoboCop/COUNTRY=KR/PRODUCT_NO=SI-3131G\r\nSMS d9190956 0DD3230F6E789E6A   Gauntlet/COUNTRY=EU,BR/PRODUCT_NO=25006-50\r\nSMS a64898ce E466186F844A540D   George Foreman's KO Boxing/COUNTRY=EU,BR/PRODUCT_NO=MK-27041-50,026180\r\nSMS 956c416b 25ABB2B6FC7AD67C   Geraldinho/COUNTRY=BR/PRODUCT_NO=021080/COMMENT=Brazilian hacked version of \"Teddy Boy\", released by Tec Toy.\r\nSMS 1ddc3059 DC6545FFFA415CE4   Ghostbusters/COUNTRY=US,EU,BR,KR/PRODUCT_NO=5065,GB1024JG\r\nSMS c0f3ce7e 827C30E5ED689206   Ghost House/COUNTRY=JP/PRODUCT_NO=C-512\r\nSMS f1f8ff2d 102C54291BD04715   Ghost House/COUNTRY=US,EU,AU,IT,BR/PRODUCT_NO=4002,4502\r\nSMS 1203afc9 C65D33D6DF6C90F9   Ghost House/COUNTRY=KR\r\nSMS c3e7c1ed 1C5A4BE99B9035F6   Ghost House [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS b746a6f5 A9CF4BEC1F7EF8BC   Global Defense/COUNTRY=US,EU,BR/PRODUCT_NO=5102/COMMENT=Export version of \"SDI\".\r\nSMS 91a0fc4e CB2CDBCADF1A610A   Global Defense [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS b67ceb76 DA2CA2C86604B076   Global Gladiators/COUNTRY=EU,BR/PRODUCT_NO=MK-27062-50,027090\r\nSMS 05cdc24e 03D41A910937FC42   G-LOC - Air Battle/NAME_BR=G-Loc/COUNTRY=EU,BR,KR/PRODUCT_NO=7071,GB2009JG\r\nSMS a249fa9d CEDEE0CA40083032   Gokuaku Doumei Dump Matsumoto/COUNTRY=JP/PRODUCT_NO=G-1302/COMMENT=Japanese version of \"Pro Wrestling\".\r\nSMS c08132fb 07A18B1093D71D36   Golden Axe/COUNTRY=US,EU,BR/PRODUCT_NO=9004,028060\r\nSMS a471f450 35D1C89EB09E94B2   Golden Axe [Demo]/FLAGS=PROTO/COUNTRY=US/COMMENT=Rolling non-interactive demo to advertise the game.\r\nSMS c7ded988 9BCA87E879AE0BFA   Golden Axe Warrior/COUNTRY=US,EU,BR/PRODUCT_NO=7505\r\nSMS 48651325 C0AB0A7E886044E1   Golfamania/COUNTRY=EU,BR/PRODUCT_NO=7502\r\nSMS 5dabfdc3 D7DD318BE2DA8351   Golfamania [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 7f7b568d 3D8263CB4F982705   Golfamania (Super Golf) [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game, then called \"Super Golf\".\r\nSMS a51376fe 593A81384915F462   Golvellius - Valley of Doom/COUNTRY=US,EU,BR/PRODUCT_NO=7017,024170/COMMENT=Export version of \"Maou Golvellius\".\r\nSMS 7a92eba6 DB5D5B37B0F77916   Ghouls'n Ghosts/COUNTRY=US,EU,BR,KR/PRODUCT_NO=7055,025170,GB-2006JG\r\nSMS 8821a7c9 C640492AACEA777A   Ghouls'n Ghosts [HTH] (SMS-GG)/PRODUCT_NO=HG 402-01/COUNTRY=TW/COMMENT=Extracted from 2-in-1 HG 402-01.\r\nSMS 96ca6902 8D436928DC24B2ED   Ghouls'n Ghosts [Demo]/FLAGS=PROTO/COUNTRY=US/COMMENT=Rolling non-interactive demo to advertise the game.\r\nSMS ec2da554 EB6D4D69959BF2D0   GP Rider/COUNTRY=EU,BR/PRODUCT_NO=9013,028200\r\nSMS 10ed6b57 40C511003F43AFB9   Great Baseball/COUNTRY=US,EU,BR/PRODUCT_NO=5061/COMMENT=Not the same game as the Japanese card version also named \"Great Baseball\".\r\nSMS 89e98a7c 9F82F97234F38CC1   Great Baseball [JP]/COUNTRY=JP/PRODUCT_NO=C-505/COMMENT=Not the same game as the Export cartridge version also named \"Great Baseball\".\r\nSMS 2ac001eb 47A87FEE28140464   Great Basketball/NAME_BR=Great Basket/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1320,5071\r\nSMS 6fe448a5 8E35498FE5E6A1F9   Great Basketball [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-17/COMMENT=Taiwanese HTH release for Game Gear. Box says \"94-Nen Super Basketball\".\r\nSMS 2055825f 9081CE66CC2A03C2   Great Football/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1321,5058\r\nSMS 98e4ae4a 20A77684F32545E2   Great Golf/NAME_JP=Masters Golf/COUNTRY=JP,US,EU/PRODUCT_NO=G-1332,5057/COMMENT=This game was called \"Masters Golf\" in Japan. Another game also named \"Great Golf\" was released in Japan, but isn't the same game.\r\nSMS c6611c84 8573186E10A8BF0B   Great Golf [Mega-Tech]/COUNTRY=US,EU/COMMENT=From \"Mega-Tech\" arcade version.\r\nSMS 4847bc91 94664B361BFAE58B   Great Golf [Proto]/NAME_JP=Masters Golf [Proto]/COUNTRY=JP/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 6586bd1f 60D284A3414C61B9   Great Golf [JP]/COUNTRY=JP/PRODUCT_NO=G-1313/COMMENT=Another game also named \"Great Golf\" was released in USA and Europe, but isn't the same game.\r\nSMS 5def1bf5 2FB39F2D8372A7B6   Great Golf [JP]/COUNTRY=KR\r\nSMS 946b8c4a B0132F32485E1D19   Great Ice Hockey/COUNTRY=US,JP/PRODUCT_NO=5062/EMU_INPUTS=SPORTSPAD\r\nSMS 0ed170c9 114D726F249BB949   Great Soccer/COUNTRY=EU/PRODUCT_NO=4082,41018/COMMENT=Another game also named \"Great Soccer\" was released in USA.\r\nSMS 2d7fd7ef 68A3CEF02BC61B2B   Great Soccer/COUNTRY=JP/PRODUCT_NO=C-504/COMMENT=Another game also named \"Great Soccer\" was released in USA.\r\nSMS 84665648 A1CCBAEB22981321   Great Soccer/COUNTRY=TW/PRODUCT_NO=K-307\r\nSMS 95cbf3dd 03AA0AD98772E196   Great Tennis \\/ Super Tennis/COUNTRY=JP/PRODUCT_NO=C-515/COMMENT=Official game name is \"Great Tennis\" but title screen says \"Super Tennis\".\r\nSMS 8d43ea95 8FC056003B11CF40   Great Volleyball/NAME_BR=Great Voley/COUNTRY=US,EU,BR,KR/PRODUCT_NO=5070,023170,028560,GB-1006\r\nSMS 6819b0c0 46304A99131AF783   Great Volleyball/COUNTRY=JP/PRODUCT_NO=G-1317\r\nSMS 3af7ccad A083946B5290817B   Gun.Smoke/COUNTRY=KR\r\nSMS b9fdf6d9 6A8EE24DE483B4BE   Haja no Fuuin/COUNTRY=JP/PRODUCT_NO=G-1331/COMMENT=Japanese version of \"Miracle Warriors - Seal of The Dark Lord\".\r\nSMS 071b045e F0A23277115075EF   Hang On/COUNTRY=EU,AU,BR,DE,IT/PRODUCT_NO=4080\r\nSMS 5c01adf9 EE5DD09C3A26C623   Hang On/COUNTRY=JP/PRODUCT_NO=C-502\r\nSMS 649f29e8 EC7C600B6C427E01   Hang On [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Red card label.\r\nSMS 1c5059f0 AC0BC3BFC7D2AB83   Hang On \\/ Astro Warrior/COUNTRY=US/PRODUCT_NO=6002\r\nSMS e167a561 319F4234855F6670   Hang On \\/ Safari Hunt/COUNTRY=US,KR/PRODUCT_NO=6001/EMU_INPUTS=LIGHTPHASER\r\nSMS a120b77f 03D287D576716F79   Hang On \\/ Safari Hunt [Proto]/FLAGS=PROTO/EMU_INPUTS=LIGHTPHASER/COMMENT=Prototype version of the game.\r\nSMS fdab876a AEB225FECBA7EE1D   Heavyweight Champ/COUNTRY=EU,BR/PRODUCT_NO=7063,024180/COMMENT=Same game as \"George Foreman's KO Boxing\" and \"James \"Buster\" Douglas Knockout Boxing\".\r\nSMS cde13ffb 003CC95FA787A4CA   Heroes of the Lance/COUNTRY=EU,BR/PRODUCT_NO=29003.50,028070\r\nSMS 9611bebd 5C7AED2ED64DDA12   Heroes of the Lance [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 98af0236 C89C8F4197527A69   Hi-Com 3-in-1 The Best Game Collection A/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Hang On, Pit Pot, Spy vs Spy.\r\nSMS 6ebfe1c3 D276EDD339D93AAC   Hi-Com 3-in-1 The Best Game Collection B/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Great Baseball, Great Soccer, Super Tennis.\r\nSMS 81a36a4f 76FBAF87132C908A   Hi-Com 3-in-1 The Best Game Collection C/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Teddy Boy Blues, Pit-Pot, Astro Flash.\r\nSMS 8d2d695d 54C959A96963AD68   Hi-Com 3-in-1 The Best Game Collection D/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Teddy Boy Blues, Great Soccer, Comical Machine Gun Joe.\r\nSMS 82c09b57 B547AFCC3800361B   Hi-Com 3-in-1 The Best Game Collection E/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Ghost House, Teddy Boy Blues, Seishun Scandal.\r\nSMS 4088eeb4 BF636F2E924ECC95   Hi-Com 3-in-1 The Best Game Collection F/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Satellite-7, Great Baseball, Seishun Scandal.\r\nSMS fba94148 65FB5EB69B3CA90C   Hi-Com 8-in-1 The Best Game Collection A/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Hyper Sports 2, Champion Boxing, Safari Race, Astro Flash, Monkey Academy, Star Force, Bank Panic, Teddy Boy.\r\nSMS 8333c86e 1457CD1F9A95F585   Hi-Com 8-in-1 The Best Game Collection B/COUNTRY=KR/EMU_MAPPER=16/COMMENT=King's Valley, Ghost House, Sega-Galaga, Monaco GP, Magical Tree, Ninja Princess, Satellite-7, Hang-On.\r\nSMS 00e9809f 76FDF6F9656C29A4   Hi-Com 8-in-1 The Best Game Collection C/COUNTRY=KR/EMU_MAPPER=16/COMMENT=Athletic Land, Super Tank, Bomb Jack, Hyper Sports, Circus Charlie, Exerion, Great Baseball, Yie Ar Kung-Fu.\r\nSMS 9eb1aa4f 7DD79A9894C6A878   High School! Kimengumi/COUNTRY=JP/PRODUCT_NO=G-1309\r\nSMS 24f5fe8c 36CE68D578724E87   Hokuto no Ken/COUNTRY=JP/PRODUCT_NO=G-1303/COMMENT=Japanese version of \"Black Belt\". This game is based on the \"Fist of the North Star\" manga.\r\nSMS c4ab363d 7761965CF39300B0   Hokuto no Ken/COUNTRY=TW/PRODUCT_NO=G-1303/COMMENT=Taiwanese version of \"Hokuto no Ken\" as released by Aaronix. Final boss graphic data is corrupted (verified from original cartridge).\r\nSMS b6207f0d 0A9F6FCB746A47F8   Hokuto no Ken [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-04/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Northen Ken\".\r\nSMS c9dbf936 FA6B14A912C33ECB   Home Alone/COUNTRY=EU/PRODUCT_NO=7109/EMU_TVTYPE=PAL\r\nSMS 8040b2fa C0FDE9D208640814   Hong Kil Dong/COUNTRY=KR\r\nSMS 955a009e F35F09A93C040AB2   Hoshi wo Sagashite.../COUNTRY=JP/PRODUCT_NO=G-1354\r\nSMS 9ced34a7 09D4957E1609945D   Hook [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nSMS e4b7c56a 5263549F2E3AA14F   Hwarang-ui Geom/COUNTRY=KR/PRODUCT_NO=GB-2356/COMMENT=Korean version of \"Kenseiden\".\r\nSMS 64d6af3b C4B805DCD752A8D2   Impossible Mission/COUNTRY=EU,BR/PRODUCT_NO=25007-50\r\nSMS 71c4ca8f 1F41F02BC293A789   Impossible Mission [Proto]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game.\r\nSMS b4584dde 1C154AA5EFE3EF1F   Incredible Crash Dummies, The/NAME_BR=Crash Dummies/COUNTRY=EU,BR/PRODUCT_NO=MK 27057-50/COMMENT=Also referred to as \"Crash Dummies\".\r\nSMS be9a7071 19CC267376518536   Incredible Hulk, The/COUNTRY=EU,BR/PRODUCT_NO=29016-50\r\nSMS 8aeb574b 17779413DD492085   Indiana Jones and the Last Crusade/COUNTRY=EU,BR,PT/NAME_BR=Indiana Jones e a Última Cruzada/PRODUCT_NO=27008-50,027079\r\nSMS acec894d 64EA5CF36D9CD486   Indiana Jones and the Last Crusade [Proto]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game.\r\nSMS f60e71ec 476097D9BFBB1C53   Jaemiissneun Game Mo-eumjip 42 Hap [SMS-MD]/COUNTRY=KR/EMU_MAPPER=25\r\nSMS 53904167 88554C664810D445   Jaemiissneun Game Mo-eumjip 65 Hap [SMS-MD]/COUNTRY=KR/EMU_MAPPER=25\r\nSMS 8d23587f 5CEC5CB49DC68FB6   James Bond 007: The Duel/COUNTRY=EU/PRODUCT_NO=MK 27046-50\r\nSMS 8feff688 A022B16F114CDAE7   James Bond 007: The Duel/COUNTRY=BR/PRODUCT_NO=027230\r\nSMS 6a664405 97C27C98AF09FCDF   James \"Buster\" Douglas Knockout Boxing/COUNTRY=US/PRODUCT_NO=7063/COMMENT=Same game as \"George Foreman's KO Boxing\" and \"Heavyweight Champ\".\r\nSMS cfb4bd7b 92C27B97AF09FBE7   James \"Buster\" Douglas Knockout Boxing [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Only the ROM header is different from the final version.\r\nSMS 0a9089e5 3B2C5FDB4270713C   Joe Montana Football/COUNTRY=US,EU,BR/PRODUCT_NO=7062\r\nSMS 102d5fea 0C38C7A1580A24CE   James Pond II - Codename: RoboCod/COUNTRY=EU,BR/PRODUCT_NO=29013-50,028580\r\nSMS 192949d5 DE089DF319087BEE   Janggun-ui Adeul/COUNTRY=KR/EMU_MAPPER=13\r\nSMS 929222c4 3D06F62515E53078   Jang Pung II/COUNTRY=KR/PRODUCT_NO=SI-0103G/EMU_MAPPER=9/COMMENT=Unlicensed Street Fighter II clone.\r\nSMS 76c5bdfb F6B47C90D268957B   Jang Pung II [SMS-GG]/COUNTRY=KR/FLAGS=SMSGG_MODE/EMU_MAPPER=3/COMMENT=Unlicensed Street Fighter II clone.\r\nSMS 18fb98a3 3EC6C8A5278C0DCF   Jang Pung 3/COUNTRY=KR/EMU_MAPPER=9\r\nSMS 695a9a15 C723308C422E8664   Jungle Book, The (Walt Disney's Classic)/NAME_FR=Le Livre de la Jungle (Walt Disney's Classic)/NAME_DE=Das Dschungelbuch (Walt Disney's Classic)/COUNTRY=EU,FR,DE,PT,BR/PRODUCT_NO=MK-27069-50,MK-27069-09,MK-27069-18,027330\r\nSMS 0667ed9f 9E66E0AB50B7A4C6   Jurassic Park/COUNTRY=EU,BR,PT/PRODUCT_NO=9030,028335\r\nSMS 516ed32e 841BF3EB6EAF3E28   Kenseiden/COUNTRY=US,EU,BR/PRODUCT_NO=7013\r\nSMS 05ea5353 C248674DC457190E   Kenseiden/COUNTRY=JP/PRODUCT_NO=G-1358\r\nSMS a59b4a09 41C836B63E29CDD7   Kenseiden [HTH] (SMS-GG)/PRODUCT_NO=HG 402-01/COUNTRY=TW/COMMENT=Extracted from 2-in-1 HG 402-01. A standalone cartridge exists.\r\nSMS 0ae470e5 212FE2656C8EE887   King & Balloon/COUNTRY=KR\r\nSMS f8d33bc4 7A69F7D063546D32   King's Quest - Quest for the Crown/COUNTRY=US/PRODUCT_NO=4360\r\nSMS fd27bef1 E9A70F437A8CFE1A   King's Quest - Quest for the Crown [Proto 0]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game. Marked \"1989.2.3\".\r\nSMS b7fe0a9d A7EF2C74C4AA61FB   King's Quest - Quest for the Crown [Proto 1]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game.\r\nSMS 2b435fd6 97D1E5EB0E6664F0   KLAX/COUNTRY=EU/PRODUCT_NO=301040-0160\r\nSMS f89af3cc 1E40D12DA16EB3E2   Knightmare II: The Maze of Galious/COUNTRY=KR/EMU_MAPPER=12\r\nSMS 64a585eb 6328C143CB001393   Krusty's Fun House/COUNTRY=EU,BR/PRODUCT_NO=MK 27056-50,026280\r\nSMS d11d32e4 261F3B6965EAC701   Kujakuou/COUNTRY=JP/PRODUCT_NO=G-1366/COMMENT=Japanese version of SpellCaster.\r\nSMS 1e949d1f 50C0B42AE27D4D66   Kung Fu Kid/COUNTRY=US,EU,BR/PRODUCT_NO=5078/COMMENT=Export version of \"Makai Retsuden\".\r\nSMS 4762e022 715E94C4B05F03C7   Kung Fu Kid [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 401-21/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 24e97200 37B375B8FEA09AB1   Land of Illusion - Starring Mickey Mouse/COUNTRY=EU,BR/PRODUCT_NO=9014\r\nSMS 0ca95637 B3C4296E5BC63899   Laser Ghost/COUNTRY=EU/PRODUCT_NO=7074/COMMENT=This game can be played using the Light Phaser. To enable this feature, start the game by pressing a button on the second Control Pad.\r\nSMS eb71247b DF5DEA1CDB3EC8DD   Lethal Weapon 3 [Music] [Proto]/FLAGS=PROTO/COUNTRY=EU/COMMENT=Sound driver and music tracks by Jeroen Tel, for the unreleased \"Lethal Weapon 3\" game.\r\nSMS 6350e649 EBBA1A5F14B6D543   Legend of Illusion - Starring Mickey Mouse/COUNTRY=BR/PRODUCT_NO=028750/COMMENT=This is a port from the Game Gear version.\r\nSMS f369b2d8 C3A7D6B47AE01C96   Lemmings/COUNTRY=EU,BR,KR/PRODUCT_NO=7108,025204,GB2032JG\r\nSMS 2c61ed88 9841AB54F8EB0441   Lemmings [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS cf5aecca FDA25D3F5F358CA5   Lemmings 2 - The Tribes [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nSMS cb09f355 9C076464A46F730F   Line of Fire/COUNTRY=EU,BR,KR/PRODUCT_NO=9006,GB-4011JG/COMMENT=This game has an hidden 3-D Glasses mode. To enable this feature, press both Control Pad buttons during reset.\r\nSMS c352c7eb DC4FD0C90A6F5E65   Lion King, The (Disney's)/NAME_SP=El Rey León (Disney's)/NAME_FR=Le Roi Lion (Disney's)/NAME_DE=Der König Der Löwen (Disney's)/NAME_IT=Il Re Leone/COUNTRY=EU,SP,FR,DE,BR,IT/PRODUCT_NO=MK-27081-50,MK-27081-06,MK-27081-09,MK-27081-18,MK-27081-13,028450\r\nSMS aa7d6f45 572DF98CDFB5D98A   Lord of Sword/COUNTRY=JP/PRODUCT_NO=G-1361/COMMENT=Japanese version of \"Lord of The Sword\".\r\nSMS 7eaed675 DCA3A3F9337D95A0   Lord of Sword [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-05/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS e8511b08 92362CB89D5572F0   Lord of The Sword/COUNTRY=US,EU,BR/PRODUCT_NO=7016/COMMENT=Export version of \"Lord of Sword\".\r\nSMS 323f357f 10BBC3D7919A561A   Loretta no Shouzou/COUNTRY=JP/PRODUCT_NO=G-1315\r\nSMS a1710f13 57B8D77289FE41E0   Lucky Dime Caper, The - Starring Donald Duck/NAME_BR=Lucky Dime Caper, The - Estrelando Pato Donald/COUNTRY=EU,BR/PRODUCT_NO=7072,7072-50\r\nSMS 7f6d0df6 FF0D4BCCBFED062B   Lucky Dime Caper, The - Starring Donald Duck [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game, featuring a single playable level and no sound. Cartridge label says \"Donald Duck\".\r\nSMS bcfbfc67 C3982C78688D8983   Mahjong Sengoku Jidai/NAME_HK=Mah-jong/COUNTRY=JP,HK/PRODUCT_NO=G-1337\r\nSMS 996b2a07 17F25E349C4BF48A   Mahjong Sengoku Jidai [Proto]/COUNTRY=JP/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS ca860451 DFCFA670AC174930   Makai Retsuden/COUNTRY=JP/PRODUCT_NO=G-1324/COMMENT=Japanese version of \"Kung Fu Kid\".\r\nSMS bf0411ad FFA3B9E9C1445E59   Maou Golvellius/COUNTRY=JP/PRODUCT_NO=G-1363/COMMENT=Japanese version of \"Golvellius - Valley of Doom\".     ; [EDITOR NOTE] SMS checksum is wrong, was verified on original cartridge.\r\nSMS 21a21352 FEA3B9E9C1445D5B   Maou Golvellius [Proto]/FLAGS=PROTO/COUNTRY=JP/COMMENT=Prototype version of the game.\r\nSMS bf6f3e5f EFA3373E2142D2C4   Marble Madness/COUNTRY=EU/PRODUCT_NO=27024-50\r\nSMS e8ea842c 8865855EC8C5267D   Marksman Shooting & Trap Shooting/COUNTRY=US,BR/PRODUCT_NO=6003/EMU_INPUTS=LIGHTPHASER\r\nSMS e8215c2e 73340E125480BFA6   Marksman Shooting \\/ Trap Shooting \\/ Safari Hunt/COUNTRY=EU,DE,IT,BR/EMU_INPUTS=LIGHTPHASER\r\nSMS 96fb4d4b 4B833BC369A0A586   Master of Darkness/COUNTRY=EU,BR/PRODUCT_NO=7107,7107-50,025112\r\nSMS 20f40cae 5B02852A4E1B3952   Master of Darkness \\/ Vampire [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Title screen says \"Vampire\" which was a working title.\r\nSMS 93141463 6A32F08336B0FA11   Masters of Combat/COUNTRY=EU,AU,BR/PRODUCT_NO=7124,9028/COMMENT=Master System version of \"Buster Fight\" on the Game Gear.\r\nSMS 31b8040b 8775EA954C13F531   Maze Hunter 3-D/COUNTRY=US,EU,BR/PRODUCT_NO=8003/EMU_3D/COMMENT=Export version of \"Maze Walker\".\r\nSMS e0a8e408 580EAEDFD42EDA31   Maze Hunter 3-D [Proto]/FLAGS=PROTO/EMU_3D/COMMENT=Prototype version of the game.\r\nSMS 871562b0 6F10F2363597F697   Maze Walker/COUNTRY=JP,KR/PRODUCT_NO=G-1345,GB-1345/EMU_3D/COMMENT=Japanese version of \"Maze Hunter 3-D\".\r\nSMS 919b4b6e A7D1D652604B1D98   Mega Mode Super Game 30 [SMS-MD]/COUNTRY=KR/PRODUCT_NO=SA-3001/EMU_MAPPER=24\r\nSMS 7f667485 22B314C00393348D   Mega Mode Super Game 138 [SMS-MD]/COUNTRY=KR/EMU_MAPPER=25\r\nSMS 29bc7fad 9AE49900AF32A95F   Megumi Rescue/COUNTRY=JP/PRODUCT_NO=G-1359/EMU_INPUTS=PADDLE\r\nSMS d7416b83 0C2287D260615D5B   Mercs/COUNTRY=EU,BR/PRODUCT_NO=9007\r\nSMS 25051dd5 61223A2720C539FE   Mickey's Ultimate Challenge/COUNTRY=BR/PRODUCT_NO=028700/COMMENT=This is a port from the Game Gear version.\r\nSMS a577ce46 8264C47AA02D1CF3   Micro Machines/COUNTRY=EU/PRODUCT_NO=19001/EMU_MAPPER=3/EMU_TVTYPE=PAL\r\nSMS 41cc2ade 2197A343DD55D25E   Micro Xevious, The/COUNTRY=KR\r\nSMS 0e333b6e 5DF944A13D3573E0   Miracle Warriors - Seal of The Dark Lord/COUNTRY=US,EU,BR/PRODUCT_NO=7500/COMMENT=Export version of \"Haja no Fuuin\".\r\nSMS 301a59aa C6AE142A815DF27E   Miracle Warriors - Seal of The Dark Lord [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS fbe5cfbb 32DAD3B36F53F7B5   Missile Defense 3-D/NAME_BR=Missile Defense 3D/COUNTRY=US,EU,BR/PRODUCT_NO=8001,023230/EMU_INPUTS=LIGHTPHASER/EMU_3D/EMU_LP_FUNC=1\r\nSMS 43def05d 9EFD71605F7B0FAB   Missile Defense 3-D [Proto]/FLAGS=PROTO/EMU_INPUTS=LIGHTPHASER/EMU_3D/EMU_LP_FUNC=1/COMMENT=Prototype version of the game.\r\nSMS 01d67c0b 78D6D79A391713DE   Mônica no Castelo do Dragão/COUNTRY=BR/COMMENT=Brasilian hacked version of \"Wonder Boy in Monster Land\", released by Tec Toy.\r\nSMS 026d94a4 486A3C3EC40B37CE   Monopoly/COUNTRY=EU\r\nSMS 69538469 4D632D43B6FE42EA   Monopoly/COUNTRY=US\r\nSMS 7e9d87fc BFD80824BC3567E5   Monopoly [Proto 0]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game.\r\nSMS e0d1049b 69795E6B0DBDB3D8   Monopoly [Proto 1]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game. Marked \"1988.04.22\".\r\nSMS 82fda895 E5824AEB86A48CAE   Montezuma's Revenge - Featuring Panama Joe/COUNTRY=US/PRODUCT_NO=4370\r\nSMS 575d0fcf 530F373A728F5BD1   Montezuma's Revenge - Featuring Panama Joe [Proto]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game.\r\nSMS 56cc906b FA387D6C37963DDB   Moonwalker (Michael Jackson's)/NAME_BR=Moonwalker/COUNTRY=US,EU,BR,KR/PRODUCT_NO=7052,GB2004JG\r\nSMS 54123936 F6367C6B39953EE1   Moonwalker (Michael Jackson's) [Proto]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game.\r\nSMS fac1d0bc 91D7102A0C6B07E0   Moonwalker (Michael Jackson's) [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-08/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS b49aa6fc F77F4A19E34FD71E   Mopiranger/COUNTRY=KR\r\nSMS 302dc686 BC55ADDD0F5CF901   Mortal Kombat/COUNTRY=EU,BR/PRODUCT_NO=MK-29021-50,028240\r\nSMS 2663bf18 C71D87669810186F   Mortal Kombat II/COUNTRY=EU,BR,AU/PRODUCT_NO=MK-29029-50,028530\r\nSMS 395ae757 6E91621C296C02EC   Mortal Kombat 3/COUNTRY=BR/PRODUCT_NO=028730/COMMENT=This is a port from the Game Gear version.\r\nSMS 3cd816c6 F78B647E2DECD2B1   Ms. Pac-Man/COUNTRY=EU,BR/PRODUCT_NO=301030-0160\r\nSMS ff5091e0 CF1D3E59D0C1C824   MSX Soccer/COUNTRY=KR/PRODUCT_NO=G-137\r\nSMS 62f0c23d ED4ACAF1CF794680   My Hero/NAME_BR=Gang's Fighter/COUNTRY=US,EU,BR,PT,DE,IT/PRODUCT_NO=4001,4501,021030,41004/COMMENT=Export version of \"Seishun Scandal\".\r\nSMS 332a847d 59A05C7FBF656A9E   NBA Jam [Proto]/FLAGS=PROTO/EMU_TVTYPE=PAL/COMMENT=Prototype version of the unreleased game.\r\nSMS 5b5f9106 43FAFA9DD769AB41   Nekkyuu Koushien/COUNTRY=JP/PRODUCT_NO=G-1367\r\nSMS e316c06d E8185C6373EE5090   Nemesis/COUNTRY=KR/EMU_MAPPER=12\r\nSMS 0a77fa5e D9A608B8110F2B76   Nemesis 2/COUNTRY=KR/EMU_MAPPER=12\r\nSMS dbbf4dd1 BD4A36BDBE1C7FAD   New Boggle Boggle 2/COUNTRY=KR/COMMENT=Unlicensed clone of \"Bubble Bobble\".\r\nSMS c660ff34 0F4613232FB9602D   NewZealand Story, The/COUNTRY=EU/PRODUCT_NO=27035-50\r\nSMS 320313ec 690DDE10E39C7CA1   Ninja, The/COUNTRY=JP/PRODUCT_NO=G-1308\r\nSMS 66a15bd9 6E674174DCF99F02   Ninja, The/NAME_IT=I Ninja/COUNTRY=US,EU,IT,DE,BR/PRODUCT_NO=5066,41012,023350\r\nSMS 2cd62dca 96D8CAD5B690505D   Ninja, The [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-13,HG 202-01/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 1b1d8cc2 9E56B510032E6FA7   Ninja Gaiden/COUNTRY=EU,BR/PRODUCT_NO=7101\r\nSMS 761e9396 762C4C122E81DD74   Ninja Gaiden [Proto]/FLAGS=PROTO/COUNTRY=EU,BR/COMMENT=Prototype version of the game.\r\nSMS d1a7b1aa 17D121A728287888   Olympic Gold [v0]/COUNTRY=KR,BR/PRODUCT_NO=GB2023JG\r\nSMS 6a5a1e39 A6491A91F74F0A16   Olympic Gold [v1]/COUNTRY=EU,UK,AU,SP,FR,DE/PRODUCT_NO=MK-27030-50,MK-27030-05,MK-27030-06,MK-27030-09,MK-27030-18\r\nSMS a2f9c7af 972BE85E65BA5A7F   Olympic Gold [v0] [SMS-GG]/COUNTRY=US,JP,BR/PRODUCT_NO=T-79018,G-3316,015810/FLAGS=SMSGG_MODE\r\nSMS 3382d73f 9B2BE85C65BA5A7D   Olympic Gold [v0] [SMS-GG]/COUNTRY=TW/FLAGS=SMSGG_MODE/COMMENT=This minor hack of the code enable the game to run on unlicensed cartridges using a slightly incompatible mapper.\r\nSMS 1d93246e 489D35A442E436E6   Olympic Gold [v1] [SMS-GG]/COUNTRY=EU,DE,FR,UK,SP/PRODUCT_NO=79018-50,79018-18,79018-09,79018-05,79018-06/FLAGS=SMSGG_MODE\r\nSMS bea27d5c 7DBE1156242EEE1E   Opa Opa/COUNTRY=JP,KR/PRODUCT_NO=G-1343,GB-1343/COMMENT=Japanese version of \"Fantasy Zone: The Maze\".\r\nSMS 205caae8 0BD7C48F97528F53   Operation Wolf/COUNTRY=EU,BR/PRODUCT_NO=7039/EMU_INPUTS=LIGHTPHASER/EMU_TVTYPE=PAL/COMMENT=This game can also be played using the second Control Pad.\r\nSMS 82ef2a7d 9C0F1AFF59252A94   Ottifants, The/COUNTRY=EU,BR/PRODUCT_NO=7120,025450\r\nSMS 5589d8d2 B32F41555F15C94B   Out Run/NAME_BR=OutRun/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1326,7003,024240/COMMENT=This game optionally support the Paddle Control.\r\nSMS d6f43dda 1BB3AE977AC3CCE4   Out Run 3-D/NAME_BR=Out Run 3D/COUNTRY=EU,BR/PRODUCT_NO=8007/EMU_3D/COMMENT=This game optionally support the Paddle Control. The 3-D effect can be disabled by pressing Pause on title screen.\r\nSMS 4e684ec0 9FF9E104E43B97CD   Out Run 3-D [Proto]/FLAGS=PROTO/EMU_3D/COMMENT=Prototype version of the game.\r\nSMS 3932adbc 436E35E9D2EFEF81   Out Run Europa/COUNTRY=EU,BR/PRODUCT_NO=27016-50\r\nSMS f037ec00 3BFAB46092543899   Out Run Europa [SMS-GG]/COUNTRY=US/FLAGS=SMSGG_MODE/PRODUCT_NO=T-79038\r\nSMS 01eab89d 45F5AC628D4F37A5   Out Run Europa [SMS-GG]/COUNTRY=EU,BR/FLAGS=SMSGG_MODE/PRODUCT_NO=79038-50,016870\r\nSMS be57a9a5 7DBED7938B8E4FF3   Pac-Mania/COUNTRY=EU/PRODUCT_NO=25010-50/COMMENT=Also referred to as \"Pacmania\".\r\nSMS 294e0759 EBC446E748FB6978   Paperboy [v0]/COUNTRY=EU/PRODUCT_NO=25008-50\r\nSMS 327a0b4c 266B27943121471B   Paperboy [v1]/COUNTRY=US,BR/PRODUCT_NO=5121\r\nSMS 354bee78 A63466570BFB253E   Paperboy [v1] [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-23/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Paper Boy\".\r\nSMS e030e66c 621888488B1D43CB   Parlour Games/COUNTRY=US,EU/PRODUCT_NO=5103/COMMENT=Export version of \"Family Games\" (\"Party Games\").\r\nSMS 9aefe664 B3AE3F297F8E9793   Pat Riley Basketball [Proto]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the unreleased game.\r\nSMS 445525e2 C78797B1481E0FF5   Penguin Adventure/COUNTRY=KR/EMU_MAPPER=12\r\nSMS f97e9875 E01345F078025D01   Penguin Land/COUNTRY=US,EU/PRODUCT_NO=5501/COMMENT=Export version of \"Doki Doki Penguin Land - Uchuu Daibouken\".\r\nSMS 95b9ea95 5C82866D629F75B9   PGA TOUR Golf/COUNTRY=EU/PRODUCT_NO=27070-50 301045-0160\r\nSMS 6605d36a 2E083BD3646B9C51   Phantasy Star/COUNTRY=JP/PRODUCT_NO=G-1341\r\nSMS e4a65e79 ABD648F1F23F54C1   Phantasy Star [v2]/COUNTRY=US,EU/PRODUCT_NO=9500/COMMENT=This first batch of the English localization has a minor graphic bug. In the interface, when trying to save from certain place, there's garbage on the screen. It was fixed in version 3 of the ROM, which is more common.\r\nSMS 00bef1d7 ABD447F2F23F56C1   Phantasy Star [v3]/COUNTRY=US,EU/PRODUCT_NO=9500\r\nSMS 75971bef 1B751562EAF667B2   Phantasy Star/COUNTRY=BR/PRODUCT_NO=029010\r\nSMS 747e83b5 4CB57E6A76C6CF0C   Phantasy Star/COUNTRY=KR/PRODUCT_NO=GB 4014KS\r\nSMS 07301f83 A8CCBAD5B519DA55   Phantasy Star Fukkokuban [SMS-MD]/COUNTRY=JP/PRODUCT_NO=G-4534/COMMENT=This is the Sega Megadrive version, as reissued in Japan on April 2nd, 1994. It was later included in \"Phantasy Star Collection\" for the Sega Saturn.\r\nSMS c0ac6956 468A729CE9D4A6BF   Pigu-Wang 7 Hap - Jaemiiss-neun Game Mo-eumjip/COUNTRY=KR/EMU_MAPPER=25\r\nSMS b840a446 99682219F73E5738   Pit-Fighter/COUNTRY=EU/PRODUCT_NO=MK 29009-50\r\nSMS aa4d4b5a B0EEC623306A5986   Pit-Fighter/COUNTRY=BR/PRODUCT_NO=028250\r\nSMS ca082218 CC2A2FBFE47BE4D9   Pooyan/COUNTRY=KR\r\nSMS c7a1fdef E9FF01CC584A7A2F   Populous/COUNTRY=EU,BR/PRODUCT_NO=27014\r\nSMS abd48ad2 DFAFA4ECD0D02D15   Poseidon Wars 3-D/NAME_BR=Poseidon Wars 3D/COUNTRY=US,EU,BR/PRODUCT_NO=8006/EMU_3D/COMMENT=The 3-D effect can be disabled by pressing Control Pad 2 Button 1 on title screen.\r\nSMS 6d309ac5 DF29E600439575C5   Power Boggle Boggle/COUNTRY=KR/COMMENT=Unlicensed clone of \"Bubble Bobble\".\r\nSMS 4077efd9 A3A0129B65F27148   Power Strike/COUNTRY=US,EU,BR,KR/PRODUCT_NO=5109,GB-1004\r\nSMS a109a6fe 2BC9EC1AC078E1ED   Power Strike II/COUNTRY=EU,BR/PRODUCT_NO=9024\r\nSMS 0047b615 CCDD81E10B375F54   Predator 2/COUNTRY=EU/PRODUCT_NO=MK-27026-50/EMU_TVTYPE=PAL\r\nSMS 2b54c82b E77D821B153FC3E8   Predator 2/COUNTRY=BR/PRODUCT_NO=027110\r\nSMS e5f789b9 C5D3A3094BD09F02   Predator 2 [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=US,EU/PRODUCT_NO=T-81068,T-81068-50\r\nSMS 7704287d 2AD78D0B99231992   Prince of Persia/COUNTRY=EU,BR/PRODUCT_NO=27022-50,027270\r\nSMS 311d2863 A7AF7C148412B4D0   Prince of Persia [SMS-GG]/COUNTRY=US/PRODUCT_NO=T-48098 301053-0161/FLAGS=SMSGG_MODE\r\nSMS 45f058d6 A8AB7C128212B8D3   Prince of Persia [SMS-GG]/COUNTRY=EU/PRODUCT_NO=T-88018-50/FLAGS=SMSGG_MODE\r\nSMS cafd2d83 2C1E66E95ED392A4   Prince of Persia [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-15/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Prince of Persia\" in English and \"Ali Papa Densetsu\" in Japanese.\r\nSMS 30af0233 6B2F747298C5F330   Promocao Especial M.System III Compact/COUNTRY=BR/COMMENT=Tec Toy cartridge sent to Brasilian shops, promoting the Master System III Super Compact and release of Sonic The Hedgehog 2.\r\nSMS fbde42d3 FE6C6689595835C1   Pro Wrestling/COUNTRY=US,EU,DE,IT,BR/PRODUCT_NO=5056,41009/COMMENT=Export version of \"Gokuaku Doumei Dump Matsumoto\".\r\nSMS da9be8f0 368FE6B9C92FC4E0   Pro Yakyuu Pennant Race, The/COUNTRY=JP/PRODUCT_NO=G-1323\r\nSMS 5c0b1f0f 106D424E827F1FD3   Psychic World/COUNTRY=EU,BR/PRODUCT_NO=7066\r\nSMS 97993479 51C5A27AE5C1A97F   Psycho Fox/COUNTRY=US,EU,BR,KR/PRODUCT_NO=7032,GB-7032\r\nSMS 4bf0e1cc 77EDC51FDB6C6D04   Psycho Fox [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 357d4f78 F8FBE39B6B9A7A10   Putt & Putter/NAME_BR=Minigolf/COUNTRY=EU,BR/PRODUCT_NO=5122\r\nSMS 8167ccc4 57D2E5AF6CF007E0   Putt & Putter [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 76e8265f 22792EA4280C8FD0   Puznic/COUNTRY=KR\r\nSMS e0f34fa6 7B806045EC630110   Quartet/COUNTRY=US,EU/PRODUCT_NO=5073/COMMENT=Export version of \"Double Target - Cynthia no Nemuri\".\r\nSMS cacdf759 603D4A07BB29C36B   Quartet [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-28/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS f42e145c B8840BAF3B2A2C79   Quest for the Shaven Yak Starring Ren Hoëk & Stimpy/COUNTRY=BR/PRODUCT_NO=028540/EMU_TVTYPE=PAL/COMMENT=This is a port from the Game Gear version.\r\nSMS c172a22c 7BCD35D3A8365C76   Rainbow Islands/COUNTRY=EU/PRODUCT_NO=7117\r\nSMS 00ec173a 60C74DD2B1355C78   Rainbow Islands/COUNTRY=BR/PRODUCT_NO=026360/COMMENT=This version is an earlier build than the European version. It has different copyright information.\r\nSMS bbda65f0 35A0597C0B263AEB   Rambo - First Blood Part II/COUNTRY=US/PRODUCT_NO=5064/COMMENT=Same game as \"Ashura\" (Japan) and \"Secret Command\" (Europe). Also referred to as \"Rambo\".\r\nSMS da5a7013 670E95C06B26376E   Rambo III/COUNTRY=US,EU,BR,KR/PRODUCT_NO=7015,GB-7015/EMU_INPUTS=LIGHTPHASER\r\nSMS 42fc47ee 554C7BE855EAE1DC   Rampage/COUNTRY=US,EU,BR/PRODUCT_NO=QC-001,27005\r\nSMS 0e0d6c7a 7F450EE1FC11AE92   Rampage [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 426e5c8a 23F4F2C7282735AC   Rampart/COUNTRY=EU/PRODUCT_NO=301026-0160\r\nSMS c547eb1b 1DA1B2C2A17604B3   Rastan/COUNTRY=US,EU,BR/PRODUCT_NO=7022\r\nSMS f063bfc8 3795FE95416244BA   Rastan [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 9c76fb3a D5F5307E4C80328A   Rastan Saga [SMS-GG]/COUNTRY=JP/FLAGS=SMSGG_MODE/PRODUCT_NO=T-11037\r\nSMS 54316fea A3E4BFF29BB8066F   R.C. Grand Prix/COUNTRY=US,EU,BR/PRODUCT_NO=27007\r\nSMS 767f11b8 5EDFCCBA77EF03D4   R.C. Grand Prix [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 56201996 A88B7C7AF6466F2C   R.C. Grand Prix [SMS-GG]/COUNTRY=US/PRODUCT_NO=T-86018\r\nSMS cca47191 291934813022C1F6   R.C. Grand Prix [Proto] [SMS-GG]/FLAGS=PROTO/COMMENT=Prototype version of the GG version. On NTSC systems the Sega logo repeats for a while.\r\nSMS 6d94bb0e 4D23BD40BBC8C14F   Reggie Jackson Baseball/COUNTRY=US/PRODUCT_NO=7019\r\nSMS 3be7f641 62359CD87BD76D36   Renegade/COUNTRY=EU,BR/PRODUCT_NO=7116\r\nSMS 79ac8e7f 3913D462E83B4912   Rescue Mission/COUNTRY=US,EU,BR/PRODUCT_NO=5106/EMU_INPUTS=LIGHTPHASER\r\nSMS 8034bd27 329541104FC89140   Road Fighter/COUNTRY=KR\r\nSMS b876fc74 E1D4360F1398203B   Road Rash/COUNTRY=EU,PT,BR,AU/PRODUCT_NO=29012-50,028410\r\nSMS 9f951756 D1F812706360AE44   RoboCop 3/COUNTRY=EU,BR/PRODUCT_NO=MK-27064-50,027350/EMU_TVTYPE=PAL\r\nSMS 8212b754 7C3D8387CD52CB53   RoboCop versus The Terminator/COUNTRY=EU,BR/PRODUCT_NO=MK-29022-50,29022-50,028520\r\nSMS 1bcc7be3 6510DE9EFF33617C   Rocky/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1319,7002\r\nSMS bb54b6b0 5286A12D022F2801   R-Type/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1364,9002\r\nSMS 0d0840d5 BB28E74692B7DBCC   R-Type [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Data layout is different from final build but otherwise content is the same.\r\nSMS e532716f 217A297127BA42A8   R-Type [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 401-01/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 1fdae719 9815A90C29BA6556   Running Battle/COUNTRY=EU,BR/PRODUCT_NO=7037,024300\r\nSMS 66388128 D28E2F698C014338   Sagaia/COUNTRY=EU,BR/PRODUCT_NO=7078\r\nSMS 29610b58 FB57115A77F330A9   Sagaia [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-38/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 97d03541 49C0303E13D3CBD8   Samgukji III/NAME_JP=Sangokushi III/COUNTRY=KR/EMU_MAPPER=9\r\nSMS 0e7a5f9f A98E33A9C7FDAC7D   Sapo Xulé O Mestre do Kung Fu/COUNTRY=BR/PRODUCT_NO=023500/COMMENT=Hacked version of \"Kung Fu Kid\", released by Tec Toy.\r\nSMS 7ab2946a 137517DF00728D83   Sapo Xulé S.O.S. Lagoa Poluída/COUNTRY=BR/PRODUCT_NO=023510/COMMENT=Hacked version of \"Astro Warrior\" by Tec Toy.\r\nSMS 9a608327 A55A9508345B7560   Sapo Xulé Vs Os Invasores do Brejo/COUNTRY=BR/PRODUCT_NO=026340/COMMENT=Hacked version of \"Psycho Fox\", released by Tec Toy.\r\nSMS 16249e19 ABFBCE1810529280   Satellite 7/COUNTRY=JP/PRODUCT_NO=C-506\r\nSMS 9a8b28ec 8C879DB38E98096E   Scramble Spirits/COUNTRY=EU,BR/PRODUCT_NO=7031\r\nSMS b45d4700 82DD270F13DA2F4F   Scramble Spirits [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 7d59283b 0A6F1CFCF5311831   Scramble Spirits [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-09/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 1de2c2d0 FD39BA27B96F853C   SDI/COUNTRY=JP,KR/PRODUCT_NO=G-1338,GB-1338/COMMENT=Means \"Strategic Defense Initiative\". Japanese version of \"Global Defense\".\r\nSMS 00529114 E7DF258AF50C0981   Secret Command/COUNTRY=EU/PRODUCT_NO=5081/COMMENT=Also referred to as \"Secret Commando\" on title screen. Same game as \"Ashura\" (Japan) and \"Rambo - First Blood Part II\" (USA).\r\nSMS 89efcc22 D2D92284F30609AD   Secret Command [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 101-07/COMMENT=Taiwanese HTH release for Game Gear. Box title is yet unknown.\r\nSMS a8061aef A2AB60901AE8F3CE   Sega Chess/COUNTRY=EU,BR/PRODUCT_NO=7069\r\nSMS 276aa542 1490B536046BD32F   Sega Graphic Board v2.0 [Proto]/FLAGS=PROTO/EMU_INPUTS=GRAPHICBOARDV2/EMU_MAPPER=11\r\nSMS 296879dd C1191ABD8EFFA31F   Sega World Tournament Golf/COUNTRY=EU,BR,KR/PRODUCT_NO=7103,024420,GB2038JG\r\nSMS f0ba2bc6 A2297AFAC9472988   Seishun Scandal/COUNTRY=JP/PRODUCT_NO=C-510/COMMENT=Japanese version of \"My Hero\".\r\nSMS d0263024 81845E918735BE92   Seishun Scandal [HTH] [SMS-GG]/COUNTRY=TW/FLAGS=SMSGG_MODE/PRODUCT_NO=HG 256-06/COMMENT=Taiwanese HTH release for Game Gear. Box says \"Action Boy\".\r\nSMS f8176918 233B773430937DB7   Sensible Soccer/COUNTRY=EU/PRODUCT_NO=8011,MK-25014-50\r\nSMS 3793c01a BB279C12C22FBFC0   Shadow Dancer - The Secret Of Shinobi/NAME_BR=The Secret Of Shinobi/NAME_KR=Shadow Dancer/COUNTRY=EU,BR,KR/PRODUCT_NO=9009,GB4010JG\r\nSMS ab67c6bd FFCF49E495178BCE   Shadow Dancer - The Secret Of Shinobi [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 401-06/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 1575581d F96C3BA032F7D6C1   Shadow of the Beast/COUNTRY=EU,BR/PRODUCT_NO=27019-50,025270/EMU_TVTYPE=PAL\r\nSMS ac2ea669 D7DF5953A9944D14   Shadow of the Beast [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-47/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS aab67ec3 EC0F9129D095CB1B   Shanghai/COUNTRY=US,EU/PRODUCT_NO=5110\r\nSMS d5d25156 CBF272B7DA6BC90C   Shanghai [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS e1fff1bb E3EBF1D8895B9FE6   Shinobi [v0]/COUNTRY=JP,BR/PRODUCT_NO=G-1353,028380\r\nSMS 0c6fac4e DEF9F2C7A058ADCB   Shinobi [v1]/COUNTRY=US,EU,BR,KR/PRODUCT_NO=7009,GB-2353\r\nSMS 4b051022 034E26895A59CF7E   Shooting Gallery/NAME_BR=Shooting G./COUNTRY=US,EU,BR,IT/PRODUCT_NO=5072/EMU_INPUTS=LIGHTPHASER\r\nSMS abdf3923 10361067C4C6C7F2   Sítio do Picapau Amarelo/COUNTRY=BR/PRODUCT_NO=028710\r\nSMS 77ba2667 0A9445E774AD31E4   Sky Fighter/COUNTRY=KR/PRODUCT_NO=G-M1\\/4\r\nSMS 5b8e65e4 F7E1FEDA866F82D9   Sky Jaguar/COUNTRY=KR/EMU_MAPPER=11\r\nSMS e3f260ca 9DEBAC77C07066BF   Sky Jaguar [Clover]/COUNTRY=KR/EMU_MAPPER=11\r\nSMS c93bd0e9 594106F8C181ED39   Slap Shot [v0]/COUNTRY=EU/PRODUCT_NO=7035\r\nSMS d33b296a 094AF2F7B08DE3A4   Slap Shot [v1]/COUNTRY=EU/PRODUCT_NO=7035\t\t; [EDITOR-NOTE] Some DB label this one \"UE\" but I have no source for it\r\nSMS 702c3e98 124C00EBBF84E58F   Slap Shot [v2]/COUNTRY=US,BR/PRODUCT_NO=7035,024430\r\nSMS fbb0a92a EB6998CED0932CB7   Slap Shot [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Title screen says \"Slap Shoot\".\r\nSMS 3e63768a 0199AF74006BE2F6   Smurfs, The/NAME_FR=Les Schtroumpfs/COUNTRY=EU,BR/PRODUCT_NO=MK-27082-50,027380/COMMENT=Also referred to using the french title showing on the cartridge: \"Les Schtroumpfs\".\r\nSMS 97e5bb7d 4F65ACDA08A4B169   Smurfs Travel the World, The/NAME_FR=Les Schtroumpfs Autour du Monde/PRODUCT_NO=MK-27085-50/COMMENT=Also referred to using the french title showing on the box: \"Les Schtroumpfs Autour du Monde\".\r\nSMS 7982ae67 5064ACDA08A4B268   Smurfs Travel the World, The [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game, only 2 bytes differs from final version.\r\nSMS 11645549 146FA8E655225E1A   Solomon no Kagi - Oujo Rihita no Namida/COUNTRY=JP/PRODUCT_NO=002\r\nSMS 92dc4cd6 80CC1AC534E69427   Solomon no Kagi - Oujo Rihita no Namida [Proto]/COUNTRY=JP/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 96b3f29e 5A989B9EFF10EED8   Sonic Blast/COUNTRY=BR/PRODUCT_NO=030030/EMU_TVTYPE=PAL/COMMENT=This is a port from the Game Gear version.\r\nSMS aedf3bdf 724EF423E356618F   Sonic Chaos/COUNTRY=EU,BR/PRODUCT_NO=9021,028120\r\nSMS 11c1bc8a D3A4F10A4B37C04C   Sonic Spinball/COUNTRY=EU,BR,AU/PRODUCT_NO=9034,028489\r\nSMS b519e833 2F2C8E1A0AE456B9   Sonic The Hedgehog/COUNTRY=EU,US,BR/PRODUCT_NO=7076\r\nSMS 5b3b922c 89244C65041595F4   Sonic The Hedgehog 2 [v0]/COUNTRY=EU,BR/PRODUCT_NO=9015,028120/EMU_TVTYPE=PAL\r\nSMS d6f2bfca 9E35369CB6BB509A   Sonic The Hedgehog 2 [v1]/COUNTRY=EU,BR,KR/PRODUCT_NO=9015,028120,GB4030JG/EMU_TVTYPE=PAL\r\nSMS d9096263 3DC6AEC840CA126B   Sonic's Edusoft [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased educational game software.\r\nSMS a908cff5 33FD350EEDE48D2F   Space Gun/COUNTRY=EU/PRODUCT_NO=9010/EMU_INPUTS=LIGHTPHASER\r\nSMS ca1d3752 82CBE6058E19A67B   Space Harrier [50 Hz]/COUNTRY=EU/PRODUCT_NO=7080/EMU_TVTYPE=PAL\r\nSMS beddf80e 0AEA3665ABDB3AB1   Space Harrier [50-60 Hz]/COUNTRY=JP,US/PRODUCT_NO=G-1310,7080\r\nSMS 6bd5c2bf BEFA25D66361C8C1   Space Harrier 3-D/COUNTRY=US,EU,BR/PRODUCT_NO=8004/EMU_3D/COMMENT=The 3-D effect can be removed by doing the following: complete the game with a score that qualifies for a sixth or higher position on the high score screen, then enter THREE as a name on the high score screen with Control Pad 2.\r\nSMS 156948f9 97FA12D86875C8E0   Space Harrier 3D/COUNTRY=JP/PRODUCT_NO=G-1349/EMU_3D/COMMENT=The 3-D effect can be removed by doing the following: complete the game with a score that qualifies for a sixth or higher position on the high score screen, then enter THREE as a name on the high score screen with Control Pad 2.\r\nSMS fa8e4ca0 A6E188CF3FB0E053   Special Criminal Investigation - S.C.I./COUNTRY=EU/PRODUCT_NO=7079\r\nSMS 1b7d2a20 AEE088CC3FB0E04F   Special Criminal Investigation - S.C.I. [Proto]/FLAGS=PROTO/COMMENT=Pre-approval prototype version of the game. Game content is identical, only the ROM header is different.\r\nSMS a57cad18 A416C45F248AD89D   Speedball [Image Works]/COUNTRY=EU/PRODUCT_NO=25009-50\r\nSMS 5ccc1a65 7B32EAE9E99C54A7   Speedball [Virgin]/COUNTRY=EU/PRODUCT_NO=25013-50\r\nSMS 0c7366a0 5D5B88F6AA6D367D   Speedball 2/COUNTRY=EU/PRODUCT_NO=27039-50\r\nSMS 4752cae7 DCC8653E70E4F66F   SpellCaster/COUNTRY=US,EU,BR/PRODUCT_NO=9003/COMMENT=Export version of \"Kujakuou\"\r\nSMS ebe45388 5C12588F41421117   Spider-Man - Return of the Sinister Six/COUNTRY=EU,BR/PRODUCT_NO=MK-27055-50,026290\r\nSMS 908ff25c F0697EEFE5278CA2   Spider-Man - vs. The Kingpin/COUNTRY=EU,US,BR,AU/PRODUCT_NO=7065\r\nSMS 41c948bf 6333A82396B2CF88   Sports Pad Soccer/COUNTRY=JP/PRODUCT_NO=G-1365/EMU_INPUTS=SPORTSPAD\r\nSMS e42e4998 C4C45B848BC2A3A9   Sports Pad Football/COUNTRY=US/PRODUCT_NO=5060/EMU_INPUTS=SPORTSPAD\r\nSMS 78d7faab 83A4D6495B81DD01   Spy vs Spy/COUNTRY=US,EU,DE,AU,BR,IT/PRODUCT_NO=4083,4583,41021/COMMENT=Sometimes referred to as \"Spy Vs. Spy\".\r\nSMS d41b9a08 440AA3B0518BF192   Spy vs Spy/COUNTRY=JP,KR/PRODUCT_NO=C-514,SG15C\r\nSMS 689f58a2 CDE5989D3972E985   Spy vs Spy/COUNTRY=TW/PRODUCT_NO=K-321\r\nSMS d4b8f66d 92936B306B38B8E5   Star Wars/COUNTRY=EU,BR/PRODUCT_NO=29014-50,028260\r\nSMS 01a2d595 1E802D0CDFBA761A   Street Battle [Proto] [SMS-GG]/COUNTRY=US/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of the unreleased game. This is a conversion from the Korean original \"Jang Pung II\".\r\nSMS 0f8287ec 905391ED1A483904   Street Fighter II'/COUNTRY=BR/PRODUCT_NO=030010\r\nSMS 9fa727a0 A66B4A6607E970DF   Street Hero [Proto 0] [SMS-GG]/COUNTRY=US/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of the unreleased game. This is a conversion from the Korean original \"Janggun-ui Adeul\".\r\nSMS fb481971 E152E02DE2677007   Street Hero [Proto 1] [SMS-GG]/COUNTRY=US/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game. This is a conversion from the Korean original \"Janggun-ui Adeul\".\r\nSMS 83f0eede F1E64D24CBBD220E   Street Master/COUNTRY=KR/EMU_MAPPER=12\r\nSMS 4ab3790f CC782C54E741D242   Streets of Rage/COUNTRY=EU,BR/PRODUCT_NO=9019,028190\r\nSMS 04e9c089 40214E28DB2E75AB   Streets of Rage II/COUNTRY=EU,BR,KR/PRODUCT_NO=9026,028300,GB94002JG\r\nSMS 9802ed31 87B23673DB921899   Strider/COUNTRY=EU,US,BR,KR/PRODUCT_NO=9005,GB4028JG\r\nSMS 63a7f906 8B5F187B87419229   Strider [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 401-02/COMMENT=Taiwanese HTH release for Game Gear. Box says \"The Strider\".\r\nSMS b990269a 4795A5446841741E   Strider [Demo]/FLAGS=PROTO\r\nSMS b8f0915a 44E778659B2ECD62   Strider II/COUNTRY=EU,BR/PRODUCT_NO=29005-50,026250\r\nSMS d8f2f1b9 2E5B54DFAA4D4706   Submarine Attack/COUNTRY=EU,BR/PRODUCT_NO=7048\r\nSMS d282ef71 2E635CDBA9494501   Submarine Attack [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-31/COMMENT=Taiwanese HTH release for Game Gear. Box title is yet unknown.\r\nSMS b13df647 57E32ED9EF14328A   Sukeban Deka II - Shoujo Tekkamen Densetsu/COUNTRY=JP/PRODUCT_NO=G-1318\r\nSMS 8da5c93f AF2D01D4A78C8B91   Summer Games/NAME_BR=Jogos Olímpicos/COUNTRY=EU,BR/PRODUCT_NO=5119\r\nSMS 4f530cb2 D1B42E8EF4C358B0   Summer Games [Proto 0]/FLAGS=PROTO/COMMENT=Early prototype version of the game. No audio.\r\nSMS 80eb1fff 420EEF0B240F3152   Summer Games [Proto 1]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 01686d67 88E8E8D0608B22CB   Suho Jeonsa/COUNTRY=KR/PRODUCT_NO=DS-G402\r\nSMS 0dbf3b4a 01EF5A009C6701B2   Super Basketball [Demo]/FLAGS=PROTO/COUNTRY=US/COMMENT=Rolling non-interactive demo to advertise unreleased game. Was shown at the CES exposition floor in USA (around 1989?).\r\nSMS a66d26cf 5E7FE6D39D642445   Super Bioman I/COUNTRY=KR\r\nSMS bf5a994a 8DF09E55615029B6   Super Boy I/COUNTRY=KR\r\nSMS 67c2f0ff 9FD6C92669F0360D   Super Boy II/COUNTRY=KR\r\nSMS 9195c34c 8585901FA9FBF8AB   Super Boy 3/COUNTRY=KR/EMU_MAPPER=12\r\nSMS b995b4f0 EE7A46299269111D   Super Boy 4/COUNTRY=KR\r\nSMS 22c09cfd 50BB66C5832E8C8D   Super Bubble Bobble/COUNTRY=KR/COMMENT=Unlicensed clone of \"Bubble Bobble\".\r\nSMS 6ce7f694 8B297D82FFFB75DE   Super Columns/COUNTRY=KR/COMMENT=Unlicensed clone. Also referred to as \"Super Columns & Tetris\".\r\nSMS 551e6f51 FA1DF196B3DCEDE6   Super Futebol II [Game Box Série Esportes]/COUNTRY=BR,PT/PRODUCT_NO=028560/COMMENT=Part of \"Game Box Série Esportes\" compilation.\r\nSMS 1b8956d1 CFD4EB5527452E83   Super Game 150/COUNTRY=KR/EMU_MAPPER=22\r\nSMS 4e202aa2 3EE0DA7C01A6786D   Super Game 180/COUNTRY=KR/EMU_MAPPER=20\r\nSMS ba5d2776 1EBAD8829E4FF6EB   Super Game 200/COUNTRY=KR/EMU_MAPPER=20\r\nSMS d9ef7d69 7A8AA34E6083F137   Super Game 270/COUNTRY=KR/EMU_MAPPER=22\r\nSMS d3056492 1537C90CFD960E3E   Super Game 270 Hap ~ Jaemissneun-270/COUNTRY=KR/EMU_MAPPER=18\r\nSMS edb13847 3EEA007A568DAECD   Super Game 45/COUNTRY=KR/EMU_MAPPER=21\r\nSMS a841c0b7 82F73F4413D9CF49   Super Game 52 Hap/COUNTRY=KR/EMU_MAPPER=20\r\nSMS ab07ecd4 BA49364933A43F68   Super Game World 260 Hap/COUNTRY=KR/EMU_MAPPER=18\r\nSMS 0cde0938 2DFBC7EBB5C63576   Super Game World 30 Hap [v0]/COUNTRY=KR/EMU_MAPPER=18\r\nSMS e6ad4d4b 4BD0AAA2A4BBE05A   Super Game World 30 Hap [v1]/COUNTRY=KR/EMU_MAPPER=18/COMMENT=Label says \"Super World 30 Hap\".\r\nSMS c29bb8cd F5394893312A6339   Super Game World 75 Hap/COUNTRY=KR/EMU_MAPPER=18\r\nSMS 406aa0c2 50701F46EEB21328   Super Kick Off/COUNTRY=EU,BR/PRODUCT_NO=27017-50\r\nSMS 10dbbef4 30332F1FFBCB8405   Super Kick Off [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=EU/PRODUCT_NO=2415\r\nSMS 6f9ac98f 8F53B08718544338   Superman - The Man of Steel/COUNTRY=EU,BR/PRODUCT_NO=MK-27050-50,027190\r\nSMS 55bf81a0 59B3C79CC4A7DE48   Super Monaco GP [v0]/COUNTRY=EU,BR/PRODUCT_NO=7043,025310\r\nSMS 3ef12baa 848ACF83D5A4DE49   Super Monaco GP [v1]/COUNTRY=US/PRODUCT_NO=7043\r\nSMS a1d6d963 CA2E38E7805970A0   Super Monaco GP [Proto 0]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS dd7adbcc C9712D78F61127F3   Super Monaco GP [Proto 1]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 3753cc95 8289CE81D5A4DE4F   Super Monaco GP [Proto 2]/FLAGS=PROTO/COUNTRY=US/COMMENT=Prototype version of the game. Marked \"1990.07.18\". Only 3 header bytes differs from final US release.\r\nSMS e890331d 0EE799CB6D17E43F   Super Monaco GP II (Ayrton Senna's)/COUNTRY=EU,BR,KR/PRODUCT_NO=9011\r\nSMS 660bf6ec D093565FC7E8C376   Super Multi Game - Super 75 in 1/COUNTRY=KR/EMU_MAPPER=18\r\nSMS eb7790de 7A908E975CEC7415   Super Multi Game - Super 125 in 1/COUNTRY=KR/EMU_MAPPER=18\r\nSMS 54f68c2a F34CECBA9A4AAF88   Super Off Road/COUNTRY=EU/PRODUCT_NO=MK-27059-50\r\nSMS ce8d6846 BA46E1977D539F19   Super Off Road [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 53d742db AB2F0B166575FD2E   Super Penguin/COUNTRY=KR/PRODUCT_NO=SI-3131G\r\nSMS 7e0ef8cb 52DA42A9A94927D0   Super Racing/COUNTRY=JP/PRODUCT_NO=G-1357/COMMENT=This game optionally support the Paddle Control.\r\nSMS e0b1aff8 55607A442D170643   Super Smash T.V./COUNTRY=EU/PRODUCT_NO=27044-50/COMMENT=Official game material mentions \"Super Smash T.V.\", but the game shows a \"Smash T.V.\" title screen.\r\nSMS 1d6244ee A2F23281E94DB5CE   Super Space Invaders/COUNTRY=EU/PRODUCT_NO=MK 27023-50\r\nSMS 914514e3 F799F9C458560EF7   Super Tennis/COUNTRY=US,EU,DE/PRODUCT_NO=4007,4507,41010\r\nSMS bd1cc7df 230C5D2B35293BB0   Super Tetris/COMMENT=Unlicensed Tetris clone.\r\nSMS b1da6a30 D805179D29845F63   Super Wonder Boy Monster World (Super Wonder Boy Monster Land)/COUNTRY=JP/PRODUCT_NO=G-1346/COMMENT=Japanese version of \"Wonder Boy in Monster Land\". When ran on an export Master System, the game title screen says \"Super Wonder Boy Monster Land\". This later title is found on certain US cartridges' label, but never shown in-game elsewhere than in this version.\r\nSMS 93ca8152 BC18F17F4F471214   T2: The Arcade Game/COUNTRY=EU/PRODUCT_NO=MK-27061-50\r\nSMS 85cfc9c9 3818020380F03704   Taito Chase H.Q./COUNTRY=EU/EMU_TVTYPE=PAL/PRODUCT_NO=7038  ; [EDITOR NOTE] This game is internally a mess: almost duplicated pages, unused data, etc. I think it could work with only 128 KB but the SMS checksum was computed for 256 KB. The ROM is the exact content you get reading from an original cartridge. Reading from upper pages (256 KB+) return 0xFF so the ROM is really 256 KB.\r\nSMS 1cdcf415 B68CF0B91B594859   Taito Chase H.Q. [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 7bb81e3d 508B3E02BE909106   Taito Chase H.Q. [SMS-GG]/COUNTRY=JP/FLAGS=SMSGG_MODE/PRODUCT_NO=T-11017\r\nSMS c8381def 5EDD7209C4516FC6   Taito Chase H.Q. [SMS-GG]/NAME_US=Chase H.Q./COUNTRY=US/FLAGS=SMSGG_MODE/PRODUCT_NO=T-11018\r\nSMS 42d911f3 6D2A92A3208C4D3B   Tank Battalion/COUNTRY=KR\r\nSMS 11ce074c C37CA576419924A8   Taz in Escape from Mars/COUNTRY=BR/PRODUCT_NO=028620/COMMENT=This is a port from the Game Gear version.\r\nSMS 7cc3e837 3781F099BC8BE494   Taz-Mania/COUNTRY=EU,BR/PRODUCT_NO=7111,027150\r\nSMS 1b312e04 EFF0F33BC64A548F   Taz-Mania [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 5a1c3dde 3AABE45F522F0156   Tecmo World Cup '93/COUNTRY=EU/PRODUCT_NO=7106\r\nSMS 96e75f48 155B04B46BAEE2DD   Tecmo World Cup '93 [Proto]/COUNTRY=EU/FLAGS=PROTO/COMMENT=Prototype version of the game. Title screen says \"Tecmo World Cup '92\".\r\nSMS 2728faa3 C57A94919D619509   Teddy Boy/COUNTRY=US,EU,BR,IT/PRODUCT_NO=4003,4503,021060/COMMENT=Export version of \"Teddy Boy Blues\".\r\nSMS 316727dd BBE8D843FF8FF6BE   Teddy Boy Blues/COUNTRY=JP/PRODUCT_NO=C-501/COMMENT=Japanese version of \"Teddy Boy\".\r\nSMS d7508041 D7FED948FE980371   Teddy Boy Blues [EP-MyCard]/COUNTRY=JP/PRODUCT_NO=C-501/FLAGS=PROTO/COMMENT=Prototype cartridge containing data to be used by the unreleased EP-MyCard system. Located after the regular game data, additionnal data includes the game name (in japanese katakana), product number and duplication price of 1800 yens.\r\nSMS 1a390b93 98916E9343CD4A7C   Tennis Ace/NAME_BR=Super Tennis/COUNTRY=EU,BR/PRODUCT_NO=7028\r\nSMS 8132ab2c CEEB86B43819EAD2   Tensai Bakabon/COUNTRY=JP/PRODUCT_NO=G-1355\r\nSMS edc5c012 00F96F49ABD7E3EA   Terminator, The/COUNTRY=EU/PRODUCT_NO=MK-27025-50\r\nSMS e3d5ce9a 20C1B4873A128612   Terminator, The/COUNTRY=BR/PRODUCT_NO=027320\r\nSMS ac56104f 798ED2D04A190EE6   Terminator 2: Judgment Day/COUNTRY=EU/PRODUCT_NO=MK 27052-50\r\nSMS 8640e7e8 F59737442BCF7986   Three Dragon Story, The/COUNTRY=KR\r\nSMS ae920e4b 71B0240AD8312583   Thunder Blade/COUNTRY=US,EU,BR/PRODUCT_NO=7011\r\nSMS c0ce19b1 1FE27772C146E52A   Thunder Blade/COUNTRY=JP/PRODUCT_NO=G-1360\r\nSMS bab9533b 357C1104D326FF42   Thunder Blade [Proto]/COUNTRY=JP/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 98cf1254 394D74D61F0665A6   Thunder Blade [HTH] [SMS-GG] (TW)/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-03/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 51bd14be C69000F39D02997F   Time Soldiers/COUNTRY=US,EU,BR/PRODUCT_NO=7024\r\nSMS bf7b7285 2CAB2FD57FA3D42F   Tom and Jerry: The Movie/COUNTRY=EU,BR,KR/PRODUCT_NO=7070,026150,GB2022JG\r\nSMS 0c2fc2de CF198685CF743C8E   Tom and Jerry: The Movie [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 4f8d75ec A896A3A30327D280   Toto World 3/COUNTRY=KR/PRODUCT_NO=DS-G301\r\nSMS 4bc42857 DA63DA8BEB8E7C69   TransBot/NAME_BR=Nuclear Creature/COUNTRY=US,EU,DE,IT,BR/PRODUCT_NO=4004,4502,41003,021050/COMMENT=Export version of \"Astro Flash\".\r\nSMS 58b99750 BAFA10720389211D   TransBot [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS e5374022 8C3364BCB756F81C   Trivial Pursuit - Genus Edition/COUNTRY=EU/PRODUCT_NO=MK 29008-50\r\nSMS 178801d2 DE0E85F3BB491B7D   Ttoriui Moheom/COUNTRY=KR/PRODUCT_NO=G-37/COMMENT=Hacked Korean version of \"Seishun Scandal\" \\/ \"My Hero\".\r\nSMS 22cca9bb 0E91C33709612BD2   Turma da Mônica em - O Resgate/COUNTRY=BR/PRODUCT_NO=026260/COMMENT=Brazilian hacked version of \"Wonder Boy III: The Dragon's Trap\" \\/ \"Monster World II\", released by Tec Toy.\r\nSMS e1714a88 830DC65B43CD65DA   TV Colosso (As Aventuras da)/COUNTRY=BR/PRODUCT_NO=028650/COMMENT=Brazilian hacked version of \"Astérix and the Secret Mission\", released by Tec Toy. Based on local cartoon series.\r\nSMS b52d60c8 3EEC41D938FA3456   Ultima IV/COUNTRY=EU,BR/PRODUCT_NO=9501\r\nSMS de9f8517 A9FD5B95131658E9   Ultima IV [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 15668ca4 7638A4C78062F114   Ultimate Soccer/COUNTRY=EU,BR/PRODUCT_NO=7119,024440\r\nSMS dfb0b161 826B0C3B91EAF65B   Vigilante/COUNTRY=US,EU,BR/PRODUCT_NO=7023\r\nSMS 57f1545b 63CE90266CDA3B98   Virtua Fighter Animation/COUNTRY=BR/PRODUCT_NO=030020/COMMENT=This is a port from the Game Gear version.\r\nSMS 3d55759b 2893A79D37A62301   Walter Payton Football/COUNTRY=US/PRODUCT_NO=7020/COMMENT=US version of \"American Pro Football\".\r\nSMS 5359762d 1E9957BF6F2A4B4F   Wanted/COUNTRY=US,EU,BR/PRODUCT_NO=5118/EMU_INPUTS=LIGHTPHASER\r\nSMS b14b6195 C1F11922544DA4CE   Wimbledon [v0] [Game Box Série Esportes]/COUNTRY=BR,PT/PRODUCT_NO=028560/COMMENT=Part of \"Game Box Série Esportes\" compilation.\r\nSMS 912d92af 6002C9391330D782   Wimbledon [v1]/COUNTRY=EU/PRODUCT_NO=7100\r\nSMS 7f3afe58 F3781A7463B39160   Wimbledon II/NAME_BR=Wimbledon/COUNTRY=EU,BR/PRODUCT_NO=7115,024390\r\nSMS a20290b6 B24204297A3B42E8   Winter Olympics/COUNTRY=EU,FR,DE/PRODUCT_NO=29015-50,29015-09,29015-18\r\nSMS 2fec2b4a F624C8EE78DBDD00   Winter Olympics/COUNTRY=BR/PRODUCT_NO=028350\r\nSMS 428b1e7c 3086E74963CE9E4B   Where in the World is Carmen Sandiego?/COUNTRY=US/PRODUCT_NO=4350\r\nSMS 88aa8ca6 EFC7A06831BB0650   Where in the World is Carmen Sandiego?/COUNTRY=BR/PRODUCT_NO=023450\r\nSMS 1f8efa1d FBDA82A4AA3C34EB   Wolfchild/COUNTRY=EU,BR/PRODUCT_NO=MK-27060-50\r\nSMS e2fcb6f3 A9F764062AFED3FB   Wonder Boy [v0]/NAME_JP=Super Wonder Boy/COUNTRY=JP,IT,KR/PRODUCT_NO=G-1316,5068,GB-1003\r\nSMS 73705c02 AFB122C8D3EE7A7B   Wonder Boy [v1]/COUNTRY=US,EU,BR/PRODUCT_NO=5068/COMMENT=Export version of \"Super Wonder Boy\".\r\nSMS 8cbef0c1 522ECFED1D0DF8A2   Wonder Boy in Monster Land/COUNTRY=US,EU/PRODUCT_NO=7007/COMMENT=Early production batch of the US version was labelled \"Super Wonder Boy Super Monster Land\" on the cartridge, but kept showing the \"Wonder Boy in Monster Land\" title screen.\r\nSMS 8312c429 FEE7F612ED897726   Wonder Boy in Monster Land [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 7d7ce80b 9ECDFDB1438755C8   Wonder Boy in Monster World/COUNTRY=EU,KR/PRODUCT_NO=9012,9012-50,GB4021JG\r\nSMS 81bff9bb 2AC27C1DAA5E640F   Wonder Boy in Monster World [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 679e1676 9C7847B5CB3F875F   Wonder Boy III: The Dragon's Trap/NAME_JP=Monster World II/COUNTRY=US,EU,KR,AU/PRODUCT_NO=7026,GB-2004\r\nSMS 5e7b18c8 24E29B513CCE7B89   Wonder Kid [Proto] [SMS-GG]/FLAGS=SMSGG_MODE,PROTO/COUNTRY=US/COMMENT=Prototype version of the game, based on 'Adventure Kid' available in '4 Pak All Action'/EMU_MAPPER=41\r\nSMS a05258f5 7DA12B7293A88D7D   Wonsiin/COUNTRY=KR/EMU_MAPPER=12\r\nSMS 315917d4 96069693DD5753B4   Woody Pop - Shinjinrui no Block Kuzushi/COUNTRY=JP/PRODUCT_NO=C-519/EMU_COUNTRY=1/EMU_INPUTS=PADDLE\r\nSMS c9dd4e5f 7B26A0ABD55647A2   Woody Pop (Super Arkanoid)/COUNTRY=KR/PRODUCT_NO=G-2101\r\nSMS c9a449b7 29655F8F9FFB0EDC   World Class Leader Board/COUNTRY=EU,BR/PRODUCT_NO=27015-50,025330\r\nSMS 6e1ad6fd 83C0B3E1924F1434   World Cup Italia '90/NAME_BR=Super Futebol II/COUNTRY=EU,BR/PRODUCT_NO=5084,023340\r\nSMS a0cf8b15 805E1AC308DBF36F   World Cup Italia '90 [Demo]/COUNTRY=US/COMMENT=Rolling non-interactive demo to advertise the game.\r\nSMS a6bf8f9e 412EC711CEF9955D   World Cup USA 94/COUNTRY=EU,BR,AU/PRODUCT_NO=29028-50,29028-05,29028-06,29028-09,29028-18,028430\r\nSMS a2a60bc8 036FB34FE9E516A8   World Games/COUNTRY=EU,BR/PRODUCT_NO=5114\r\nSMS 914d3fc4 15E6422DECFDF4B9   World Games [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 4aaad0d6 761980092FA9EA26   World Grand Prix [v0]/COUNTRY=EU,IT,DE/PRODUCT_NO=5080,41006/COMMENT=Export version of \"The Circuit\".\r\nSMS 7b369892 1624A9110762168D   World Grand Prix [v2]/COUNTRY=US,BR,KR/PRODUCT_NO=5080,?,GB-1304/COMMENT=Export version of \"The Circuit\". Also used in Brazilian and Korean version.\r\nSMS b5a9f824 7DB5DA9A1F9C326D   World Grand Prix [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 72112b75 54286C65B89E5409   World Soccer/NAME_US=Great Soccer/NAME_BR=Super Futebol/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1327,5059/COMMENT=This game has multiple name and title screen. It is named \"Great Soccer\" in USA, and is unrelated to the other \"Great Soccer\" game released in Japan and Europe.\r\nSMS 2db21448 E816FF0B158ACF8A   WWF WrestleMania Steel Cage Challenge/COUNTRY=EU,BR/PRODUCT_NO=27054-050,026270\r\nSMS da8e95a9 1C2E45C0C47B0E64   WWF WrestleMania Steel Cage Challenge [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=EU\r\nSMS 5c205ee1 148D13D956C94E06   Xenon 2: Megablast [Image Works]/COUNTRY=EU/PRODUCT_NO=27012-50\r\nSMS ec726c0d 949238322F74AC21   Xenon 2: Megablast [Virgin]/COUNTRY=EU/PRODUCT_NO=27038-50\r\nSMS d47f5c89 F35E8CD9947B42F9   Xenon 2: Megablast [HTH] [SMS-GG]/FLAGS=SMSGG_MODE/COUNTRY=TW/PRODUCT_NO=HG 201-16/COMMENT=Taiwanese HTH release for Game Gear.\r\nSMS 3e1387f6 5817A60154C0D7FF   X-Men: Mojo World/COUNTRY=BR/PRODUCT_NO=028740/COMMENT=This is a port from the Game Gear version.\r\nSMS 565c799f 3E57DDC184F4D481   Xyzolog/COUNTRY=KR/PRODUCT_NO=G-91\r\nSMS 32759751 13C43FBEE6B25341   Ys/COUNTRY=JP/PRODUCT_NO=G-1370/EMU_VDP=315-5124/COMMENT=Japanese version of \"Y's: The Vanished Omens\".\r\nSMS b33e2827 6C4C3C65EF39ADD2   Y's: The Vanished Omens/NAME_BR=Y's/COUNTRY=US,EU,BR/PRODUCT_NO=7501/COMMENT=Export version of \"Ys\".\r\nSMS e8b82066 06806D7C60FB9C9A   Y's: The Vanished Omens [Demo]/COUNTRY=US/FLAGS=PROTO//EMU_VDP=315-5124/COMMENT=Rolling non-interactive demo to advertise the game. Text in Japanese although this is an US demo cartridge.\r\nSMS a3ef13cb 73E4CCD0CC1A69BE   Zaxxon 3-D/NAME_JP=Zaxxon 3D/COUNTRY=JP,US,EU,BR/EMU_3D/PRODUCT_NO=G-1336,8002/COMMENT=The 3-D effect can be removed by pressing Pause on title screen. It works only on non-Japanese systems.\r\nSMS bba74147 2D689EA985B828BF   Zaxxon 3-D [Proto]/NAME_JP=Zaxxon 3D [Proto]/FLAGS=PROTO/EMU_3D/COMMENT=Unfinished prototype version of the game.\r\nSMS 7cd51467 488D49FF0599CE77   Zemina 4-in-1 (Q-Bert, Sports 3, Gulkave, Pooyan)/COUNTRY=KR/EMU_MAPPER=23\r\nSMS e6c9c046 F4E9FC49C3C374E4   Zemina Best 25/COUNTRY=KR/EMU_MAPPER=40/COMMENT=This is the second 512KB of Zemina Best 88. Evidence of a physical release exist.\r\nSMS d8169fe2 BF9411BD7824093A   Zemina Best 39/COUNTRY=KR/EMU_MAPPER=40/COMMENT=This is the first 512KB of Zemina Best 88. No evidence yet of a physical release.\r\nSMS 3c339d9e B37D0D063BE77D1E   Zemina Best 88/COUNTRY=KR/EMU_MAPPER=40\r\nSMS 60c19645 39A919D7DA6933B8   Zillion [v0]/NAME_JP=Akai Koudan Zillion/COUNTRY=JP,EU/PRODUCT_NO=G-1325,5075\r\nSMS 5718762c 88E69FBAA2DA4974   Zillion [v1]/COUNTRY=US/PRODUCT_NO=5075     ; [EDITOR NOTE] Country listing for all 3 versions are based on what we found so far. It's probable that v1 and v2 were released in both US and EU.\r\nSMS 7ba54510 8AE29FB6A2DC4B76   Zillion [v2]/COUNTRY=EU/PRODUCT_NO=5075\r\nSMS 2f2e3bc9 FE36CB6E6BC5ED76   Zillion II: The Tri Formation/NAME_JP=Tri Formation/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-1344,5105\r\nSMS 5b1cf392 59089ED697AC5494   Zillion II: The Tri Formation [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nSMS 9d9d0a5f F8C690D818C64DAF   Zool/COUNTRY=EU/PRODUCT_NO=27075-50\r\n\r\n; BIOS images\r\nSMS cf4a09ea E7605A0A2D3939B6   Alex Kidd in Miracle World [BIOS]/FLAGS=BIOS\r\nSMS 9c5bad91 1CBCFDC2F498BB22   Alex Kidd in Miracle World [BIOS]/FLAGS=BIOS/COUNTRY=KR\r\nSMS 8edf7ac6 394EDEF5E1094A72   Hang On [BIOS]/FLAGS=BIOS\r\nSMS 91e93385 E48EA39C2A04D150   Hang On \\/ Safari Hunt [BIOS]/FLAGS=BIOS\r\nSMS e79bb689 0BCFEBA4D00C704B   Missile Defense 3-D [BIOS]/FLAGS=BIOS/EMU_INPUTS=LIGHTPHASER/EMU_3D\r\nSMS 81c3476b 21346172A6AAF296   Sonic The Hedgehog [BIOS]/FLAGS=BIOS\r\nSMS 0072ed54 8FA45DBECEBC899F   SMS (v1.3) [BIOS]/COUNTRY=US,EU/FLAGS=BIOS\r\nSMS b3d854f8 A5AA61B4D1BA8C85   SMS (v2.0) [BIOS]/COUNTRY=EU/FLAGS=BIOS\r\nSMS 48d44a13 312C856A6F60479E   SMS Japanese (v2.1) [BIOS]/COUNTRY=JP/FLAGS=BIOS\r\nSMS 1a15dfcc AEA4E4E75C18620D   SMS Prototype (M404) [BIOS]/FLAGS=BIOS\r\nSMS 72bec693 59E14606333368AC   SMS Prototype (v1.0) [BIOS]/FLAGS=BIOS\r\nSMS ee2c29ba D96A4E58E20A9794   SMS Store Display Unit [BIOS]/EMU_MAPPER=10/COUNTRY=US/FLAGS=BIOS/COMMENT=This is not properly emulated.\r\nSMS 90bfd088 2A26B6AA93E2F7E4   Super Magic Drive (v3.0) [BIOS]/FLAGS=BIOS/COMMENT=This is not properly emulated.\r\nSMS e08173ba 11D194A8DEFE0402   Super Magic Drive (v3.1g) [BIOS]/FLAGS=BIOS/COMMENT=This is not properly emulated.\r\nSMS 07402a75 804BCF87BAFFE145   Super Magic Drive (v4.1a) [BIOS]/FLAGS=BIOS/COMMENT=This is not properly emulated.\r\n\r\n; Bad dumps\r\nSMS 8b4ca9e4 8CFC7A4DECE2BC27   Air Rescue/FLAGS=BAD\r\nSMS 6a9eaef7 6A00D45444FC0E20   Astro Warrior \\/ Pit Pot/FLAGS=BAD/COMMENT=Overdump with 1 bad byte.\r\nSMS b4dfb825 D8A33ACA58CD77E5   Bank Panic/FLAGS=BAD/COMMENT=2 bad bytes (incorrect header).\r\nSMS e239ed95 AF4F56F9D7628FEB   Casino Games/FLAGS=BAD/COMMENT=45 bad bytes.\r\nSMS f964f356 CA4954F3D05891ED   Casino Games/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 6203efbb 285215E561B24732   Castle of Illusion/FLAGS=BAD\r\nSMS 5ef8dbda D080CE7C20815F66   Dead Angle/FLAGS=BAD/COMMENT=4 bad bytes.\r\nSMS e730bb27 3488F258EC375B7C   Double Dragon/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 3b79d63e E857D8017B03EA80   Double Dragon/FLAGS=BAD\r\nSMS 6cc2e967 090BDB10B329FD28   Double Dragon/FLAGS=BAD\r\nSMS 7c2e6c5a 8060A048D88038A8   Ghost House/FLAGS=BAD/COMMENT=Overdump with bad bytes.\r\nSMS 1eec7abc 07A18B1093D71B38   Golden Axe/FLAGS=BAD/COMMENT=2 bad bytes.\r\nSMS c5083000 9F54DCE0F03F170B   Hang On \\/ Safari Hunt/COUNTRY=US,KR/FLAGS=BAD/EMU_INPUTS=LIGHTPHASER/COMMENT=This dump has the first 16 Kb duplicated on an unused location of the ROM. Thus the game is working but checksum is failing.\r\nSMS 2b7f7447 A222B16F114CDAE5   James Bond 007 - The Duel/COUNTRY=BR/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS fef68275 0C38C7A1580A24CE   James Pond II - Codename: RoboCod/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS bb351118 97D1E5EB0E6663F1   KLAX/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 68108314 261F3B6965EAC701   Kujakuou/FLAGS=BAD/COUNTRY=JP/COMMENT=1 bad byte.\r\nSMS d70bbd06 B32F41555F15C84C   Out Run/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 94fee07b EFA3373E2142D1C5   Marble Madness/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS fac09af4 BDDCD79E4A141381   Mônica no Castelo do Dragão/FLAGS=BAD/COUNTRY=BR/COMMENT=Hacked version of Wonder Boy in Monster Land by Tec Toy. 58 bad bytes.\r\nSMS 9fb7d63b 690DDE11E39C7CA0   Ninja, The/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 283712a9 97682219F73E573A   Pit-Fighter/COUNTRY=EU/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 4902b7a2 A88B7C7AF6466F2C   R.C. Grand Prix [SMS-GG]/COUNTRY=US/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS 599901bb 905391ED1B463806   Street Fighter II'/COUNTRY=BR/FLAGS=BAD/COMMENT=5 bad bytes.\r\nSMS 87aabdfe 8F5391ED1B463906   Street Fighter II'/COUNTRY=BR/FLAGS=BAD/COMMENT=4 bad bytes.\r\nSMS 6f2cf48a C8782C54E741D246   Streets of Rage/COUNTRY=EU,BR/FLAGS=BAD/COMMENT=2 bad bytes.\r\nSMS 10b1c008 F07A46299069111D   Super Boy 4/COUNTRY=KR/FLAGS=BAD/COMMENT=2 bad bytes.\r\nSMS 12706a8a EF7A46299169111D   Super Boy 4/COUNTRY=KR/FLAGS=BAD/COMMENT=1 bad byte.\r\nSMS ab260100 0BDC8EDC154D82CB   World Soccer/COUNTRY=JP,US,EU,BR/FLAGS=BAD\r\nSMS cb42bd33 C95F6AD329B98B2E   WWF WrestleMania Steel Cage Challenge [SMS-GG]/FLAGS=BAD,SMSGG_MODE/COUNTRY=EU/COMMENT=First 64 Kb from the correct ROM.\r\n\r\n; Hacks\r\nSMS 32da4b0d 606D1F7886714065   Argos no Juujiken [Hack]/COUNTRY=JP/FLAGS=HACK/PRODUCT_NO=S-001/COMMENT=Also known in the west as \"Rygar\". Hack of the game. Some original game data was overwritten. MarkIII screen and SALIO logo on title screen were removed.\r\nSMS 0e21e6cf 2C1F1C2AD72C87E5   Astro Flash [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game, found in unlicensed Game Gear compilations. Some original game data was overwritten, and code was added.\r\nSMS 5877b10d AAD6EA9514AE82BD   Castle of Illusion [SMS-GG] [Hack]/FLAGS=SMSGG_MODE,HACK/COUNTRY=JP\r\nSMS 5d08e823 BD3E8E6BB4B48C18   Fushigi no Oshiro Pit Pot [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some original game data was overwritten, and code was added.\r\nSMS dabcc054 6A8138E7EE6B9409   Ghost House [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some original game data was overwritten.\r\nSMS c1e699db 9B82007132F58AC1   Great Baseball [JP] [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some original game data was overwritten.\r\nSMS 656d1a3e 78639E5DF49500A1   Hokuto no Ken [Hack]/COUNTRY=TW/PRODUCT_NO=G-1303/COMMENT=Hack of the game, part of a Sega header was forged whereas the original doesn't have it.\r\nSMS 87b9ecb8 ACFDD61911549271   Satellite 7 [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some unused game data was overwritten.\r\nSMS bcd91d78 4F1F78F6C14326FA   Seishun Scandal [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some original game data was overwritten.\r\nSMS a71bc542 410BA7B1518CEF90   Spy vs Spy [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some original game data was overwritten.\r\nSMS 44fbe8f6 1995410AC093A113   Taito Chase H.Q. [SMS-GG] [Hack]/FLAGS=HACK,SMSGG_MODE/COUNTRY=JP\r\nSMS 18086b70 69207F0C7E233219   Taito Chase H.Q. [SMS-GG] [Hack]/FLAGS=BAD,HACK,SMSGG_MODE/COUNTRY=JP/COMMENT=2x Overdump. The first half was hacked.\r\nSMS 9dfa67ee B4EAE0440091F6B7   Teddy Boy Blues [Hack]/COUNTRY=JP/FLAGS=HACK/COMMENT=Hack of the game. Some unused game data was overwritten.\r\nSMS 7522cf0a 5F37D2F71D0F086D   Wonder Boy in Monster Land [Hack]/FLAGS=HACK/COUNTRY=US,EU/COMMENT=This hack does two things: force the game to run in Japanese mode (with an harder difficulty level), and allows to Pause the game by pressing LEFT+RIGHT+Button 2 on joypad 1 (a combination that cannot be done on a normal SMS joypad).\r\n\r\n; Homebrews\r\nSMS ca270f40 6DE7159995D9820E   AntiISDA Warrior [v1.00]/FLAGS=HOMEBREW/VERSION=1.00/AUTHORS=Ventzislav Tzvetkov, Maze\\/Apathy/COMMENT=Buggy.\r\nSMS 7408ef2f 6BF3098A9DD38B14   AntiISDA Warrior [v1.01]/FLAGS=HOMEBREW/VERSION=1.01/AUTHORS=Ventzislav Tzvetkov, Maze\\/Apathy/COMMENT=A bit less buggy than version 1.00.\r\nSMS b3e5986e 57EB138F95E3980C   AntiISDA Warrior [v1.02]/FLAGS=HOMEBREW/VERSION=1.02/AUTHORS=Ventzislav Tzvetkov, Maze\\/Apathy\r\nSMS 2734a9b4 79DBBE8D02C64D4C   Blockhead/FLAGS=HOMEBREW/AUTHORS=proppy & tet/COMMENT=4K game, released for 2004 MiniGame Compo.\r\nSMS 1d43a351 8B4F3D6114DE1086   Bock's Birthday 2002/FLAGS=HOMEBREW/AUTHORS=Maxim\r\nSMS c07cb738 D489232826DFDA79   Bock's Birthday 2003/FLAGS=HOMEBREW/AUTHORS=Maxim\r\nSMS 43600bb1 038591ABC985F9F5   Copyright Violation/FLAGS=HOMEBREW/AUTHORS=Heliophobe\r\nSMS bfee193c 5FED15D30F837BBF   Code 38 - Volume I [French\\/NoPSG]/FLAGS=HOMEBREW/AUTHORS=Furrtek\\/L.i.N./COMMENT=French version. No music.\r\nSMS 0299bda4 8EEACEC09980CF12   Crappy/FLAGS=HOMEBREW/AUTHORS=Memetic\r\nSMS ff67359b BAADC12E0B5E0041   DataStorm/FLAGS=HOMEBREW/EMU_MAPPER=0\r\nSMS 7cc2a20b 0929A17E9208977E   DCEvolution.net Intro/FLAGS=HOMEBREW/VERSION=1.00/AUTHORS=Ventzislav Tzvetkov, Maze\\/Apathy/COMMENT=Promotional intro for the DCEvolution.net SMS\\/GG\\/SG-1000 project.\r\nSMS a95013d3 B788F3842E5B8938   Fri For Fransk! [v1.02]/FLAGS=HOMEBREW/VERSION=1.02/AUTHORS=Marc Klemp\r\nSMS 07c39ba4 20C7DA1FAAE0375F   Happy Looser/FLAGS=HOMEBREW/AUTHORS=Zoop\r\nSMS 922954c6 19C6E01FA9E23760   Happy Looser/FLAGS=BAD,HOMEBREW/AUTHORS=Zoop/COMMENT=Corrupted ROM header. This ROM was distributed in the sources package.\r\nSMS ed169d59 A9A8F900277B8C88   Headbreak for a Scroller/FLAGS=HOMEBREW/AUTHORS=Furrtek\\/L.i.N.\r\nSMS 6eaead07 A05F0BE71505FEF7   Page Frame Register Detect [v0.01]/FLAGS=HOMEBREW/VERSION=0.01/AUTHORS=Eric R. Quinn/EMU_MAPPER=0\r\nSMS ad0ff4f1 CDABEB55AD267EF7   Page Frame Register Detect [v1.00]/FLAGS=HOMEBREW/VERSION=1.00/AUTHORS=Eric R. Quinn/EMU_MAPPER=0\r\nSMS 1f30cb32 ADD696C40348EEEA   Page Frame Register Detect [v2.00]/FLAGS=HOMEBREW/VERSION=2.00/AUTHORS=Eric R. Quinn/EMU_MAPPER=0\r\nSMS f61874c9 D91BB1A6725E02E3   Robbyie/FLAGS=HOMEBREW/VERSION=0.99/AUTHORS=Ventzislav Tzvetkov/COMMENT=1K game, released for 2004 MiniGame Compo.\r\nSMS 7cbd4432 7BC5F85A1C32DF41   SALY/FLAGS=HOMEBREW/VERSION=1.00/AUTHORS=Marc Klemp\r\nSMS 49790a5a 6CD4D4285F37A589   Sega Mark III Port Test/FLAGS=HOMEBREW/VERSION=0.1/AUTHORS=Enri (T.H)\r\nSMS 5f1120c8 389C255B45409790   Sega Mark III BG Test/FLAGS=HOMEBREW/VERSION=0.01/AUTHORS=Enri (T.H)\r\nSMS 297efb87 F6CA6BFD36AE4CA8   SMSPower 7 [v1.00]/FLAGS=HOMEBREW/VERSION=1.00/AUTHORS=Nick Warren (Heliophobe)/COMMENT=SMS Power 7th Anniversary Demo.\r\nSMS 72506a85 7389804C41C573BF   SMSPower 7 [v1.03]/FLAGS=HOMEBREW/VERSION=1.03/AUTHORS=Nick Warren (Heliophobe)/COMMENT=SMS Power 7th Anniversary Demo. ; SDSC tag says version 1.02 but it is 1.03, really.\r\nSMS a3e97d04 89D423D3A6865130   Tetracycline [v1]/FLAGS=HOMEBREW/VERSION=1/AUTHORS=Heliophobe\r\nSMS 983e17e4 D8DB27E4A88354C3   Tetracycline [v2]/FLAGS=HOMEBREW/VERSION=2/AUTHORS=Heliophobe\r\nSMS fd603aea A19CB1789551FCB8   Tetracycline [v3]/FLAGS=HOMEBREW/VERSION=3/AUTHORS=Heliophobe\r\nSMS a0bf829b 2D816184804F9806   Tetracycline [v4]/FLAGS=HOMEBREW/VERSION=4/AUTHORS=Heliophobe\r\nSMS 046ebc1b 795067F611200B9E   Unité Centrale de Huit Bits/FLAGS=HOMEBREW/AUTHORS=Comic Bakery/COMMENT=SMS Demo for Mainframe03.\r\nSMS ad300bd9 8147C138C1003E40   VIK 01/FLAGS=HOMEBREW/AUTHORS=L.i.N.\r\nSMS a463ddfa 1DE693E241DE4D1C   Zoom Effect #1/FLAGS=HOMEBREW/AUTHORS=Charles MacDonald/COMMENT=Doesn't run properly in MEKA.\r\n\r\n; Translations\r\nSMS 7338d04e 6399700AAAC09F81   Air Rescue/FLAGS=TRANS/TRANS=PT/AUTHORS=Emutrans\r\nSMS 7337abb7 8A2B7047E7DBAE24   Air Rescue/FLAGS=BAD,TRANS/TRANS=PT/AUTHORS=Emutrans\r\nSMS 9a1ecfec 2E30322805F4420D   Ghost House/FLAGS=TRANS/COUNTRY=US,EU/TRANS=BR/AUTHORS=Leo\r\nSMS 11e19fb1 C24C078D64F2E325   Golvellius - Valley of Doom/FLAGS=TRANS/COUNTRY=US,EU/TRANS=FR/VERSION=1.3/AUTHORS=floflo\r\nSMS 359141ef 848E8CA2DD44E9B6   Golvellius - Valley of Doom/FLAGS=TRANS/COUNTRY=US,EU/TRANS=DE/AUTHORS=Star-trans\r\nSMS 00196eba F1227B8A149789B4   Golvellius - Valley of Doom/FLAGS=TRANS/COUNTRY=US,EU/TRANS=BR/AUTHORS=Albert Viudes Dick.\r\nSMS 0643620e 078F6E3FDB3CDFC7   Ninja Gaiden/FLAGS=TRANS/TRANS=FR/AUTHORS=?/COMMENT=Translation based on the prototype version.\r\nSMS 41e5b485 6B11424AD07AE6C8   Ninja Gaiden/FLAGS=TRANS/TRANS=FR/AUTHORS=Terminus/COMMENT=Translation based on the prototype version.\r\nSMS 317f14da 642D4E5E1BB23ABC   Ninja Gaiden/FLAGS=TRANS/TRANS=DE/VERSION=1.00/AUTHORS=Star-trans/COMMENT=Translation based on the prototype version.\r\n\r\n;-----------------------------------------------------------------------------\r\n; DATA - SEGA GAME GEAR (GG)\r\n;-----------------------------------------------------------------------------\r\n\r\nGG  f85a8ce8 5DB92D172BF43C4B   5 in One Fun Pak/COUNTRY=US/PRODUCT_NO=T-125028\r\nGG  1d17d2a0 A5D21350B842022A   Aah! Harimanada/COUNTRY=JP/PRODUCT_NO=G-3327\r\nGG  1d01f999 EE39E44E85E0C77B   Addams Family, The/COUNTRY=US,EU,JP/PRODUCT_NO=T-81188,T-81188-50,T-81087\r\nGG  bb4f23ff E66F317D87443101   Adventures of Batman & Robin, The/COUNTRY=US,EU,BR/PRODUCT_NO=2552,2552-50,077240\r\nGG  3e549b7a D0CFB9E6942DCC35   Aerial Assault [v0]/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-3219,2320,015820\r\nGG  04fe6dde CFD0B9E6942DCC35   Aerial Assault [v1]/COUNTRY=JP/PRODUCT_NO=G-3219    ; [EDITOR-NOTE] Unconfirmed in other countries\r\nGG  7a41c1dc B9E076A223923E5C   Aladdin (Disney's)/COUNTRY=US,EU,BR/PRODUCT_NO=2525,077120\r\nGG  770e95e1 0FAC122A0F7FFA81   Aladdin (Disney's)/COUNTRY=JP/PRODUCT_NO=G-3336\r\nGG  11a68c08 73C0F3CC1F5A1D78   Alien 3/COUNTRY=US,EU/PRODUCT_NO=T-81048,T-81048-50\r\nGG  06f6eebb 8169175BF3BC33C2   Alien 3/COUNTRY=JP/PRODUCT_NO=T-81047\r\nGG  ffe4ed47 8E692D2511E6F5CB   Alien Syndrome/COUNTRY=JP/PRODUCT_NO=T-44037\r\nGG  bb5e10e0 B773122D1BECF0A0   Alien Syndrome/COUNTRY=US,EU/PRODUCT_NO=2324\r\nGG  46c9fa3e 3F02FDFC275C2F14   Andre Agassi Tennis/COUNTRY=US/PRODUCT_NO=T-101018\r\nGG  f167028e C1ED6D522A2A8EB1   Andre Agassi Tennis [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  3deca813 8E92A6014E129049   Arcade Classics/COUNTRY=US/PRODUCT_NO=2330\r\nGG  f0204191 9A1D6EB1E8A2AAF6   Arch Rivals/COUNTRY=US/PRODUCT_NO=T-81118\r\nGG  7cb3facf 3556E4BEA15709D2   Arena - Maze of Death/NAME_EU=Arena/COUNTRY=US,EU/PRODUCT_NO=2565,2565-50\r\nGG  97e3a18c F70090C4366C52C1   Ariel - The Little Mermaid (Disney's)/COUNTRY=US,EU,BR/PRODUCT_NO=2411,075260\r\nGG  35fa3f68 EDE3ACDDC72A476F   Arliel - Crystal Densetsu/COUNTRY=JP/PRODUCT_NO=G-3403/COMMENT=Japanese version of \"Crystal Warriors\".\r\nGG  78208b40 A662E4EF17F3CC4F   Astérix and the Great Rescue/COUNTRY=US,BR/PRODUCT_NO=2520,077210\r\nGG  328c5cc8 0676B41642F43153   Astérix and the Great Rescue/COUNTRY=EU/PRODUCT_NO=2520\r\nGG  c01a8051 4EC17BDFA523F1DE   Astérix and the Secret Mission/COUNTRY=EU/PRODUCT_NO=2513\r\nGG  dfcf555f 5FA88D0C551D33BB   Ax Battler - A Legend of Golden Axe [v1.5]/NAME_JP=Ax Battler - Golden Axe Densetsu/COUNTRY=JP/PRODUCT_NO=G-3304\r\nGG  3435ab54 20D68E092FC9A0DB   Ax Battler - A Legend of Golden Axe [v2.0] [Proto]/COUNTRY=US,EU/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  663bcf8a C75A6F968FFFD973   Ax Battler - A Legend of Golden Axe [v2.4]/NAME_BR=Golden Axe,COUNTRY=US,EU,BR/PRODUCT_NO=2405,012100\r\nGG  8d8bfdc4 1C884BD0A4242752   Baku Baku/COUNTRY=US/PRODUCT_NO=2451/COMMENT=Title screen says \"Baku Baku Animal\".\r\nGG  10ac9374 DF6C0BFA8275ECCD   Baku Baku/COUNTRY=EU/PRODUCT_NO=2451-50/COMMENT=Title screen says \"Baku Baku Animal\".\r\nGG  7174b802 72E0E91D3A450128   Baku Baku Animal - Sekai Shiikugakari Senshu-ken/COUNTRY=JP/PRODUCT_NO=G-3378\r\nGG  03a0ce9e C53AA373B2CC521B   Barbie Super Model [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  ffa447a9 2949C80F6E63FBEB   Bartman Meets Radioactive Man (The Simpsons)/COUNTRY=US/PRODUCT_NO=?\r\nGG  c0009274 2D9E0A3FD48CA3E9   Bart vs. The Space Mutants (The Simpsons)/COUNTRY=US,EU/PRODUCT_NO=T-81018,T-81018-50\r\nGG  da7bd5c7 EC249DDDD77540EA   Bart vs. The World (The Simpsons)/NAME_JP=Bart World/COUNTRY=JP,US,EU,BR/PRODUCT_NO=T-81077,T-81098,075410\r\nGG  618b19e2 AB897446BC1570D1   Batman Forever/COUNTRY=US,EU,JP/PRODUCT_NO=T-81268,T-81268-50,T-81187\r\nGG  7ac4a3ca 516CF5541BA9E056   Batman Returns/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-3314,2416,2416-50,015590\r\nGG  16448209 C201ABFADA677FD8   Batter Up/COUNTRY=US/PRODUCT_NO=T-14028/COMMENT=Export version of \"Gear Stadium\".\r\nGG  e9987511 82E53FF69611EBD2   Battleship - The classic naval combat game/COUNTRY=US/PRODUCT_NO=T-87018\r\nGG  cb3cd075 EA08216FFAAA5E7C   Battletoads/COUNTRY=JP,EU/PRODUCT_NO=G-3311,2436\r\nGG  817cc0ca EC062170FAAA5D7C   Battletoads/COUNTRY=US/PRODUCT_NO=T-97018\r\nGG  a6bf865e 23BF4FE1E01DC42D   Beavis and Butt-Head (MTV's)/COUNTRY=US,EU/PRODUCT_NO=T-139018,T-139018-50\r\nGG  3858f14f 3332DEF0ABBF471C   Beavis and Butt-Head (MTV's) [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  a4bb9ffb F7196CDC184FF74A   Berenstain Bears' Camping Adventure, The/COUNTRY=US/PRODUCT_NO=2447\r\nGG  325b1797 5213F712A56DCDB3   Berlin no Kabe - The BerlinWall/COUNTRY=JP/PRODUCT_NO=T-33017\r\nGG  fe7374d2 7C9BF74B57970FAA   Bishoujo Senshi Sailor Moon S/COUNTRY=JP/PRODUCT_NO=T-133017\r\nGG  64d7a694 6A7CA59C13A35AC9   BreakThru! [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  6edd48a6 6E7CA59A13A35AC7   BreakThru! [Proto] [Fixed]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game, manually fixed.\r\nGG  bfceba5f 7239ED165A6A8608   Bonkers Wax Up! (Disney's)/COUNTRY=US,EU/PRODUCT_NO=2536,2536-50\r\nGG  fba338c5 D558C670ED32D2AC   Bubble Bobble/COUNTRY=US/PRODUCT_NO=T-11028\r\nGG  be2dc770 744B94047EA8552E   Bubble Bobble [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  5c34d9cd 0A954147D11708E9   Bugs Bunny in Double Trouble/COUNTRY=US,EU/PRODUCT_NO=2569,7766-50\r\nGG  c90f29ef DCCED394874D1605   Bust-A-Move/COUNTRY=US/PRODUCT_NO=2567\r\nGG  7cb079d0 7545BA4617EBF252   Buster Ball/COUNTRY=JP/PRODUCT_NO=T-53027\r\nGG  a72a1753 AE763A9D3E7084D3   Buster Fight/COUNTRY=JP/PRODUCT_NO=G-3341/COMMENT=Game Gear version of \"Masters of Combat\" on the Master System.\r\nGG  c53b60b8 3377568CE62DE47D   Caesars Palace/COUNTRY=US/PRODUCT_NO=T-70098,1240\r\nGG  f6a697f8 CADE4673E162E27A   Car Licence/COUNTRY=JP/COMMENT=Non-retail Japanese release. The exact story behind this cartridge is yet unknown.\r\nGG  2b732056 C51E34D54AB1C554   Casino FunPak/COUNTRY=US/PRODUCT_NO=T-125048\r\nGG  5675dfdd ABD4AF91D87D8369   Captain America and The Avengers/COUNTRY=US\t\t\t\t; [EDITOR-NOTE] Product no?\r\nGG  dfc7adc8 A6DB92F52896C476   Chakan/COUNTRY=US,EU/PRODUCT_NO=2414\r\nGG  e21d2a88 BA2B2AA1D437E362   Championship Hockey/COUNTRY=EU/PRODUCT_NO=?\r\nGG  4e78fd36 778927EF24927BB9   Cheese Cat-Astrophe - Starring Speedy Gonzales/COUNTRY=US,EU,BR/PRODUCT_NO=2523,2523-50,077160\r\nGG  da811ba6 340FBB84D6F82B85   Chessmaster, The/NAME_BR=Sega Chess/COUNTRY=US,EU,BR/PRODUCT_NO=2317,013520\r\nGG  6b0fcec3 C8E8E57E33BC39C5   Chicago Syndicate/COUNTRY=US,BR/PRODUCT_NO=2535,077260\r\nGG  635bc4f5 DAB3B95BFD82A13F   Chicago Syndicate [Proto] [1995-03-20]/FLAGS=PROTO/COMMENT=Prototype version of the game with an \"Empire Syndicate\" title screen.\r\nGG  c2e8a692 4CFC722EB04E8892   Choplifter III/COUNTRY=US/PRODUCT_NO=T-22038\r\nGG  191b1ed8 D569D43547670605   Chuck Rock/COUNTRY=US,EU,JP,BR/PRODUCT_NO=2430,G-3320,016740\r\nGG  cb3a1d23 C00226EF6E17495B   Chuck Rock [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  3fcc28c9 B6FD24D8906B3422   Chuck Rock II: Son of Chuck/COUNTRY=US/PRODUCT_NO=301086-0161 T-48148\r\nGG  656708bf 65F159C71229103F   Chuck Rock II: Son of Chuck/COUNTRY=EU,BR/PRODUCT_NO=T-115018-50,115018-50,075.450\r\nGG  72981057 233F58409660EF21   CJ Elephant Fugitive/COUNTRY=EU,US/PRODUCT_NO=17014/EMU_MAPPER=3\r\nGG  3ace6335 E043D969D2712632   CJ Elephant Fugitive [Proto]/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of the game.\r\nGG  bf75b153 2F97B4630C0D23E7   Cliffhanger/COUNTRY=US/PRODUCT_NO=T-93038\r\nGG  d228a467 9B49411CCAC8D756   Clutch Hitter/COUNTRY=US/PRODUCT_NO=2311\r\nGG  2c758fc8 775934E6039885F6   Cool Spot/COUNTRY=US/PRODUCT_NO=T-70108\r\nGG  ba0714db AB4672C88FA8A3FB   Cool Spot/COUNTRY=EU/PRODUCT_NO=T-70108-50\r\nGG  f3ca6676 10E74B085532032C   Columns [v0]/COUNTRY=JP/PRODUCT_NO=G-3101\r\nGG  ac37e092 C8F45DEC67DF2095   Columns [v1]/COUNTRY=JP/PRODUCT_NO=G-3101,G-3104\r\nGG  83fa26d9 9FD46CE7B8EE365E   Columns [v2]/NAME_BR=Shapes and Columns/COUNTRY=US,EU,BR/PRODUCT_NO=2201,012070\r\nGG  6caa625b 6D119C88287DCBEE   Cosmic Spacehead/COUNTRY=EU,US/PRODUCT_NO=T-120028-50,T-160013/EMU_MAPPER=3/EMU_TVTYPE=PAL/EMU_SPRITE_FLICKER ; [EDITOR-NOTE] should not be PAL here\r\nGG  03d28eab 6B96D3F3E3A93875   Crayon Shin-chan - Taiketsu! Kantamu Panic!!/COUNTRY=JP/PRODUCT_NO=T-133047\r\nGG  46ad6257 E4707F6AD1B4E658   Crazy Faces [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  529c864e A21AD85B167F6913   Crystal Warriors/COUNTRY=US,EU/PRODUCT_NO=2502/COMMENT=Export version of \"Arliel - Crystal Densetsu\".\r\nGG  6a24e47e C2965F6E8A59A751   Cutthroat Island/COUNTRY=US/PRODUCT_NO=T-81338\r\nGG  6352ef00 B7731FD87342E644   Cutthroat Island [Proto]/COUNTRY=US/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  aae268fc 099CC645306AB402   Daffy Duck in Hollywood/COUNTRY=EU,BR/PRODUCT_NO=2550,077110\r\nGG  696f446d 96AF11854EE526CC   David Robinson's Supreme Court [Demo] [Proto]/FLAGS=PROTO/COMMENT=Prototype demo version of the unreleased game.\r\nGG  5a136d7e C8D6479F8BF46C91   Deep Duck Trouble - Starring Donald Duck (Disney's)/COUNTRY=US,EU,BR/PRODUCT_NO=2514,1205,077.070/COMMENT=Export version of \"Donald Duck no Yottsu no Hihou\".\r\nGG  e2791cc1 02E7288B76458A1F   Defenders of Oasis/COUNTRY=US,EU/PRODUCT_NO=2503/COMMENT=Export version of \"Shadam Crusader ~Harukanaru Oukoku~\".\r\nGG  c674eccc BC784278D69408A0   Defenders of Oasis [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game. Only the first 256 KB half so the game is probably unstable and incomplete.\r\nGG  c2e111ac 10D532DB6BFB198F   Desert Speedtrap - Starring Road Runner and Wile E. Coyote/NAME_BR=Desert Speedtrap/COUNTRY=US,BR/PRODUCT_NO=2442,075400\r\nGG  ec808026 B9DF362895F7017D   Desert Speedtrap - Starring Road Runner and Wile E. Coyote/COUNTRY=EU/PRODUCT_NO=2442\r\nGG  f6c400da AE87403603D0E79B   Desert Strike - Return to the Gulf/COUNTRY=US\r\nGG  3e44eca3 B681482B16BEE89A   Desert Strike/COUNTRY=EU/PRODUCT_NO=T-88068-50\r\nGG  25db174f FED59D64601210AA   Devilish/COUNTRY=JP/PRODUCT_NO=T-28017\r\nGG  d43ac6c5 7DFFB63AF302306F   Devilish/COUNTRY=EU,BR/PRODUCT_NO=2321,015340\r\nGG  c01293b0 A9F32B4C77256DE4   Devilish/COUNTRY=US                                         ; [EDITOR-NOTE] might be a prototype\r\nGG  2306aaf4 47EA8C022D9DA2D5   Dinobasher - Starring Bignose the Caveman [Proto]/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of the unreleased game.\r\nGG  2d98bd87 9A5CD4E692C2A854   Donald Duck no Lucky Dime/COUNTRY=JP/PRODUCT_NO=G-3306/COMMENT=Japanese version of \"Lucky Dime Caper\\, The\".\r\nGG  4457e7c0 FF64CE10F01C7D36   Donald Duck no Yottsu no Hihou/COUNTRY=JP/PRODUCT_NO=G-3332/COMMENT=Japanese version of \"Deep Duck Trouble - Starring Donald Duck (Disney's)\".\r\nGG  87b8b612 FFBCED0863554B4D   Donald no Magical World (Ronald in the Magical World)/COUNTRY=JP/PRODUCT_NO=G-3340/COMMENT=The game has an alternate \"Ronald in the Magical World\" title screen when ran on export system, but it was never released outside of Japan.\r\nGG  733292a6 1D6B7F6FC8CE6D87   Doraemon Waku Waku Pocket Paradise/COUNTRY=JP/PRODUCT_NO=G-3383\r\nGG  1307a290 505B00DA3C579A4E   Double Dragon/NAME_EU=Double Dragon - The Revenge of Billy Lee/COUNTRY=US,EU/PRODUCT_NO=T-70038,T-70038-50\r\nGG  331904c0 B247BC4945B611F6   Double Dragon [Proto]/FLAGS=PROTO/COUNTRY=US,EU/COMMENT=Prototype version of the game.\r\nGG  c9907dce 63F29FF2C073A146   Dr. Franken [Demo]/FLAGS=PROTO/COMMENT=Prototype demo version of the unreleased game.\r\nGG  3c2d4f48 129ED3B48CD93133   Dr. Robotnik's Mean Bean Machine/COUNTRY=US,EU,BR/PRODUCT_NO=2446\r\nGG  69ebe5fa A3B7C429356E31E5   Dracula (Bram Stoker's)/COUNTRY=EU/PRODUCT_NO=T-93018-50\r\nGG  d966ec47 A3BEC3293C5E33E6   Dracula (Bram Stoker's)/COUNTRY=US/PRODUCT_NO=T-93018\r\nGG  89f12e1e D522749CF8737519   Dragon Crystal - Tsurani no Meikyuu/COUNTRY=JP/PRODUCT_NO=G-3206\r\nGG  0ef2ed93 77C55F382ABB2325   Dragon Crystal/COUNTRY=US,EU/PRODUCT_NO=2305\r\nGG  19e1cf2b D163D0F834459CEF   Dragon: The Bruce Lee Story/COUNTRY=EU/PRODUCT_NO=T-70148-50\r\nGG  17f588e8 D2CA3AAE14557F94   Dragon: The Bruce Lee Story/COUNTRY=US/PRODUCT_NO=T-81358\r\nGG  12e0e85b A2B9FD8131D7A778   Dragon: The Bruce Lee Story [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  152f0dcc 4C605B8937009F9A   Dropzone (Archer MacLean's)/COUNTRY=EU/PRODUCT_NO=T-121007/EMU_MAPPER=3\r\nGG  77ed48f5 646BC15AEE70793F   Dunk Kids/COUNTRY=JP/PRODUCT_NO=G-3352\r\nGG  610ff95c 44C54C81ACC8AC0A   Dynamite Headdy/COUNTRY=US,EU/PRODUCT_NO=2544\r\nGG  f6af4b6b B33070CAB97B921D   Dynamite Headdy/COUNTRY=JP/PRODUCT_NO=G-3355\r\nGG  843556b1 B5CDFD6349EA09E2   Dynamite Headdy [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  5d3f23a9 A338FA736E8E1D9F   Earthworm Jim/COUNTRY=US/PRODUCT_NO=T-132028\r\nGG  691ae339 4E2E597F60A504A3   Earthworm Jim/COUNTRY=EU/PRODUCT_NO=T-70178-50\r\nGG  a32eb9d5 26F78FEB7D00EB01   Ecco the Dolphin/COUNTRY=JP/PRODUCT_NO=G-3344\r\nGG  866c7113 855EA7962D1C2B6C   Ecco the Dolphin/COUNTRY=US,EU,BR/PRODUCT_NO=2516,077100\r\nGG  e2f3b203 21E70CD78EEE2D6C   Ecco - The Tides of Time/NAME_FR=Ecco - Les Marées du Temps/COUNTRY=US,EU,FR,BR,CH/PRODUCT_NO=2541,2541-50,02541F,077190/COMMENT=Export version of \"Ecco the Dolphin II\".\r\nGG  ba9cef4f AF60C9ACE9E9A406   Ecco the Dolphin II/COUNTRY=JP/PRODUCT_NO=G-3362/COMMENT=Japanese version of \"Ecco - The Tides of Time\".\r\nGG  5e53c7f7 658232077A8D8554   Ernie Els Golf/COUNTRY=EU/PRODUCT_NO=T-120098-50/EMU_MAPPER=3/COMMENT=This cartridge contains an onboard 64 KBit RAM chip.\r\nGG  04302bbd E46D03796A96D95A   Eternal Legend/COUNTRY=JP/PRODUCT_NO=G-3402,G-3412\r\nGG  36aaf536 970EAA8535666E23   Evander Holyfield's \"Real Deal\" Boxing/COUNTRY=US,EU/PRODUCT_NO=2419,2419-50\r\nGG  8bdb0806 D340349AE7C03345   F-15 Strike Eagle/COUNTRY=US,EU/PRODUCT_NO=T-104018,T-104018-50\r\nGG  aaf6f87d CFF55A311BC62FA1   Face Ball 2000/COUNTRY=JP/PRODUCT_NO=T-53037\r\nGG  59e3be92 C32205C4D7835C9C   Factory Panic/NAME_BR=Crazy Company/COUNTRY=EU,BR/PRODUCT_NO=2308/COMMENT=Export version of \"Ganbare Gorby!\".\r\nGG  d69097e8 2C887DCDCA714285   Fantasy Zone/NAME_JP=Fantasy Zone Gear - Opa Opa Jr. no Bouken/COUNTRY=JP,EU/PRODUCT_NO=T-44017,G-3225,2319/COMMENT=Title screen says \"Fantasy Zone Gear\".\r\nGG  fad007df 4ED59BC6746A841A   Fantasy Zone/COUNTRY=US,BR/PRODUCT_NO=2319,013480/COMMENT=Title screen says \"Fantasy Zone Gear\".\r\nGG  449787e2 01B1CB4E2F1E4C9C   Fatal Fury Special/COUNTRY=US/PRODUCT_NO=T-103028/COMMENT=Export version of \"Garou Densetsu Special\".\r\nGG  fbd76387 08B5C74D2F1B4C99   Fatal Fury Special/COUNTRY=EU/PRODUCT_NO=2582-50/COMMENT=Export version of \"Garou Densetsu Special\".\r\nGG  e632a3a2 79E80A0C5A985A3D   FIFA International Soccer/COUNTRY=US,EU/PRODUCT_NO=T-50018,T-50018-50\r\nGG  78159325 7ECE281E38B22163   FIFA International Soccer/COUNTRY=JP/PRODUCT_NO=T-106017\r\nGG  c379de95 B55C08995BA5E26C   FIFA Soccer 96/COUNTRY=US,EU/PRODUCT_NO=T-100108,T-100108-50\r\nGG  d46d5685 F20EFF6AC22E099E   Foreman for Real/COUNTRY=US,EU,JP/PRODUCT_NO=T-81348,T-81197\r\nGG  d0a93e00 2B05E6CBE6E79BB7   F1/NAME_US=Formula One/COUNTRY=US,EU/PRODUCT_NO=T-88058 301063-0161,T-88058-50\r\nGG  107092d0 9C6B7C172B17C85C   F1 - World Championship Edition/COUNTRY=EU/PRODUCT_NO=?\r\nGG  c443c35c DA478D64E6018A7D   Frank Thomas Big Hurt Baseball/COUNTRY=US/PRODUCT_NO=T-81328\r\nGG  e123d9b8 776593D0265E3FFE   Fray ~Shugyou hen~/COUNTRY=JP/PRODUCT_NO=T-52037\r\nGG  46f40b9f 6686067B7F5218AA   Fred Couples Golf/COUNTRY=US/PRODUCT_NO=2529\r\nGG  b1196cd7 FCB8715AAD21852E   Fred Couples Golf/COUNTRY=JP/PRODUCT_NO=G-3358\r\nGG  da724710 10CC5C366165B616   Frogger [Proto]/COUNTRY=US/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  a1f2f4a1 F740DD014127ACD7   Ganbare Gorby!/COUNTRY=JP/PRODUCT_NO=G-3210/COMMENT=Japanese version of \"Factory Panic\".\r\nGG  09534742 45190AB92665163E   Gamble Panic/COUNTRY=JP/PRODUCT_NO=G-3364\r\nGG  423803a7 9E7E0CAD62261E85   Gambler Jikochuushin Ha/COUNTRY=JP/PRODUCT_NO=G-3309,G-3339\r\nGG  0593ba24 905D6D377D1F9D36   Galaga '91/COUNTRY=JP/PRODUCT_NO=T-14057/COMMENT=Japanese version of \"Galaga 2\".\r\nGG  95ecece2 432C080C09AD5275   Galaga 2/COUNTRY=EU/PRODUCT_NO=2322/COMMENT=Export version of \"Galaga '91\".\r\nGG  cd53f3af 5434506F49A77C4D   Garfield: Caught in the Act/COUNTRY=US,EU,BR/PRODUCT_NO=2560,2560-50,077290\r\nGG  9afb6f33 CE07E49360532BD6   Garou Densetsu Special/COUNTRY=JP/PRODUCT_NO=T-103017/COMMENT=Japanese version of \"Fatal Fury Special\".\r\nGG  0e300223 27BA4F0E3A5DBF6C   Gear Stadium/COUNTRY=JP/PRODUCT_NO=T-14037/COMMENT=Japanese version of \"Batter Up\".\r\nGG  a0530664 08ADE585B8DA024D   Gear Stadium Heiseiban/COUNTRY=JP/PRODUCT_NO=T-14077\r\nGG  e9a2efb4 F9F734AF23CDB28B   Gear Works/COUNTRY=US/PRODUCT_NO=T-93058\r\nGG  58b44585 C92745E46E995090   George Foreman's KO Boxing/COUNTRY=US,EU/PRODUCT_NO=T-81038,T-81038-50\r\nGG  1b80a75b 682713F64A0AAD67   GG Aleste/COUNTRY=JP/PRODUCT_NO=T-66017\r\nGG  9a8b2c16 4200580F20BADF9E   GG Doraemon Nora No Suke No Yabou/COUNTRY=JP/PRODUCT_NO=G-3326\r\nGG  695cc120 FCC991E880B52D60   GG Portrait - Pai Chen/COUNTRY=JP/PRODUCT_NO=G-3387\r\nGG  51159f8f 5D96967FEE1C49A5   GG Portrait - Yuuki Akira/COUNTRY=JP/PRODUCT_NO=G-3386\r\nGG  83926bd1 7EC1D6C6D2A7119B   GG Shinobi, The/COUNTRY=JP/PRODUCT_NO=G-3302\r\nGG  d2b6021e F0E8A87399B7C4F9   Global Gladiators/COUNTRY=US,EU/PRODUCT_NO=T-70058,T-70058-50\r\nGG  abbd0222 1C3B4548B9BEEEB7   Global Golf [Proto]/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of \"Ernie Els Golf\".\r\nGG  18de59ed 093B5C63C1FA1E24   G-LOC - Air Battle/NAME_BR=G-LOC/COUNTRY=US,EU,BR/PRODUCT_NO=2301,012120\r\nGG  2333f615 9B4CDA9945218AB6   G-LOC - Air Battle [v0]/COUNTRY=JP/PRODUCT_NO=G-3204\r\nGG  33237f50 6949D8B6CE13CD12   G-LOC - Air Battle [v1]/COUNTRY=JP/PRODUCT_NO=G-3204\r\nGG  4cf97801 AB28B8AACF008D6F   Godzilla - Kaijuu Daishingeki/COUNTRY=JP/PRODUCT_NO=G-3430\r\nGG  7a26ec6a 6D6E6D3BB3A373B4   GP Rider/COUNTRY=JP/PRODUCT_NO=G-3347\r\nGG  876e9b72 12D2CD56CAF145F9   GP Rider/COUNTRY=US,EU/PRODUCT_NO=2528\r\nGG  f27925b0 5184CBDD08EAAEE3   Greendog - The Beached Surfer Dude!/COUNTRY=US,BR/PRODUCT_NO=2429,075270\r\nGG  a93e8b0f AB0C222F75C0695A   Griffin/COUNTRY=JP/PRODUCT_NO=T-49017\r\nGG  c3c52767 6A66AD66C5D81A66   Gunstar Heroes/COUNTRY=JP/PRODUCT_NO=G-3349\r\nGG  7e9dea46 400DE4894112C132   Halley Wars/NAME_BR=Space Battle/COUNTRY=US,EU,BR/PRODUCT_NO=2318,013500\r\nGG  def5a5d0 1F25824E7BFAA5D2   Halley Wars/COUNTRY=JP/PRODUCT_NO=T-11027\r\nGG  7e689995 90F66A8B1F353DF4   Head Buster/COUNTRY=JP/PRODUCT_NO=T-25017\r\nGG  beed9150 BFF25E2CEA4F8C00   Heavy weight Champ/COUNTRY=JP/PRODUCT_NO=T-44027\r\nGG  dde29f74 4CB0035708055746   Home Alone/NAME_BR=Home Alone - Esqueceram de Mim/COUNTRY=US,EU,BR/PRODUCT_NO=2410,075100\r\nGG  dfa805a0 357F4A30EE2C9A1E   Honoo no Toukyuuji Dodge Danpei/COUNTRY=JP/PRODUCT_NO=G-3220\r\nGG  a5aa5ba1 1D9F6DAE1A4EB60B   Hook/COUNTRY=EU/PRODUCT_NO=T-93028-50\r\nGG  f53ced2e 54FCF17485714015   Hook/COUNTRY=US/PRODUCT_NO=T-93028\r\nGG  0a25eec5 83AE170BBEE765A3   Hurricanes/COUNTRY=EU/PRODUCT_NO=79138-50\r\nGG  42389270 3F8665D57BA3A043   Hyokkori Hyoutan Jima - Hyoutan Jima no Daikoukai/COUNTRY=JP/PRODUCT_NO=G-3218\r\nGG  056cae74 07EAA1CEF2F8BBFB   Hyper Chou Pro Yakyuu '92/COUNTRY=JP/PRODUCT_NO=G-3217\r\nGG  9f64c2bb 69824C1FDBCFC040   Ichidant~R GG (Puzzle & Action)/COUNTRY=JP/PRODUCT_NO=G-3359/COMMENT=Proper Japanese transcription is \"Ichidanto A~Ru GG\". \"Ichidant~R\" is official romanization of the Arcade version. Note the different position of the tilde. Title screen shows \"PUZZLLE & ACTION\" with 2 L.\r\nGG  087fc247 F1E3947961D3D813   Incredible Crash Dummies, The/NAME_JP=Incredible Crash Dummies, The - Crash Dummy ~Slick Bouya no Daichousen~/COUNTRY=US,EU,JP/PRODUCT_NO=T-81138,T-81138-50,T-81127/COMMENT=Also referred to as \"Crash Dummies\".\r\nGG  d7055f88 C11C2B5FAA24A02B   Incredible Hulk, The/COUNTRY=US,EU/PRODUCT_NO=T-79078,79078-50\r\nGG  b875226b 4991B2A2AE8AB8E2   Indiana Jones and the Last Crusade/NAME_EU=Indiana Jones and the Last Crusade: The Action Game/NAME_BR=Indiana Jones e a Ultima Crusada/COUNTRY=US,EU,BR/PRODUCT_NO=T-79028,79028-50,075060\r\nGG  dab0f265 67E30F160D0B7FFA   In the Wake of Vampire/COUNTRY=JP/PRODUCT_NO=T-44047/COMMENT=Japanese version of \"Vampire - Master of Darkness\" (USA) and \"Master of Darkness\" (Europe).\r\nGG  44e7e2da C919CCEF16A7376F   Itchy & Scratchy Game, The/COUNTRY=US,EU/PRODUCT_NO=T-81218,T-81218-50\r\nGG  881a4524 499877BC81C4D4D3   James Bond 007: The Duel/COUNTRY=EU/PRODUCT_NO=T-88038-50\r\nGG  f8c31c15 7AFDED08CD2D0B8F   James Bond 007 - The Duel [Proto]/FLAGS=PROTO\r\nGG  9fb5c155 50DEECE6BA2DD940   James Pond II - Codename: RoboCod/COUNTRY=US/PRODUCT_NO=T-79068\r\nGG  c2f7928b 62A218D5697EDB4D   James Pond II - Codename: RoboCod/COUNTRY=EU/PRODUCT_NO=79068,79068-50\r\nGG  68bb7f71 32FF34928F7D6B92   James Pond 3 - Operation Starfi5h/COUNTRY=EU/PRODUCT_NO=79158-50/EMU_IPERIOD=227/COMMENT=Packaging and in-game screens are inconsistent about the exact name spelling. Packaging, manual and cartridges all says \"Operation Starfi5h\". In-game screens says \"James Pond 3 - Operation Starfish\".\r\nGG  d7820c21 4BB99C103FA92B3D   Jeopardy!/COUNTRY=US/PRODUCT_NO=T-83038\r\nGG  5ab12961 8F9C641F8EEACD0D   Jeopardy! [Proto]/COUNTRY=US/FLAGS=PROTO\r\nGG  2dd850b7 2C18F1F2231B2E6D   Jeopardy! Sports Edition/COUNTRY=US/PRODUCT_NO=T-83078\r\nGG  2e01ba6c 79B3C73C524481BA   Joe Montana Football [v0]/COUNTRY=US,EU/PRODUCT_NO=2403\r\nGG  4a98678b F1553EA2FE16794D   Joe Montana Football [v1]/COUNTRY=JP,BR/PRODUCT_NO=G-3305,016040\r\nGG  a12a28a0 214814EA42B19C0A   J League GG Pro Striker '94/COUNTRY=JP/PRODUCT_NO=G-3417\r\nGG  abddf0eb CC0DEE292FE1B749   J League Soccer Dream Eleven/COUNTRY=JP/PRODUCT_NO=G-3431\r\nGG  04d23fc4 3CC3817F0F2AD7F1   Judge Dredd/COUNTRY=US,EU/PRODUCT_NO=T-81228,T-81228-50\r\nGG  a8ef36a7 3D8EFDAAD4168123   Junction/COUNTRY=JP/PRODUCT_NO=T-22017\r\nGG  32abaa02 12D49B6FB6946B5B   Junction/COUNTRY=US/PRODUCT_NO=T-22018\r\nGG  30c09f31 BC411BF2B555F1FB   Jungle Book, The (Walt Disney's)/COUNTRY=US/PRODUCT_NO=T-70118,1198/COMMENT=Majesco release says \"Walt Disney's\", regular release says only \"Disney's\".\r\nGG  90100884 AE4DC2168F64AF8B   Jungle Book, The (Walt Disney's Classic)/NAME_FR=Le Livre de la Jungle (Walt Disney's Classic)/NAME_DE=Das Dschungelbuch (Walt Disney's Classic)/COUNTRY=EU,FR,DE/PRODUCT_NO=T-70118-50,T-70118-09,T-70118-18\r\nGG  d51642b0 DA20C3B345BD622C   Jungle Strike/COUNTRY=US/PRODUCT_NO=T-100038\r\nGG  bd6f2321 78FF86D439FA807C   Jurassic Park/COUNTRY=US,EU,BR/PRODUCT_NO=2511,077050\r\nGG  2f536ae3 2192332A14FC845C   Jurassic Park/COUNTRY=JP/PRODUCT_NO=G-3229\r\nGG  937fd52b 5B21015F3D470997   Kaitou Saint Tail/COUNTRY=JP/PRODUCT_NO=G-3382\r\nGG  23f9150a 14860DC4BF4D9CED   Kawasaki Superbikes/COUNTRY=EU/PRODUCT_NO=T-88118-50/COMMENT=Title screen says \"Kawasaki SuperBike Challenge\" like the US version.\r\nGG  fc508318 7309BA56E30C94F1   Kawasaki SuperBike Challenge/COUNTRY=US/PRODUCT_NO=T-88098 301069-0161\r\nGG  d9ce3f4c 896982D01506AFF2   Kenyuu Densetsu Yaiba/COUNTRY=JP/PRODUCT_NO=G-3346\r\nGG  fd14ce00 E8983AA73B33032E   Kick & Rush/COUNTRY=JP/PRODUCT_NO=T-44057\r\nGG  4af7f2aa FAF731A5A0AB9757   Kinetic Connection/COUNTRY=JP/PRODUCT_NO=G-3401\r\nGG  7d622bdd 73CDFBB9A17B628E   Kishin Douji Zenki/COUNTRY=JP/PRODUCT_NO=G-3373\r\nGG  9b40fc8e B87E281ACCCE2FBF   KLAX/COUNTRY=US,EU/PRODUCT_NO=301040-0161,T-48048-50\r\nGG  398f2358 D04392A2150C4850   Kuni Chan no Game Tengoku/COUNTRY=JP/PRODUCT_NO=G-3303\r\nGG  f3774c65 FFCDA1F1F85CCC82   Kuni Chan no Game Tengoku Part 2/COUNTRY=JP/PRODUCT_NO=G-3322\r\nGG  d01e784f 3321E82A25113E26   Krusty's Fun House/COUNTRY=US,EU/PRODUCT_NO=T-81078,T-81078-50\r\nGG  52dbf3e1 B0B04035A468D44B   Land of Illusion - Starring Mickey Mouse/NAME_BR=Land of Illusion - Estrelando Mickey Mouse/COUNTRY=US,EU,BR/PRODUCT_NO=2509,077020/COMMENT=Export version of \"Mickey Mouse no Mahou no Crystal\".\r\nGG  2d367c43 415BEEFFADDCF9F5   Last Action Hero/COUNTRY=US/PRODUCT_NO=T-93048\r\nGG  ce5ad8b7 4789B713B7475612   Legend of Illusion - Starring Mickey Mouse/COUNTRY=US,EU/PRODUCT_NO=2533,2533-50/COMMENT=Export version of \"Mickey Mouse Densetsu no Oukoku\".\r\nGG  0fde7baa 48D2B5FB715B2545   Lemmings/COUNTRY=US,EU,JP,BR/PRODUCT_NO=2431,G-3317,075210\r\nGG  51548f61 B706651F0ECDA044   Lemmings [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  fbc807e1 1A2D0A371C939930   Lemmings 2 - The Tribes [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  9808d7b3 0DE81165350FE170   Lion King, The (Disney's)/COUNTRY=US,BR/PRODUCT_NO=2549,1205,077200\r\nGG  0cd9c20b 0EE71166350EE170   Lion King, The (Disney's)/COUNTRY=EU/PRODUCT_NO=T-70158\r\nGG  c78b8637 B71DD32DCAA24779   Lion King, The (Disney's)/COUNTRY=JP/PRODUCT_NO=G-3363\r\nGG  8d1597f5 A2C697B8888E2E05   Lost World: Jurassic Park, The/COUNTRY=US/PRODUCT_NO=2574\r\nGG  07a7815a EEBEEC8A267160E7   Lucky Dime Caper, The - Starring Donald Duck/NAME_BR=Lucky Dime Caper, The - Estrelando Pato Donald/COUNTRY=US,EU,BR/PRODUCT_NO=2404,013560/COMMENT=Export version of \"Donald Duck no Lucky Dime\".\r\nGG  58459edd 5540503E9E1A8A9B   Lunar - Sanpo-suru Gakuen/COUNTRY=JP/PRODUCT_NO=T-45017\r\nGG  75c71ebf C4BF3F5C6538EF56   Madden NFL 95/COUNTRY=US/PRODUCT_NO=T-50028\r\nGG  9f59d302 3849BAC2E6B62D3A   Madden 96/COUNTRY=US,EU/PRODUCT_NO=T-100118,T-100118-50\r\nGG  00c34d94 01B64665BDBF978B   Madoh Monogatari I - Mittsu no Madoukyuu/COUNTRY=JP/PRODUCT_NO=G-3410\r\nGG  12eb2287 3A833A5A08D0F2E5   Madoh Monogatari II - Aruru 16-sai/COUNTRY=JP/PRODUCT_NO=G-3419\r\nGG  0a634d79 2BAC3EE795F07A05   Madoh Monogatari III - Kyuukyoku Joou-sama [v0]/COUNTRY=JP/PRODUCT_NO=G-3424\r\nGG  568f4825 2CAB3EE795F07A05   Madoh Monogatari III - Kyuukyoku Joou-sama [v1]/COUNTRY=JP/PRODUCT_NO=G-3424\r\nGG  f9c3ce13 5FD8035322691ECA   Madoh Monogatari III - Kyuukyoku Joou-sama [Proto]/COUNTRY=JP/FLAGS=PROTO\r\nGG  7ec95282 4E4D0E995D8F933F   Madoh Monogatari A - Doki Doki Vacation/COUNTRY=JP/PRODUCT_NO=T-66047\r\nGG  cf6d7bc5 BC1CE72A38884E09   Magical Puzzle Popils/NAME_EU=Popils - The blockbusting Challenge/COUNTRY=JP,US,EU/PRODUCT_NO=T-48017,301200-160,T-48068-50\r\nGG  8f82a6b9 5837AF8624E254E2   Magic Knight Rayearth/COUNTRY=JP/PRODUCT_NO=G-3423/COMMENT=Also referred to using Japanese characters as \"Mahou Kishi Rayearth\".\r\nGG  1c2c2b04 349A9743A068B997   Magic Knight Rayearth 2 ~making of magic knight~/COUNTRY=JP/PRODUCT_NO=G-3429/COMMENT=Also referred to using Japanese characters as \"Mahou Kishi Rayearth 2 ~making of magic knight~\".\r\nGG  6e1cc23c 0D6D3E01E06AB24B   Magical Taruruuto-kun/COUNTRY=JP/PRODUCT_NO=T-65017\r\nGG  36ebcd6d 15446D03DB6DB53A   Majors Pro Baseball, The/COUNTRY=US/PRODUCT_NO=2418/EMU_MAPPER=4\r\nGG  d9a7f170 EEF607B16825FADD   Man Overboard!/COUNTRY=EU/PRODUCT_NO=T-120088-50/EMU_MAPPER=3/EMU_TVTYPE=PAL\r\nGG  01d2dd2a 2CB25F033DADD204   Mappy/COUNTRY=JP/PRODUCT_NO=T-14027\r\nGG  9559e339 B424918FF035A83B   Marble Madness/COUNTRY=US,EU/PRODUCT_NO=T-48058,T-48058-50\r\nGG  22c418bf 4E62CA7D9E439B8D   Marko's Magic Football/COUNTRY=EU/PRODUCT_NO=T-88078-50\r\nGG  07d0eb42 91E3936BDE317A05   Master of Darkness/NAME_BR=Vampire - Master of Darkness/COUNTRY=EU,BR/PRODUCT_NO=2437,075140/COMMENT=European version of \"In the Wake of Vampire\" (Japan) and \"Vampire - Master of Darkness\" (Europe).\r\nGG  1ace93af F0B8660AB1883B74   Mega Man/COUNTRY=US/PRODUCT_NO=?\r\nGG  2e4ec17b F5296F1E651FF4DD   Megami Tensei Gaiden: Last Bible/COUNTRY=JP/PRODUCT_NO=G-3418\r\nGG  4ec30806 6FA65308EF07702A   Megami Tensei Gaiden: Last Bible Special/COUNTRY=JP/PRODUCT_NO=G-3427\r\nGG  fe12a92f C47B5E5AC577A12C   Mickey Mouse Densetsu no Oukoku/COUNTRY=JP/PRODUCT_NO=G-3360/COMMENT=Japanese version of \"Legend of Illusion - Starring Mickey Mouse\".\r\nGG  0117c3df 6C107B6F23212630   Mickey Mouse no Mahou no Crystal/COUNTRY=JP/PRODUCT_NO=G-3323/COMMENT=Japanese version of \"Land of Illusion - Starring Mickey Mouse\".\r\nGG  eccf7a4f DE2CEEA5F01F074D   Mickey's Ultimate Challenge/COUNTRY=US/PRODUCT_NO=T-112028\r\nGG  f7c524f6 51710931D2A8ED9D   Micro Machines/COUNTRY=EU,US/PRODUCT_NO=16001,17001/EMU_MAPPER=3\r\nGG  c21e6cd0 15FFF86F9928C400   Micro Machines [Proto]/FLAGS=PROTO/EMU_MAPPER=3/COMMENT=Prototype version of the game.\r\nGG  dbe8895c 0D511C6572333844   Micro Machines 2: Turbo Tournament/COUNTRY=EU/PRODUCT_NO=T-120108-50/EMU_MAPPER=3\r\nGG  9289dfcc 2D785B7B8B594E53   Mighty Morphin Power Rangers/COUNTRY=US,EU/PRODUCT_NO=2548,2548-50\r\nGG  b47c19e5 F02DEF107C75975C   Mighty Morphin Power Rangers: The Movie/COUNTRY=US,EU,BR/PRODUCT_NO=2564,2564-50,077250\r\nGG  1ecf07b4 C1D9061468CD789F   MLBPA Baseball/COUNTRY=US/PRODUCT_NO=T-50058\r\nGG  4d5d15fb 9A15007FFAC7F51C   Moldorian ~Hikari to Yami no Shisutaa~/COUNTRY=JP/PRODUCT_NO=G-3422\r\nGG  453c5cec 3190F6DA57189070   Monster Truck Wars/COUNTRY=US,EU/PRODUCT_NO=T-81288,T-81288-50\r\nGG  ea89e0e7 F36CF621FCC28C40   Monster World II - Dragon no Wana/COUNTRY=JP/PRODUCT_NO=G-3308/COMMENT=Japanese version of \"Wonder Boy: The Dragon's Trap\".\r\nGG  07494f2a 108F1B645538E075   Mortal Kombat/COUNTRY=US,EU/PRODUCT_NO=T-81198,T-81198-50\r\nGG  dbff0461 48AEDFE8EA0EEC5F   Mortal Kombat - Shinken Kourin Densetsu/COUNTRY=JP/PRODUCT_NO=T-81017\r\nGG  16db4f6a 0129822DFA4924C0   Mortal Kombat [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  4b304e0f 607CA3543FEBBE45   Mortal Kombat II/NAME_JP=Mortal Kombat II - Kyukyoku Shinken/COUNTRY=JP,US,EU/PRODUCT_NO=T-81107,T-81278,T-81278-50\r\nGG  c2be62bb 7CDB14D40344D8A2   Mortal Kombat 3/COUNTRY=EU/PRODUCT_NO=T-81368-50\r\nGG  5ee88bd5 571564ED798B67D8   Ms. Pac-Man/COUNTRY=US/PRODUCT_NO=T-14048\r\nGG  bcce5fd4 14D6D23E291005C8   Nazo Puyo [v0]/COUNTRY=JP/PRODUCT_NO=G-3224\r\nGG  d8d11f8d 13D7D33E291005C7   Nazo Puyo [v1]/COUNTRY=JP/PRODUCT_NO=G-3224\r\nGG  73939de4 E6D9919FD2886354   Nazo Puyo 2/COUNTRY=JP/PRODUCT_NO=G-3413\r\nGG  54ab42a4 05449D8E50F56DDA   Nazo Puyo Aruru no Ruu/COUNTRY=JP/PRODUCT_NO=G-3357\r\nGG  4c874466 7B8178C415DEF4E1   Nazo Puyo Aruru no Ruu [Editor Proto]/FLAGS=PROTO/COUNTRY=JP/COMMENT=Development version embedding a full-featured level editor.\r\nGG  19030108 89CC59B95194278D   NBA Action - Starring David Robinson/NAME_BR=NBA Action - Estrelando David Robinson/COUNTRY=US,BR/PRODUCT_NO=2409,075390/EMU_TVTYPE=NTSC\r\nGG  8f17597e 64654505786B10FA   NBA Jam/COUNTRY=US,EU/PRODUCT_NO=T-81248\r\nGG  a49e9033 5F43D36F49F4AB34   NBA Jam/COUNTRY=JP/PRODUCT_NO=T-81037\r\nGG  86c32e5b A8121F7AE0AC57CA   NBA Jam Tournament Edition/COUNTRY=US,EU,JP/PRODUCT_NO=T-81308,T-81308-50,T-81137/COMMENT=Also referred to as \"NBA JAM T.E.\".\r\nGG  3679be80 FCD47238A9F827BE   Neko Dai Suki!/COUNTRY=JP/PRODUCT_NO=G-3434\r\nGG  dc5b0407 5E4B9FC084E7107D   NFL '95/COUNTRY=US/PRODUCT_NO=2518\r\nGG  61785ed5 FD0304D38203D6CE   NFL Quarterback Club/NAME_JP=NFL Quarterback Club '95/COUNTRY=US,EU,JP/PRODUCT_NO=T-81208,T-81208-50,T-81147\r\nGG  c348e53a 58C8DD73B1B345E7   NFL Quarterback Club 96/COUNTRY=US/PRODUCT_NO=T-81378\r\nGG  c3056e15 22BA40932FD367E8   Ninkuu/COUNTRY=JP/PRODUCT_NO=G-3370\r\nGG  06247dd2 C6F0B20D1690598C   Ninkuu 2 ~Tenkuuryuu-e no Michi~/COUNTRY=JP/PRODUCT_NO=G-3376\r\nGG  9140f239 7DB3E5B919ED36F6   Ninkuu Gaiden - Hiroyuki Daikatsugeki/COUNTRY=JP/PRODUCT_NO=G-3377\r\nGG  20ef017a 491A5BE482A63303   Ninja Gaiden/COUNTRY=JP/PRODUCT_NO=G-3215/EMU_SPRITE_FLICKER\r\nGG  c578756b C216F5FA17F30926   Ninja Gaiden/COUNTRY=US,EU,BR/PRODUCT_NO=2312,013470/EMU_SPRITE_FLICKER\r\nGG  4680c7aa 743D647340B4FC88   NHL All-Star Hockey/NAME_CA=NHL All-Star Match Des Étoiles Hockey 95/COUNTRY=US,CA/PRODUCT_NO=2534\r\nGG  658713a5 1521D014975325D7   NHL Hockey/COUNTRY=US,EU/PRODUCT_NO=T-50048,T-50048-50\r\nGG  4ed45bda DE60DCC646F22CBC   Nomo's World Series Baseball/NAME_JP=Nomo Hideo no World Series Baseball/COUNTRY=JP/PRODUCT_NO=G-3432\r\nGG  71fe9c80 B3ACBC065EC8C7F2   Off The Wall [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  1e673168 76A0E0E382CF8254   Ottifants, The/COUNTRY=EU/PRODUCT_NO=2444,2444-50\r\nGG  d58cb27c 21B16C153724A0B2   Out Run/COUNTRY=JP,KR/PRODUCT_NO=G-3213,G-3222,GH-1006JG/EMU_IPERIOD=261\r\nGG  9014b322 12108246CB3247D2   Out Run/COUNTRY=EU,BR/PRODUCT_NO=2310,013460/EMU_IPERIOD=261\r\nGG  9273ee2c 024D2C99042B8D30   Pac-Attack/COUNTRY=US\r\nGG  64c28e20 C2E0E5F5C47DF350   Pac-In-Time [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  a16c5e58 3E0814A4FB499C22   Pac-Man/COUNTRY=JP/PRODUCT_NO=T-14017\r\nGG  b318dd37 BEDFF2E5AB5FA3DF   Pac-Man/COUNTRY=US/PRODUCT_NO=T-14018\r\nGG  e9783cea 09198DB9275CA96C   Panzer Dragoon Mini/COUNTRY=JP/PRODUCT_NO=G-3384\r\nGG  f54b6803 45111CC58FB4FF87   Paperboy/COUNTRY=US,EU/PRODUCT_NO=301029-0161,T-48028-50\r\nGG  8b2c454b 5A78E272B1729621   Paperboy 2/COUNTRY=US/PRODUCT_NO=301037-0161\r\nGG  0b271db6 2C7AF371AE76A72B   Paperboy 2 [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  0da23cc1 770CA17EE8E592FF   Pengo/COUNTRY=US,EU/PRODUCT_NO=2202\r\nGG  ce863dba 593C7A3470EED58A   Pengo/COUNTRY=JP/PRODUCT_NO=G-3102\r\nGG  c1756bee BDC45082B4BFDC5E   Pete Sampras Tennis/COUNTRY=EU/PRODUCT_NO=T-120078-50/EMU_MAPPER=3\r\nGG  c597ba5d 28E19F7D17FF06BF   Pete Sampras Tennis/COUNTRY=US/PRODUCT_NO=T-120078/EMU_MAPPER=3\r\nGG  b42d8430 12378C9F6286693B   Pet Club Inu Dai Suki!/COUNTRY=JP/PRODUCT_NO=G-3436\r\nGG  9700bb65 EF9680FBB3E34327   PGA TOUR Golf/COUNTRY=US,EU/PRODUCT_NO=T-48138 301045-0161,T-48138-50 301045-0161\r\nGG  4a8ac851 F910D3B7766EF495   PGA TOUR Golf II/COUNTRY=US,EU/PRODUCT_NO=T-48198 301088-0161,T-48198-50\r\nGG  542b6d8e F18A7578F6BB8067   PGA TOUR 96/COUNTRY=US,EU/PRODUCT_NO=T-100078,T-100078-50\r\nGG  1a51579d CEE87887BE4C5BE6   Phantasy Star Adventure/COUNTRY=JP/PRODUCT_NO=G-3216\r\nGG  a942514a 38B4091C24542651   Phantasy Star Gaiden/COUNTRY=JP/PRODUCT_NO=G-3405\r\nGG  281b1c3a F97057A139C5CFD2   Phantom 2040/COUNTRY=US,EU/PRODUCT_NO=T-139028,T-139028-50\r\nGG  635c483a 233F62535FB604D0   Pinball Dreams/COUNTRY=US/PRODUCT_NO=T-83058\r\nGG  cc90c723 5567550DB4B0017D   Pocket Jansou/COUNTRY=JP/PRODUCT_NO=T-14067\r\nGG  89d34067 2CE2D57DB5BA46EB   Poker Face Paul's Blackjack/COUNTRY=US/PRODUCT_NO=2326\r\nGG  d2e644b4 ECEC0711FB498745   Poker Face Paul's Cribbage [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  afd61b89 2B4995C63316E305   Poker Face Paul's Gin/COUNTRY=US/PRODUCT_NO=2328\r\nGG  e783daf8 A3CC9DD232AF4001   Poker Face Paul's Poker/COUNTRY=US/PRODUCT_NO=2325\r\nGG  0e9b0c0a 13AD1C132F72E28E   Poker Face Paul's Solitaire/COUNTRY=US/PRODUCT_NO=2327\r\nGG  71deba5a 75675BCE2FD003F9   Pop Breaker/COUNTRY=JP/PRODUCT_NO=T-52017/EMU_COUNTRY=1\r\nGG  09de1528 580F2481F9E66BAA   Power Strike II/NAME_JP=GG Aleste II/COUNTRY=JP,EU/PRODUCT_NO=G-3330,2443\r\nGG  3ef66810 E9A50801BEAAFD04   Popeye Beach Volley Ball/COUNTRY=JP/PRODUCT_NO=T-154017\r\nGG  ac369ae3 22747F9F9A975BC0   Power Drive/COUNTRY=EU/PRODUCT_NO=?\r\nGG  2a34b5c7 18673C53CC026BB9   Primal Rage/COUNTRY=US,EU/PRODUCT_NO=301108-0161 T-48218,T-48218-50\r\nGG  6d3a10d3 C8930333BCD00BD8   Pro Yakyuu '91, The/COUNTRY=JP/PRODUCT_NO=G-3207\r\nGG  2da8e943 50F748597A78081E   Pro Yakyuu GG League/COUNTRY=JP/PRODUCT_NO=G-3407/EMU_MAPPER=4\r\nGG  a1a19135 C6EE3E765A5503E6   Pro Yakyuu GG League '94/COUNTRY=JP/PRODUCT_NO=G-3353\r\nGG  afcc7828 B06D9479FA71A7C4   Psychic World/COUNTRY=JP/PRODUCT_NO=G-3203\r\nGG  73779b22 AF5D95122837E30B   Psychic World/COUNTRY=US,EU,BR/PRODUCT_NO=2306,012090\r\nGG  ecc301dd AD4D9A4947CE49C5   Putt & Putter/NAME_US=Putt & Putter - Miniature Golf/NAME_BR=Minigolf/COUNTRY=US,EU,BR/PRODUCT_NO=2307,013450\r\nGG  407ac070 ECCE2FC29C7E1526   Putt & Putter/COUNTRY=JP,KR/PRODUCT_NO=G-3209,GH-1008JG\r\nGG  d173a06f 6D6D979B9D368E93   Puyo Puyo (Puzlow Kids)/COUNTRY=JP/PRODUCT_NO=G-3324/COMMENT=The game has an alternate \"Puzlow Kids\" title screen when ran on export system, but it was never released outside of Japan.\r\nGG  3ab2393b A3111B362AD924D4   Puyo Puyo 2/COUNTRY=JP/PRODUCT_NO=T-66037\r\nGG  8e54ee04 E463A36AE4D522D1   Puzzle Bobble/COUNTRY=JP/PRODUCT_NO=T-11047\r\nGG  6c451ee1 2A50C584823D710D   Quest for the Shaven Yak Starring Ren Hoëk & Stimpy/COUNTRY=US,EU/PRODUCT_NO=2519\r\nGG  736cdb76 70BA6E9D99C81B4F   Quiz Gear Fight!!, The/COUNTRY=JP/PRODUCT_NO=G-3367\r\nGG  6dc3295e D56E2790AD1DEE4E   R.B.I. Baseball '94/COUNTRY=US/PRODUCT_NO=T-48168 301073-0161\r\nGG  03e9c607 EACA76A0EF9F1D8B   Revenge of Drancon/NAME_BR=Wonder Boy/COUNTRY=US,BR/PRODUCT_NO=2302,012080/COMMENT=US version of \"Wonder Boy\", with a different title.\r\nGG  38d8ec56 46EF1611B14E079E   Riddick Bowe Boxing/COUNTRY=US/PRODUCT_NO=T-22028\r\nGG  a45fffb7 45EF1710B24D079F   Riddick Bowe Boxing/COUNTRY=JP/PRODUCT_NO=T-22027\r\nGG  100b77b2 C8EC4DEA219A73E7   Rise of the Robots/COUNTRY=US,EU/PRODUCT_NO=T-48208/EMU_TVTYPE=NTSC/EMU_IPERIOD=229\r\nGG  efe65b3b 66C33CFBDC17A706   Ristar the Shooting Star/NAME_US=Ristar/NAME_EU=Ristar/COUNTRY=JP,US,EU/PRODUCT_NO=G-3365,2543,2543-50\r\nGG  069a0704 6065615A7606FD07   RoboCop 3/COUNTRY=JP,US,EU/PRODUCT_NO=T-81097,T-81178\r\nGG  4ab7fa4e E89A7A9BE94BBB7A   RoboCop versus The Terminator/COUNTRY=US,EU/PRODUCT_NO=?,T-70128-50\r\nGG  96045f76 897F02048B132F25   Road Rash/COUNTRY=US/PRODUCT_NO=T-79108\r\nGG  176505d4 897F02048B132F25   Road Rash/COUNTRY=EU/PRODUCT_NO=79108-50\r\nGG  445d7cd2 5A7BEBD52838F714   Royal Stone ~Hirakareshi Toki no Tobira~/COUNTRY=JP/PRODUCT_NO=G-3425\r\nGG  95efd52b 8FB34BFC642CB82F   Ryuu Kyuu/COUNTRY=JP/PRODUCT_NO=T-54017/COMMENT=Japanese version of \"Solitaire Poker\".\r\nGG  98171deb 86DFCF18904BCC0D   Samurai Shodown/COUNTRY=US/PRODUCT_NO=T-103018/COMMENT=Export version of \"Samurai Spirits\".\r\nGG  93fd73dc 13F9F13BACF847DD   Samurai Spirits/COUNTRY=JP/PRODUCT_NO=T-103027/COMMENT=Japanese version of \"Samurai Shodown\".\r\nGG  c7598b81 2A64139E7A706B6C   Sassou Shounen Eiyuuden Coca Cola Kid/COUNTRY=JP/PRODUCT_NO=G-3350\r\nGG  c10df4ce F98712224DB4C487   Scratch Golf/COUNTRY=US/PRODUCT_NO=T-23018\r\nGG  ec0f2c72 F964F26101F693C6   Scratch Golf/COUNTRY=JP/PRODUCT_NO=T-23017\r\nGG  5e2b39b8 DF6FF459A561AAB5   SD Gundam Winner's History/COUNTRY=JP/PRODUCT_NO=T-133027\r\nGG  5b68da75 75F6BDAA6E596DFA   Sensible Soccer/COUNTRY=EU/PRODUCT_NO=5011,T-93068-50\r\nGG  0924d2ec 0BFD5F19A146A2F7   Sega Game Pack 4 in 1/COUNTRY=EU/PRODUCT_NO=?\r\nGG  758a7123 3ADB2D8A91BD41A5   Sega Game Pack 4 in 1 [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  09f9ed60 3179021AB1F4F3A2   Shadam Crusader ~Harukanaru Oukoku~/COUNTRY=JP/PRODUCT_NO=G-3404/COMMENT=Japanese version of \"Defenders of Oasis\".\r\nGG  2ae8c75f 3DDFD5DF7B74DE63   Shanghai II [v0]/COUNTRY=JP/PRODUCT_NO=T-15017\r\nGG  81314249 2604C2C899482D3E   Shanghai II [v1]/COUNTRY=JP/PRODUCT_NO=T-15037/COMMENT=Meisaku Collection version.\r\nGG  6fcb8ab0 FA3B4B7B568BAC78   Shaq Fu/COUNTRY=US/PRODUCT_NO=T-50038\r\nGG  9c5c7f53 7FF06E0DC05E8A6E   Shikinjo/COUNTRY=JP/PRODUCT_NO=T-15027\r\nGG  a6ca6fa9 76749360F64106E6   Shining Force - The Sword of Hajya/COUNTRY=US/PRODUCT_NO=2524/COMMENT=Export version of \"Shining Force Gaiden II ~Jashin no Mezame~\".\r\nGG  4d1f4699 C76F1AE91B588DC7   Shining Force Gaiden ~Ensei Jashin no Kuni e~/COUNTRY=JP/PRODUCT_NO=G-3406,G-3411\r\nGG  30374681 1F9714187E37FE6B   Shining Force Gaiden II ~Jashin no Mezame~/COUNTRY=JP/PRODUCT_NO=G-3409/COMMENT=Japanese version of \"Shining Force - The Sword of Hajya\".\r\nGG  6019fe5e 87CA29057C33E3EF   Shining Force Gaiden ~Final Conflict~/COUNTRY=JP/PRODUCT_NO=G-3428\r\nGG  30f1c984 82C3D1CAD4A50C9B   Shinobi/COUNTRY=US,EU,BR/PRODUCT_NO=2402,012110\r\nGG  6201c694 4C0CF2421287A932   Shinobi II - The Silent Fury/NAME_JP=GG Shinobi II/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-3315,2421,075280\r\nGG  3d9c92c7 E8852EFBB49DA277   Skweek/COUNTRY=JP/PRODUCT_NO=T-60017/COMMENT=Japanese version of \"Slider\".\r\nGG  6a603eed 8C280F0037C2ED57   Side Pocket/COUNTRY=US/PRODUCT_NO=T-13018\r\nGG  751dad4c B0541293B90BC5CE   Slam Dunk - Shouri-e no Starting 5 (From TV animation)/COUNTRY=JP/PRODUCT_NO=T-133037\r\nGG  4dc6f555 3D9031096A4369E3   Slider/COUNTRY=US,EU/PRODUCT_NO=2315/COMMENT=Export version of \"Skweek\".\r\nGG  354e1cbd B34D79D4184F2C20   Smurfs, The/NAME_FR=Les Schtroumpfs/COUNTRY=EU/PRODUCT_NO=T-151018-50\r\nGG  3eb337df 26F7604BBD50EA41   Smurfs Travel the World, The/COUNTRY=EU/PRODUCT_NO=T-151028-50\r\nGG  f6f24b75 8A518DD06AA27646   Solitaire FunPak/COUNTRY=US/PRODUCT_NO=T-125038\r\nGG  06f2fc46 FE70EF747ED5B22A   Solitaire Poker/COUNTRY=US,EU/PRODUCT_NO=2316/COMMENT=Export version of \"Ryuu Kyuu\".\r\nGG  031b9da9 7B48F7CDDDBD7D62   Sonic Blast/NAME_JP=G-Sonic/COUNTRY=JP,US,EU/PRODUCT_NO=G-3385,2573,2573-50\r\nGG  663f2abb 2ED7693B07C9BFC8   Sonic Chaos/COUNTRY=US,EU,BR/PRODUCT_NO=2515,1204,077080/COMMENT=Export version of \"Sonic & Tails\".\r\nGG  68f0a776 1BD056AB87F45643   Sonic Drift/COUNTRY=JP/PRODUCT_NO=G-3415\r\nGG  baac1fc0 2B2C712DA26B07F7   Sonic Drift [Demo]/COUNTRY=JP/COMMENT=Sample demo version. CPU plays automatically to demonstrate the game.\r\nGG  d6e8a305 0CE1C4FB95A321FB   Sonic Drift 2/NAME_EU=Sonic Drift Racing/COUNTRY=JP,US,EU/PRODUCT_NO=G-3366,2562,2563-50\r\nGG  5550173b BEFCEE0501199B9E   Sonic Labyrinth/COUNTRY=JP,US,EU/PRODUCT_NO=G-3374,2584\r\nGG  a9210434 B4010E08A03EFD5A   Sonic Spinball/COUNTRY=US,EU,BR/PRODUCT_NO=2526,1200,077060\r\nGG  8ac0dade 9DC02F576DAE37CB   Sonic & Tails/COUNTRY=JP/PRODUCT_NO=G-3331/COMMENT=Japanese version of \"Sonic Chaos\".\r\nGG  e0e3fb6a 4EFA2A6E6334F198   Sonic & Tails [Demo]/COUNTRY=JP/COMMENT=Sample demo version.\r\nGG  496bce64 866A749727ECB141   Sonic & Tails 2/COUNTRY=JP,CH/PRODUCT_NO=G-3356,2530/COMMENT=Japanese version of \"Sonic The Hedgehog Triple Trouble\".\r\nGG  3e31cb8c 2D341FEB6A1B46CA   Sonic The Hedgehog [v0]/COUNTRY=JP,US/PRODUCT_NO=G-3307,2408\r\nGG  d163356e 53D934469DC6E116   Sonic The Hedgehog [v1]/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-3307,G-3334,2408,013550\r\nGG  816c0a1e 97222AD3F8DE1D57   Sonic The Hedgehog [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  95a18ec7 D2612363E352F220   Sonic The Hedgehog 2/COUNTRY=JP,US,EU/PRODUCT_NO=G-3321,G-3338,2507\r\nGG  15ad37a5 0CE7F172FF90100B   Sonic The Hedgehog 2 [Demo]/FLAGS=PROTO\r\nGG  d23a2a93 0F635FF9B1886A93   Sonic The Hedgehog Triple Trouble/COUNTRY=US,EU,BR/PRODUCT_NO=2530,2530-50,077180/COMMENT=Export version of \"Sonic & Tails 2\".\r\nGG  0f3e3840 4FFC5704FCA43783   Soukoban/COUNTRY=JP/PRODUCT_NO=T-53017\r\nGG  600c15b3 308DC2BE252AC7AD   Space Harrier/COUNTRY=JP,US,EU/PRODUCT_NO=G-3212,2314\r\nGG  bc240779 1D52E7C5C3B8F07A   Spider-Man - Return of the Sinister Six/COUNTRY=US,EU/PRODUCT_NO=T-81128,T-81128-50\r\nGG  2651024e 43EA5FAFAF94EA98   Spider-Man - vs. The Kingpin/COUNTRY=US,EU/PRODUCT_NO=T-81028,T-81028-50\r\nGG  742a372b D307ACC6641167D8   Spider-Man \\/ X-Men: Arcade's Revenge/COUNTRY=US/PRODUCT_NO=T-81158\r\nGG  ab622adc A46DDD4AEBC96CA8   Spirou [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  920ea193 429F753B3F39CC2B   Sports Illustrated - Championship Football & Baseball/COUNTRY=US/PRODUCT_NO=T-100128\r\nGG  a7af7ca9 8E4C09D06B5DE4A1   Sports Trivia/COUNTRY=US/PRODUCT_NO=2329\r\nGG  15e7e261 38A735F8A227D655   Sports Trivia - Championship Edition/COUNTRY=US/PRODUCT_NO=2450\r\nGG  5b5de94d 7C8CA98E3973C74E   Sports Trivia - Championship Edition [Proto]/FLAGS=PROTO\r\nGG  fc7c64e4 2D231FD27C8A8930   Stargate/COUNTRY=US,EU,JP/PRODUCT_NO=T-81298,T-81298-50,T-81157\r\nGG  087fc5f0 B5826969AF8E0EAC   Star Trek Generations - Beyond the Nexus/COUNTRY=US/PRODUCT_NO=T-86058\r\nGG  80156323 CCD54E587E846A4D   Star Trek: The Next Generation - The Advanced Holodeck Tutorial/COUNTRY=US/PRODUCT_NO=T-86038\r\nGG  db9bc599 E93FF14440FB3434   Star Wars/COUNTRY=EU/PRODUCT_NO=79098-50\r\nGG  0228769c E93FF24340FB3434   Star Wars/COUNTRY=US/PRODUCT_NO=T-79098\r\nGG  3d8bcf1d 5AD835BF116EC299   Streets of Rage/NAME_JP=Bare Knuckle/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-3313,2417,015600\r\nGG  0b618409 85CFE82DBD812633   Streets of Rage II/NAME_US=Streets of Rage 2/NAME_JP=Bare Knuckle II/NAME_BR=Streets of Rage 2/COUNTRY=JP,US,EU,BR/PRODUCT_NO=G-3328,2517,077030\r\nGG  6c395a69 BC45532F90B98FA5   Streets of Rage II [Proto]/NAME_US=Streets of Rage 2/NAME_JP=Bare Knuckle II/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  1ebfa5ca 24A227CBB87248D6   Strider Returns (Journey from Darkness)/COUNTRY=US,EU/PRODUCT_NO=T-79048,79048,79048-50\r\nGG  11085829 C5C24EB668D162DA   Strider Returns (Journey from Darkness) [Proto]/FLAGS=PROTO\r\nGG  b421c057 96BD12C62621B8D6   Striker/COUNTRY=EU/PRODUCT_NO=2551-50\r\nGG  73d6745a 18CC99C9849C9901   Super Battletank/COUNTRY=US/PRODUCT_NO=1239\r\nGG  8ba43af3 DAA4C785B7042952   Super Columns/COUNTRY=US,EU/PRODUCT_NO=2449,2449-50\r\nGG  2a100717 E7260408CEC8EE63   Super Columns/COUNTRY=JP/PRODUCT_NO=G-3226\r\nGG  528cbbce FAE75543A7740E5E   Super Golf/COUNTRY=JP/PRODUCT_NO=T-26017,T-26027\r\nGG  e9570f36 9AF88BBD917661BE   Super Golf/COUNTRY=US/PRODUCT_NO=T-47028\r\nGG  73df5a15 43574420E8CF212A   Superman - The Man of Steel/COUNTRY=EU/PRODUCT_NO=T-70068,70068-00\r\nGG  aa3f2172 0A5C6040EBCF152B   Superman - The Man of Steel [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  b731bb80 A220C02C0082E6EA   Super Momotarou Dentetsu III/COUNTRY=JP/PRODUCT_NO=T-143017\r\nGG  fcf12547 E7834B512CBEB35D   Super Monaco GP/NAME_BR=GP Mônaco/COUNTRY=US,EU,BR/PRODUCT_NO=2304,012140\r\nGG  4f686c4a 7F39562D4299AE3C   Super Monaco GP/COUNTRY=JP,KR/PRODUCT_NO=G-3201\r\nGG  1d1b1dd3 8E89AE12C88F29A9   Super Monaco GP II (Ayrton Senna's)/COUNTRY=US,EU,BR/PRODUCT_NO=2423,015570\r\nGG  661faeff 16D6ADD4B37ACB9B   Super Monaco GP II (Ayrton Senna's) [v0]/COUNTRY=JP/PRODUCT_NO=G-3312\r\nGG  7687ce09 35A7CAD2AB73C1A9   Super Monaco GP II (Ayrton Senna's) [v1]/COUNTRY=JP/PRODUCT_NO=G-3337/COMMENT=Meisaku Collection version.\r\nGG  6afb8ec6 07599F8B724D3582   Super Monaco GP II (Ayrton Senna's) [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  e8b42b1f C2886A87DB50B1E9   Super Off Road/COUNTRY=US,EU/PRODUCT_NO=T-70018,T-70018-50\r\nGG  a1160814 AA0503B950BDE4A4   Super Off Road [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  4a38b6b6 6FA3E44AAE525A66   Super Return of the Jedi (Star Wars)/COUNTRY=US,EU/PRODUCT_NO=T-100088,T-100088-50\r\nGG  1006e4e3 DA3A3FA2A0C2CCDD   Super Smash T.V./COUNTRY=US,EU,JP/PRODUCT_NO=T-81058,T-81058-50,T-81057/COMMENT=Official game material mentions \"Super Smash T.V.\", but the game shows a \"Smash T.V.\" title screen.\r\nGG  dfe38e24 3D4B8D95C6F89CFC   Super Space Invaders/COUNTRY=US,EU/PRODUCT_NO=T-48078 301052-0161,T-88028-50\r\nGG  284482a8 86FF547C91418D4C   Surf Ninjas/COUNTRY=US,EU,BR/PRODUCT_NO=2510,077090\r\nGG  45ef2062 1AF375AAF3F11AD6   Sylvan Tale/COUNTRY=JP/PRODUCT_NO=G-3426\r\nGG  9479c83a FF60671102D2A2B3   T2: The Arcade Game/COUNTRY=US,EU/PRODUCT_NO=T-81088,T-81088-50\r\nGG  0b1ba87f 7561EED848BF6CF1   T2: The Arcade Game/COUNTRY=JP/PRODUCT_NO=T-81027\r\nGG  5bb6e5d6 134A286D9BE1D8BA   Tails Adventures/NAME_US=Tails Adventure/NAME_EU=Tails Adventure/COUNTRY=JP,US,EU/PRODUCT_NO=G-3372,2583,2583-50\r\nGG  88618afa 9AB480AD16FFC7A9   Tails' Skypatrol/COUNTRY=JP/PRODUCT_NO=G-3368\r\nGG  7b7717b8 67685BAE2C08E014   Taisen-gata Daisenryaku G/COUNTRY=JP/PRODUCT_NO=T-51017,T-51027\r\nGG  cf9c607c 20AF191BD7103DD9   Taisen Mahjong Hao-Pai/COUNTRY=JP/PRODUCT_NO=G-3202,G-3223\r\nGG  20527530 128F9497F4469169   Taisen Mahjong Hao-Pai 2/COUNTRY=JP/PRODUCT_NO=G-3335\r\nGG  f1732ffe 0198EBBE947301B6   TaleSpin (Disney's)/COUNTRY=US,EU,BR/PRODUCT_NO=2412,075240\r\nGG  09151743 73869AAE809FD1CF   Tant~R (Puzzle & Action)/COUNTRY=JP/PRODUCT_NO=G-3345/COMMENT=Proper Japanese transcription is \"Tanto A~Ru\". \"Tant~R\" is official romanization. Note the different position of the tilde.\r\nGG  dd1d2ebf 8A60EE2A92FAE58D   Tama & Friends - 3 Choume Kouen Tamalympic/COUNTRY=JP/PRODUCT_NO=G-3361\r\nGG  57834c03 D0C9FEBE08434B15   Tarot no Yakata \\/ House of Tarot/COUNTRY=JP/PRODUCT_NO=G-3208\r\nGG  ef3afe8b D3490F3A10D27346   Tarzan - Lord of the Jungle/COUNTRY=EU/PRODUCT_NO=T-83098-50\r\nGG  bec57602 95202199862FC616   Tatakae! Pro Yakyuu Twin League/COUNTRY=JP/PRODUCT_NO=G-3371\r\nGG  36040c24 4CD14D2B04F786EA   Taz-Mania/COUNTRY=US,EU,BR/PRODUCT_NO=2413,075250\r\nGG  eebad66b 9B7DE59E03D29000   Taz in Escape from Mars/COUNTRY=US,EU,BR/PRODUCT_NO=2538,2538-50,077.170\r\nGG  de466796 2D756A0E3A873BEA   Tempo Jr./COUNTRY=JP,US,EU/PRODUCT_NO=G-3369,2563,2562-50\r\nGG  bf696f94 D5713EC45DD6B5D0   Tesserae/COUNTRY=US/PRODUCT_NO=T-83028\r\nGG  1cddd2a3 423AAD45E445D297   Tesserae [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  c029a5fd EFDF88CF8D68A343   Terminator, The/COUNTRY=US,EU/PRODUCT_NO=T-70048,T-70048-50\r\nGG  dd6d2e34 0942170D3CFD87D1   Tengen World Cup Soccer/COUNTRY=US,EU/PRODUCT_NO=T-48118,T-48118-50\r\nGG  8e6818ae 735FA418010478F5   Tengen World Cup Soccer [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  1bd15773 796B2AA0D64851E3   Terminator 2: Judgment Day/COUNTRY=US,EU/PRODUCT_NO=T-81148,T-81148-50\r\nGG  969cf389 5A5865B5148A5541   Tintin in Tibet/NAME_FR=Tintin au Tibet/COUNTRY=EU/PRODUCT_NO=T-151-038-50/COMMENT=Also referred to using the french title showing on the box: \"Tintin au Tibet\".\r\nGG  a1453efa D9F631F59C7933C3   Tom and Jerry: The Movie/COUNTRY=JP,BR/PRODUCT_NO=G-3319,075290\r\nGG  5cd33ff2 DC1F080D96A53D78   Tom and Jerry: The Movie/COUNTRY=US,EU/PRODUCT_NO=2434\r\nGG  5bcf9b97 F9471D41510253BC   Torarete Tamaruka!?/COUNTRY=JP/PRODUCT_NO=G-3348\r\nGG  5173b02a B31BDB3827A8440C   True Lies/COUNTRY=US,EU,JP/PRODUCT_NO=T-81318,T-81318-50,T-81167\r\nGG  820965a3 78192012DB30BF73   Ultimate Soccer/COUNTRY=JP,EU,BR/PRODUCT_NO=G-3333,075300\r\nGG  185e9fc1 07D77087D26DD517   Urban Strike/COUNTRY=US/PRODUCT_NO=T-100048\r\nGG  7ec64025 84C269594C15F3A4   Vampire - Master of Darkness/COUNTRY=US/PRODUCT_NO=2437/COMMENT=US version of \"In the Wake of Vampire\" (Japan) and \"Master of Darkness\" (Europe).\r\nGG  d431c452 89865690753E3F19   Virtua Fighter Animation/COUNTRY=US,EU/PRODUCT_NO=2570,MK2570-50\r\nGG  c05657f8 5B5E5A20BC6D6440   Virtua Fighter Mini/COUNTRY=JP/PRODUCT_NO=G-3380\r\nGG  b0f22745 E4B611A11356D972   VR Troopers/COUNTRY=US,EU,BR/PRODUCT_NO=2559,2559-50,077270\r\nGG  e91cdb2a 533DC337F17121F3   Wheel of Fortune/COUNTRY=US/PRODUCT_NO=T-83018\r\nGG  d460cc7f 32EEB88F6A58E2F5   WildSnake [Proto]/COUNTRY=US/PRODUCT_NO=T-124028/COMMENT=Prototype version of the unreleased game.\r\nGG  ce1108fd 5EF9334D02922E67   Wimbledon/NAME_US=Wimbledon Tennis/COUNTRY=JP,EU,US/PRODUCT_NO=G-3221,2323\r\nGG  d15d335b 8C9DF406D503E322   Winter Olympics/NAME_US=Winter Olympics Games/COUNTRY=US,EU/PRODUCT_NO=T-79088,T-79088-18\r\nGG  d5195a39 5AE30E1DD51AC5E4   Winter Olympics/COUNTRY=JP/PRODUCT_NO=G-3342\r\nGG  9e03f96c C2DB65453292985D   Wizard Pinball/COUNTRY=EU/PRODUCT_NO=T-88088-50\r\nGG  840a8f8e 9C35260DA7367AA5   Wolfchild/COUNTRY=EU/PRODUCT_NO=T-70078-50\r\nGG  9c0e5a04 902D4CDEE014FD28   Woody Pop [v0]/COUNTRY=JP/PRODUCT_NO=G-3101\r\nGG  b74f3a4f ED6C5F01DA350830   Woody Pop [v1]/COUNTRY=US,EU,BR/PRODUCT_NO=2203,013530\r\nGG  9977fcb3 9FF4810003787DF4   Wonder Boy/COUNTRY=JP/PRODUCT_NO=G-3205/COMMENT=Japanese version of \"Revenge of Drancon\" (US).\r\nGG  ea2dd3a7 F6D1E367A83FFA0E   Wonder Boy/COUNTRY=EU/PRODUCT_NO=2302/COMMENT=European version of \"Revenge of Drancon\" (US).\r\nGG  523c92cb A80ABF0DF2FCB1E3   Wonder Boy [Proto]/COUNTRY=US/FLAGS=PROTO/COMMENT=Prototype version of the game.\r\nGG  a74c97a7 2CDE35F4553095B3   Wonder Boy - The Dragon's Trap/COUNTRY=EU/PRODUCT_NO=2422/COMMENT=Export version of \"Monster World II - Dragon no Wana\".\r\nGG  db1b5b44 885AA4D1B3814E27   Wonder Boy - The Dragon's Trap [Proto]/FLAGS=PROTO/COUNTRY=EU/COMMENT=Export version of \"Monster World II - Dragon no Wana\". Prototype version of the game. Title screen says \"Wonder Boy III: The Dragon's Trap\".\r\nGG  868fe528 747E83E3BEE414F2   World Class Leaderboard/NAME_US=World Class LeaderBoard Golf/COUNTRY=US,EU/PRODUCT_NO=2406,2406-50\r\nGG  d2bb3690 39D9CF45064E186E   World Cup USA 94/COUNTRY=US,EU,UK,FR,BR/PRODUCT_NO=T-79128,79128-50,79128-09,79128-18,077130\r\nGG  1e81861f 756BCDAD19F5D3C5   World Derby/COUNTRY=JP/PRODUCT_NO=T-68017\r\nGG  3d8d0dd6 B172FFF90B6B79F6   World Series Baseball [v0]/COUNTRY=US/EMU_MAPPER=4\r\nGG  bb38cfd7 82392945686157B7   World Series Baseball [v1]/COUNTRY=US/EMU_MAPPER=4\r\nGG  578a8a38 1ED4D8EC92EBC10C   World Series Baseball '95/COUNTRY=US/EMU_MAPPER=4\r\nGG  8dc68d92 001C952F658A1021   WWF Raw/COUNTRY=US,EU/PRODUCT_NO=T-81258,T-81258-50\r\nGG  567a5ee6 4E1CB94E6B30D61E   X-Men/COUNTRY=US/PRODUCT_NO=2505\r\nGG  c169c344 CD0B39F3B2896859   X-Men: GamesMaster's Legacy/COUNTRY=US,EU/PRODUCT_NO=2531,2531-50\r\nGG  c2cba9d7 BAC9E98F228F95BF   X-Men: Mojo World/COUNTRY=US/PRODUCT_NO=2561\r\nGG  e678f264 734B2CD0EC0E2B21   Yogi Bear in Yogi Bear's Goldrush [Proto]/COUNTRY=US/FLAGS=PROTO/COMMENT=Prototype version of the unreleased game.\r\nGG  88ebbf9e B2B6F1EBDC28B206   Yu Yu Hakusho - Horobishi Mono no Gyakushuu/COUNTRY=JP/PRODUCT_NO=G-3343\r\nGG  46ae9159 33DF404CAF5A0B4E   Yu Yu Hakusho II - Gekitou! Nanakyou no Tatakai/COUNTRY=JP/PRODUCT_NO=G-3354\r\nGG  141aaf96 8CE8B1B8A48E3BB6   Zan Gear/COUNTRY=JP/PRODUCT_NO=T-32017\r\nGG  23904898 C3918F68D3C745D6   Zool: Ninja of the \"Nth\" Dimension/COUNTRY=EU\r\nGG  b287c695 B4F7F5B93F2FA792   Zool: Ninja of the \"Nth\" Dimension/COUNTRY=US/PRODUCT_NO=T-83048\r\nGG  e35ef7ed 41E4E0DC502EC3DE   Zool - Zool no Yume Bouken/COUNTRY=JP/PRODUCT_NO=T-149017\r\nGG  3247ff8b 126A1E96C18B90F4   Zoop/COUNTRY=US/PRODUCT_NO=T-139049\r\nGG  f397f041 0F6D1D96C28B90F4   Zoop [Proto]/FLAGS=PROTO\r\n\r\n; BIOS images\r\nGG  0ebea9d4 B5175CEECD71E2CA   Game Gear Majesco [BIOS]/FLAGS=BIOS/COUNTRY=US\r\n\r\n; Bad dumps\r\nGG  65e60dfe 516CF5541BA9E056   Batman Returns/FLAGS=BAD/COUNTRY=JP,US,EU/COMMENT=1 bad byte, affecting an instruction. It might be a hack.\r\nGG  fddd8cd9 82E53FF69611EBD2   Battleship - The classic naval combat game/FLAGS=BAD/COUNTRY=US/PRODUCT_NO=T-87018/COMMENT=Missing upper half of data. Although unused by the ROM, they are technically part of the ROM.\r\nGG  fdc8fc18 B33070CAB97B921D   Dynamite Headdy/FLAGS=BAD/COUNTRY=JP,US,EU/COMMENT=1 bad byte.\r\nGG  2b60873e 855EA7962D1B2B6D   Ecco the Dolphin/FLAGS=BAD/COUNTRY=US,EU/PRODUCT_NO=2516/COMMENT=1 bad byte.\r\nGG  365b92cf 2B867DCECA734285   Fantasy Zone Gear - Opa Opa Jr. no Bouken/FLAGS=BAD/COUNTRY=JP/PRODUCT_NO=T-44017,G-3225/COMMENT=9 bad bytes.\r\nGG  29b1df1a 01B1CB4E2F1E4C9C   Fatal Fury Special/FLAGS=BAD/COUNTRY=JP,US,EU/COMMENT=1 bad byte.\r\nGG  808a71c3 F2F739A55BF09757   Kinetic Connection/FLAGS=BAD/COUNTRY=JP/COMMENT=Overdumped ROM.\r\nGG  6755282d ED553EA2FE167951   Joe Montana Football/FLAGS=BAD/COUNTRY=JP/COMMENT=2 bad bytes.\r\nGG  8c048325 4991B2A2AE8AB9E1   Indiana Jones and the Last Crusade/FLAGS=BAD/COUNTRY=US,EU/COMMENT=1 bad byte. Doesn't affect game-play.\r\nGG  4e279baa ED0CCDB6736CF4B1   PGA TOUR Golf II/FLAGS=BAD/COUNTRY=US,EU/COMMENT=14 bad bytes.\r\nGG  03bb0668 7E75083EC5AC3224   Poker Face Paul's Poker/FLAGS=BAD/COUNTRY=US/COMMENT=Overdumped ROM.\r\nGG  4ed37a63 4B1A5BE482A63301   Ninja Gaiden/COUNTRY=JP/FLAGS=BAD/COMMENT=1 bad byte.\r\nGG  75e273eb 0C48B8C0E5B82B6C   Madden 96/FLAGS=BAD/COUNTRY=US,EU/COMMENT=27 bad bytes.\r\nGG  786dd67b F58430F7B49CA36D   Skweek/FLAGS=BAD/COUNTRY=JP/COMMENT=10 bad bytes.\r\nGG  de25e2d8 289F743A3E37CC4A   Sports Illustrated - Championship Football & Baseball/COUNTRY=US/FLAGS=BAD/COMMENT=16 bad bytes.\r\nGG  e30e7dc6 7F39562D4299AC3E   Super Monaco GP/FLAGS=BAD/COUNTRY=JP/COMMENT=2 bad bytes.\r\nGG  346e1cf1 16D6ADD4B37AC4A2   Super Monaco GP II (Ayrton Senna's)/FLAGS=BAD/COUNTRY=JP/COMMENT=7 bad bytes.\r\nGG  2e217fae BA886A87DB50B1F1   Super Off Road/FLAGS=BAD/COUNTRY=US,EU/COMMENT=4 bad bytes.\r\nGG  2ea26930 86FF547C91408D4D   Surf Ninjas/FLAGS=BAD/COUNTRY=US/COMMENT=1 bad byte.\r\nGG  cb591501 0F4A286C9AE1D8C0   Tails Adventures/FLAGS=BAD/COUNTRY=JP,US/COMMENT=3 bad bytes.\r\nGG  ca0e11cc D7713EC45DD6B5CE   Tesserae/FLAGS=BAD/COUNTRY=JP/COMMENT=1 bad byte.\r\nGG  924ce5be 2D0E8F4CFE37872E   Virtua Fighter Animation/FLAGS=BAD/COUNTRY=US\r\nGG  231e5b78 E4B611A11356D972   VR Troopers/FLAGS=BAD/COUNTRY=US,EU/COMMENT=2 bad bytes.\r\n\r\n; Hacks\r\nGG  90d40776 8A8E033FAF71E0A6   Lion King, The (Disney's) [Hack]/COUNTRY=US/FLAGS=HACK/COMMENT=Hack of the game. Include a cheat trainer.\r\nGG  040512ce 8B8D0340AF70E0A6   Lion King, The (Disney's) [Hack]/COUNTRY=EU/FLAGS=HACK/COMMENT=Hack of the game. Include a cheat trainer.\r\n\r\n; Homebrews\r\nGG  820ceb2c 30002377B9BF704E   Chaos/FLAGS=HOMEBREW/AUTHORS=Charles Doty (Raster) & Pickster\r\nGG  dbdb3a2e 707D62A152450079   Frog/FLAGS=HOMEBREW/VERSION=2/AUTHORS=Charles Doty\r\nGG  f366b29d 8A4C513A5DD6DD8F   Windows for the GG/FLAGS=HOMEBREW/VERSION=4/AUTHORS=Victor Klemp\r\n\r\n;-----------------------------------------------------------------------------\r\n; DATA - SEGA GAME 1000 (SG-1000)\r\n;-----------------------------------------------------------------------------\r\n\r\nSG1 16f240d3 E441860EAFF5455E   Adventure Island [DahJee]/COUNTRY=TW/PRODUCT_NO=GR-011/EMU_MAPPER=15\r\nSG1 d8a87095 BDE475C4465199F6   Bank Panic/COUNTRY=JP/PRODUCT_NO=C-53\r\nSG1 bd43fde4 BCE360F6644793CD   Bank Panic/COUNTRY=TW/PRODUCT_NO=R-053,A127\r\nSG1 26ecd094 4627CCD92099C86D   Black Onyx, The/COUNTRY=JP/PRODUCT_NO=C-72\r\nSG1 69fc1494 0C704C0920835C30   Bomberman Special/COUNTRY=TW/EMU_MAPPER=11\r\nSG1 ce5648c3 F3CD83E861CD4562   Bomberman Special [DahJee]/COUNTRY=TW/PRODUCT_NO=GR-009/EMU_MAPPER=15\r\nSG1 ea0f2691 0A34F046A94E1382   Bomb Jack/NAME_AU=Bombjack/COUNTRY=JP,AU/PRODUCT_NO=C-61\r\nSG1 0c69d837 4A34F046A94E1342   Bomb Jack [english logo]/COUNTRY=KR\r\nSG1 b0c7b310 AE79C52FBF35EE03   Bomb Jack [korean logo]/COUNTRY=KR\r\nSG1 deb213fe D2AEA738DA00CBFC   Bomb Jack [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-059\r\nSG1 cda3a335 A452AB39E32FFB19   Bomb Jack [english logo]/COUNTRY=TW/PRODUCT_NO=R-059\r\nSG1 0b4bca74 2AAE5B779DB522E2   Borderline/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1001\r\nSG1 9d91ab78 E46A59CC9B56AFED   Cabbage Patch Kids/COUNTRY=TW/PRODUCT_NO=R-104\r\nSG1 092f29d6 7314B489F3BDC5C7   Castle, The/COUNTRY=JP/PRODUCT_NO=G-1046/EMU_MAPPER=1/COMMENT=This cartridge contains a onboard 8 kb RAM chip.\r\nSG1 2e366ccf FD7C1D5E80B0805C   Castle, The [MSX]/COUNTRY=TW/PRODUCT_NO=Y-116/EMU_MAPPER=11\r\nSG1 d37bda49 F7646908C0727A88   Chack'n Pop/COUNTRY=JP,KR/PRODUCT_NO=C-52\r\nSG1 d81a72ce 5A6961FE08AF86A1   Chack'n Pop/COUNTRY=TW/PRODUCT_NO=R-060\r\nSG1 5970a12b B7E3FD4DBDC04758   Champion Baseball/COUNTRY=JP,AU,NZ/PRODUCT_NO=G-1011\r\nSG1 677e6878 CDD9E961B8BC4557   Champion Baseball/COUNTRY=TW/PRODUCT_NO=W-011\r\nSG1 c0c16fa7 967D926DF6349430   Champion Baseball [40k map]/COUNTRY=JP,AU,NZ/PRODUCT_NO=G-1011\r\nSG1 62b21e31 60DC69943898F205   Champion Billiards/COUNTRY=JP/PRODUCT_NO=C-71\r\nSG1 56d85bd4 C1E467AD4A66CFC8   Champion Billiards/COUNTRY=TW/PRODUCT_NO=R-069\r\nSG1 26f947d1 1FB7BB8E1123BAF3   Champion Boxing [v0]/COUNTRY=JP,NZ/PRODUCT_NO=G-1033\r\nSG1 15d2ce33 17BBBB8C1022BAFB   Champion Boxing [v0]/COUNTRY=TW/PRODUCT_NO=B-033\r\nSG1 f8b2ac1d 4123EF723DD41E0C   Champion Boxing [v1]/COUNTRY=JP/PRODUCT_NO=C-33\r\nSG1 868419b5 522DCE76FD2DC053   Champion Golf [v0]/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1005\r\nSG1 35af42ad 532DCE75FD2DC152   Champion Golf [v0]/COUNTRY=KR/PRODUCT_NO=G-35/COMMENT=Differ from original version by only 2 bytes which are likely an error in duplication.\r\nSG1 5a904122 A11DC05FF929AD54   Champion Golf [v1]/COUNTRY=JP/PRODUCT_NO=C-05\r\nSG1 bdc05652 7D6DE53955B78D5F   Champion Ice Hockey/COUNTRY=JP/PRODUCT_NO=C-59\r\nSG1 ec0b862c 7C6DEC3955B78D59   Champion Ice Hockey/COUNTRY=KR\r\nSG1 c6e5192f 7C6FFF4E64A18043   Champion Ice Hockey/COUNTRY=TW/PRODUCT_NO=R-061\r\nSG1 10cdebce 070357A3254C1774   Champion Kendou/COUNTRY=JP/PRODUCT_NO=C-67\r\nSG1 a5f61363 6422582843AB0B01   Champion Kendou/COUNTRY=TW/PRODUCT_NO=R-067\r\nSG1 372fe6bc A765C6DF45AA223E   Champion Pro Wrestling/COUNTRY=JP/PRODUCT_NO=G-1039\r\nSG1 7c663316 085A9DF0EF513B96   Champion Tennis/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1009\r\nSG1 11db4b1d FF5544CA075675CC   Championship Lode Runner/COUNTRY=JP,AU/PRODUCT_NO=C-57\r\nSMS 66b3b792 B79A469F13165849   Championship Lode Runner [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-057\r\nSG1 ec95ebcb 275B549D0D3C68DC   Championship Lode Runner [english logo]/COUNTRY=TW/PRODUCT_NO=R-057\r\nSG1 6f39719e 157515CDB5D2C746   Champion Soccer/COUNTRY=JP,EU/PRODUCT_NO=G-1034\r\nSG1 269c1aee 167215CEB4D1C947   Champion Soccer/COUNTRY=TW/PRODUCT_NO=W-034\r\nSG1 732b7180 308D125E31D34B84   Choplifter/COUNTRY=JP,AU/PRODUCT_NO=C-48\r\nSG1 954d8f26 708D125E31D34B44   Choplifter/COUNTRY=KR\r\nSG1 ff435469 279AD92023C895C6   Choplifter [Proto]/FLAGS=PROTO/COUNTRY=JP/VERSION=V-613/COMMENT=Prototype version of the game. Labelled V-613.\r\nSG1 746a8d86 06CFAC5C5DC358AB   Choplifter [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-048\r\nSG1 7c603987 8698F9446FC25321   Choplifter [english logo]/COUNTRY=TW/PRODUCT_NO=R-048\r\nSG1 825e1aae 358B115E31D14B84   Choplifter [no logo]/COUNTRY=TW/PRODUCT_NO=R-048\r\nSG1 7f7f009d AEDD97A20D8D1C86   Circus Charlie/COUNTRY=KR\r\nSG1 3404fce4 CB3C7627E57DF208   Circus Charlie/COUNTRY=TW/PRODUCT_NO=R-112\r\nSG1 5eb48a20 330FD0ED616A41F5   Congo Bongo [v0]/COUNTRY=JP/PRODUCT_NO=G-1007\r\nSG1 5a24c7cf 5BF7BDD18D354618   Congo Bongo [v1]/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1007\r\nSG1 f7eb94c5 63F9B8CE8D344617   Congo Bongo [v1]/COUNTRY=TW/PRODUCT_NO=B-007,A103\r\nSG1 f1506565 8E4A6C26BE92EA5C   Congo Bongo [v1] [40k map]/COUNTRY=JP,IT/PRODUCT_NO=G-1007\r\nSG1 be7ed0eb F6C4074F8EB7307B   C_So!/COUNTRY=JP/PRODUCT_NO=C-64\r\nSG1 82c4e3e5 43FDD850999A3233   C_So!/COUNTRY=TW/PRODUCT_NO=R-068\r\nSG1 346556b9 211D1B015A77D203   Doki Doki Penguin Land/COUNTRY=JP/PRODUCT_NO=C-50\r\nSG1 fdc095bc 987616376C42CC2B   Doki Doki Penguin Land/COUNTRY=TW/PRODUCT_NO=R-50\r\nSG1 60f30138 C299FED8BA801D78   Dragon Wang [v0]/COUNTRY=JP/PRODUCT_NO=C-46\r\nSG1 7c7d4397 AAA1D4DEFE65415F   Dragon Wang [v0] [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-046\r\nSG1 6f94e5c0 05B1D1C0046B0D3D   Dragon Wang [v0] [english logo]/COUNTRY=TW/PRODUCT_NO=R-046\r\nSG1 99c3de21 C2A4F2DAB27E1D81   Dragon Wang [v1]/COUNTRY=JP/PRODUCT_NO=C-46\r\nSG1 288940cb 546C1EFBFD7F5754   Drol/COUNTRY=JP,AU/PRODUCT_NO=C-51\r\nSG1 b7fc033d A0A7C8F3F6705147   Drol/COUNTRY=TW/PRODUCT_NO=R-051\r\nSG1 1d7c53bb B799D3F3F65E4C4A   Drol/COUNTRY=KR\r\nSG1 5af8f69d 0DE0E10D161A876E   Elevator Action/COUNTRY=JP,KR/PRODUCT_NO=C-55,G-27\r\nSG1 6846e36d BFBFF8DE289C6D7B   Elevator Action/COUNTRY=TW/PRODUCT_NO=R-055\r\nSG1 a2c45b61 4F4C5CAA21C5A8D1   Exerion/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1028\r\nSG1 b5c84a32 7A6A2EA31EBDA7C9   Exerion/COUNTRY=TW/PRODUCT_NO=W-028\r\nSG1 fc628d0d 7A435147DD03AD1E   Exerion/COUNTRY=KR\r\nSG1 bd24d27b E3234655B4D74292   Flicky [v0]/COUNTRY=JP,NZ/PRODUCT_NO=G-1036\r\nSG1 26d2862c FCBF8AD69A8C9A25   Flicky [v1]/COUNTRY=JP/PRODUCT_NO=G-1036\r\nSG1 cd0666a7 04B88ADA988B9924   Flicky [v1]/COUNTRY=TW/PRODUCT_NO=B-036\r\nSG1 1898f274 38DCD62C5EFD0C83   Girl's Garden/COUNTRY=JP/PRODUCT_NO=G-1037\r\nSG1 b9635ac4 A6D3D11150F5EE72   Girl's Garden/COUNTRY=TW/PRODUCT_NO=B-037\r\nSG1 0d159ed0 1B5A61BF9994C579   Golgo 13/COUNTRY=JP/PRODUCT_NO=G-1014\r\nSG1 40414556 3608A3EF977E8992   The Goonies/COUNTRY=TW/PRODUCT_NO=Y-105/EMU_MAPPER=15\r\nSG1 942adf84 273CD5E6FC69F08D   GP World [v0]/COUNTRY=JP,TW/PRODUCT_NO=G-1040,B-040\r\nSG1 f19f7548 525AA9E4F75EED85   GP World [v0]/COUNTRY=TW/PRODUCT_NO=B-040\r\nSG1 191ffe0a 9B2EAB302403AF86   GP World [v1]/COUNTRY=JP/PRODUCT_NO=G-1040\r\nSG1 15a754a3 CA8C9D9A871F7D50   Gulkave/COUNTRY=JP/PRODUCT_NO=C-63\r\nSG1 ddcb708b E38DA09D980A921F   Gulkave/COUNTRY=KR\r\nSG1 9be3c6bd 0EF416397D1321FE   Hang On II/COUNTRY=JP,AU,KR/PRODUCT_NO=C-60\r\nSG1 e98a111e 3CDD77312FBC1C38   Hang On II [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-062\r\nSG1 cabd451b 3E70D128CDFAFD95   Hang On II [english logo]/COUNTRY=TW/PRODUCT_NO=R-062\r\nSG1 4587de6e 9E321231AEEF54FC   H.E.R.O./COUNTRY=JP,KR/PRODUCT_NO=C-58\r\nSG1 83958998 E8319012A9AD529D   H.E.R.O. [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-058\r\nSG1 96f09c6d B98F1E14BEDE38B2   H.E.R.O. [english logo]/COUNTRY=TW/PRODUCT_NO=R-058\r\nSG1 c9d1ae7d D3797FAB2A3885A3   Home Mahjong [v0]/COUNTRY=JP/PRODUCT_NO=G-1030\r\nSG1 e7e0f0e3 DA7481AF2A3B8697   Home Mahjong [v1]/COUNTRY=JP/PRODUCT_NO=G-1030B\r\nSG1 0583a9fa 055A61EF00086BDE   Home Mahjong [v1]/COUNTRY=TW/PRODUCT_NO=R-030\r\nSG1 a627d440 6F16109C70F21E4F   Hustle Chumy/COUNTRY=JP,KR/PRODUCT_NO=G-1035\r\nSG1 c4ed1fd9 751D089B6FF01E4E   Hustle Chumy/COUNTRY=TW/PRODUCT_NO=W-035\r\nSG1 ba09a0fd 0CBF98A750BA42AA   Hyper Sports (Konami no)/COUNTRY=JP/PRODUCT_NO=G-1042\r\nSG1 87619ac2 75BA6C982FB62DBB   Hyper Sports (Konami no)/COUNTRY=TW/PRODUCT_NO=B-042\r\nSG1 3157ef9c 0EBF98A650BA42A9   Hyper Sports (Konami no)/COUNTRY=KR\r\nSG1 b0234e12 B2D25BCCB8450D4B   Hyper Sports 2/COUNTRY=TW/PRODUCT_NO=R-101\r\nSG1 223397a1 6BD893BB21816469   King's Valley/COUNTRY=TW/PRODUCT_NO=Y-106/EMU_MAPPER=15\r\nSG1 281d2888 8B8392B8E4A927F4   Knightmare [Jumbo]/COUNTRY=TW/PRODUCT_NO=GB-001/EMU_MAPPER=15\r\nSG1 2e7166d5 4EE0236CA39F45BC   Legend of Kage, The [DahJee]/COUNTRY=TW/PRODUCT_NO=GR-012/EMU_MAPPER=15\r\nSG1 00ed3970 7C7748E59B2DCE4A   Lode Runner/COUNTRY=JP,AU,EU,KR/PRODUCT_NO=G-1031\r\nSG1 e68bc7d6 BC7748E59B2DCE0A   Lode Runner/NAME_KR=Lode Runner I/COUNTRY=KR\r\nSG1 d953bdb7 A76C4BD89526CD42   Lode Runner/COUNTRY=TW/PRODUCT_NO=B-031\r\nSG1 3b912408 0D51374D3F55E6A4   Ninja Princess/COUNTRY=JP,AU/PRODUCT_NO=C-65\r\nSG1 464d144b 849462626E280985   Ninja Princess/COUNTRY=TW/PRODUCT_NO=R-065\r\nSG1 652bbd1e 5AACF5554AD6DCB4   N-Sub/COUNTRY=JP,AU,NZ,EU,TW/PRODUCT_NO=G-1003,W-003\r\nSG1 3e371769 78A8E95146D2DCB2   N-Sub/COUNTRY=TW/PRODUCT_NO=W-003\r\nSG1 b377d6e1 1A853CAEBF1FE1B8   N-Sub [40k map]/COUNTRY=JP/PRODUCT_NO=G-1003\r\nSG1 09196fc5 5CACF5534AD6DCB4   N-Sub [1988]/COUNTRY=EU/PRODUCT_NO=G-1003/COMMENT=This version has the date modified to 1988. The exact origin of this modification is unknown.\r\nSG1 ffc4ee3f 08273161CCB87E3D   Magical Kid Wiz/COUNTRY=TW/PRODUCT_NO=Y-115/EMU_MAPPER=11\r\nSG1 b3a8291a F64058B36B48B755   Magical Tree/COUNTRY=TW/PRODUCT_NO=R-102\r\nSG1 1c137cab A2DA2FADF50BA404   Mahjong [big 1983]/COUNTRY=JP/PRODUCT_NO=G-1004//COMMENT=Title screen with big \"1983\" version. Also referred to as \"Sega Mahjong\" on title screen.\r\nSG1 6d909857 254B7166E51F15A0   Mahjong [small 1983]/COUNTRY=JP/PRODUCT_NO=G-1004/COMMENT=Title screen with small \"1983\" version. Also referred to as \"Sega Mahjong\" on title screen.\r\nSG1 bc823a89 133E6158D913C743   Mahjong/COUNTRY=TW/PRODUCT_NO=B-004\r\nSG1 8572d73a 81E3163950C1F745   Monaco GP [24k] [v0] [40k map]/COUNTRY=JP,NZ,AU/PRODUCT_NO=G-1017/COMMENT=The 24KB ROM version of the game include a simplified title screen logo in text form. File size is 40KB because of the memory mapping arrangement, but only 24 KB are valid data.  ; [EDITOR NOTE] Unsure which country has which version exactly.\r\nSG1 da2d57f3 E7A6DEA71E6978EF   Monaco GP [32k] [v1]/COUNTRY=JP,KR/PRODUCT_NO=C-17,G-1017/COMMENT=The 32KB ROM version of the game include a decorated title screen logo.\r\nSG1 01cda679 E6A6DEA71E6979EF   Monaco GP [32k] [v1]/COUNTRY=TW/PRODUCT_NO=B-017,A116\r\nSG1 02e5d66a F9B0E3B61F7E8E93   Monaco GP [32k] [v2]/COUNTRY=JP/PRODUCT_NO=G-1017/COMMENT=The 32KB ROM version of the game include a decorated title screen logo.\r\nSG1 f4f78b76 466EC65A2B946EFF   Orguss/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1015\r\nSG1 4573f5bc 73C4750871602B50   Orguss/COUNTRY=TW/PRODUCT_NO=R-050/COMMENT=All Taiwanese version seems to be incorrectly using \"Doki Doki Penguin Land\" label and product number.\r\nSG1 af4f14bc FC9BB64B14BEE9AD   Othello/COUNTRY=JP/PRODUCT_NO=G-1044/EMU_MAPPER=1/COMMENT=This cartridge contains an onboard 2 kb RAM chip.\r\nSG1 1d1a0ca3 3ED8AE4924C6DC2D   Othello/COUNTRY=TW/PRODUCT_NO=R-044/EMU_MAPPER=1/COMMENT=This cartridge contains an onboard 2 kb RAM chip.\r\nSG1 30c52e5e A61DC848154BD1FC   Pacar/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1020\r\nSG1 19949375 EB44793290BD29B0   Pacar [40k map]/COUNTRY=JP/PRODUCT_NO=G-1020\r\nSG1 dd6817a0 AC11DD39154BD1FC   Pacar/COUNTRY=TW/PRODUCT_NO=W-020\r\nSG1 326587e1 04B80C5894E4A0C8   Pachinko/COUNTRY=JP/PRODUCT_NO=G-1027\r\nSG1 fd7cb50a 012054B9AACC5804   Pachinko II/COUNTRY=JP/PRODUCT_NO=G-1029\r\nSG1 6ebe81bf 0F1E52B6A8C95604   Pachinko II/COUNTRY=TW/PRODUCT_NO=W-029\r\nSG1 89710330 5BC86654F269A523   Pac-Man [DahJee]/COUNTRY=TW/PRODUCT_NO=GB-007/EMU_MAPPER=15\r\nSG1 4d972a9e 951C18D2067E667B   Ping Pong (Konami's)/COUNTRY=TW/PRODUCT_NO=R-108\r\nSG1 df7cbfa5 274A9CF385BE3F7E   Pippols [Jumbo]/COUNTRY=TW/PRODUCT_NO=GB-002/EMU_MAPPER=15\r\nSG1 37fca2eb 985694ED9B8C4B1F   Pitfall II ~The Lost Caverns~ [v0]/COUNTRY=JP/PRODUCT_NO=C-49/EMU_SPRITE_FLICKER\r\nSG1 476a079b F1A05ADE97813EE1   Pitfall II ~The Lost Caverns~ [v0] [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-049\r\nSG1 4e93bc8e D17E5CE493824319   Pitfall II ~The Lost Caverns~ [v0] [english logo]/COUNTRY=TW/PRODUCT_NO=R-049,A135\r\nSG1 3db74761 975C771A81914D1D   Pitfall II ~The Lost Caverns~ [v1]/COUNTRY=JP/PRODUCT_NO=C-49/EMU_SPRITE_FLICKER/COMMENT=Alternate color version, some objects palettes were changed to be more visible using the Mark III \\/ Master System hardware palette.\r\nSG1 db6404ba 0E3BEA9E54820158   Pop Flamer/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1019\r\nSG1 ab1da8a6 1039E99A5682025A   Pop Flamer/COUNTRY=TW/PRODUCT_NO=W-019\r\nSG1 aaac12cf 6A56F912321AA247   Rally-X/COUNTRY=TW/EMU_MAPPER=11\r\nSG1 306d5f78 5E4EB6CE2E586BDF   Rally-X [DahJee]/COUNTRY=TW/PRODUCT_NO=GR-010/EMU_MAPPER=15\r\nSG1 d2edd329 5FA46F5D98C826AB   Road Fighter/COUNTRY=TW/EMU_MAPPER=11\r\nSG1 29e047cc 8659FFAB0FA7A31E   Road Fighter [Jumbo]/COUNTRY=TW/PRODUCT_NO=GB-004/EMU_MAPPER=15\r\nSG1 0ffdd03d 44B2C607937091A9   Rock n' Bolt/COUNTRY=JP/PRODUCT_NO=C-54/EMU_SPRITE_FLICKER\r\nSG1 4eacb981 EFBBB239D75DBC7B   Rock n' Bolt [chinese logo]/COUNTRY=TW/PRODUCT_NO=R-054/EMU_SPRITE_FLICKER\r\nSG1 09a82af7 68B5AB06AE5CC167   Rock n' Bolt [english logo]/COUNTRY=TW/PRODUCT_NO=R-054/EMU_SPRITE_FLICKER\r\nSG1 49e9718b C5114D3DD002F2DC   Safari Hunting/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1002\r\nSG1 6dc51c01 CC1C4537D000F2DA   Safari Hunting/COUNTRY=TW/PRODUCT_NO=W-002\r\nSG1 08707fe3 7DEF5FABA2C8F22E   Safari Race/COUNTRY=JP,KR,AU,NZ,EU/PRODUCT_NO=G-1032,G-11\r\nSG1 b2724428 85F25AAAA0C7F12D   Safari Race/COUNTRY=TW/PRODUCT_NO=B-032\r\nSG1 619dd066 6CED5FAB9EC9F343   Safari Race [1988]/COUNTRY=EU/COMMENT=This version has the date modified to 1988. The exact origin of this modification is unknown.\r\nSG1 8efc77bc 5C5A333AD02831B4   Sega Flipper/NAME_NZ=Video Flipper/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1018\r\nSG1 042c36ba 83621A36CC232CB0   Sega Flipper/COUNTRY=TW/PRODUCT_NO=W-018\r\nSG1 fd76ad99 62DDADADD3FD1C7B   Sega Flipper [40k map]/COUNTRY=JP/PRODUCT_NO=G-1018\r\nSG1 981e36c1 4C8C69BF8C6621ED   Sega-Galaga/COUNTRY=JP,AU/PRODUCT_NO=G-1022\r\nSG1 845bbb22 B36EA2B0694902D9   Sega-Galaga/COUNTRY=TW/PRODUCT_NO=W-022\r\nSG1 31283003 6B2F612B648C8565   Sega-Galaga [40k map]/COUNTRY=JP/PRODUCT_NO=G-1022\r\nSG1 545fc9bb 9FAB5418930F2484   Serizawa Hachidan no Tsumeshogi/COUNTRY=JP/PRODUCT_NO=G-1006/COMMENT=Also referred to as \"Tsumeshogi\" (box shows both the full and short titles).\r\nSG1 207e7e99 82EFE91D633108ED   SG-1000 M2 Check Program [Proto]/COUNTRY=JP/FLAGS=PROTO\r\nSG1 5a917e06 012791545F90CD37   Shinnyuushain Tooru-Kun (Konami no)/COUNTRY=JP/PRODUCT_NO=G-1041\r\nSG1 33fc5cf6 3A138D505885CA2F   Shinnyuushain Tooru Kun (Konami no)/COUNTRY=TW/PRODUCT_NO=B-041,A121\r\nSG1 01932df9 39B539F98CD283FF   Sindbad Mystery/COUNTRY=JP,AU,NZ,EU,KR/PRODUCT_NO=G-1012\r\nSG1 945f7847 96A819F06AD081FE   Sindbad Mystery/COUNTRY=TW/PRODUCT_NO=B-012\r\nSG1 922c5468 37CC1C413181F4FA   Soukoban/NAME_AU=Thinking Rabbit/COUNTRY=JP,AU/PRODUCT_NO=C-56/COMMENT=Also known as \"Thinking Rabbit\" in bootleg form. Pirates mistakenly choose this name because it is the only latin-readable text shown on the title screen, but it is the developer's name.\r\nSG1 a2c3fc97 64CB012C4C6EF4F6   Soukoban/COUNTRY=TW/PRODUCT_NO=R-056\r\nSG1 148ea752 3ACB0F392B6B31EC   Soukoban/COUNTRY=KR\r\nSG1 89bafec5 81457EFD7250906D   Soukoban [IQ logo]/COUNTRY=KR/PRODUCT_NO=G-36\r\nSG1 6ad5cb3d 832D295F5C58E72D   Space Invaders/COUNTRY=JP/PRODUCT_NO=G-1045\r\nSG1 0760ea93 832D29605C57E72D   Space Invaders/COUNTRY=TW/PRODUCT_NO=W-045\r\nSG1 b8b58b30 8E2F02DC58C51E2A   Space Slalom/COUNTRY=JP/PRODUCT_NO=G-1023\r\nSG1 b846b52a BE0870060DA1B462   Star Force/COUNTRY=JP,AU/PRODUCT_NO=G-1043,C-43\r\nSG1 1f736931 F22542030695B059   Star Force [A]/COUNTRY=TW/PRODUCT_NO=B-043\r\nSG1 6f9b1ccd EC2542030896B15B   Star Force [B]/COUNTRY=TW/PRODUCT_NO=N\\/A\r\nSG1 2f4c8cad BF126E080C9FB25C   Star Force/COUNTRY=KR\r\nSG1 1ae94122 79C8686A8C7539B3   Star Jacker [v0]/COUNTRY=JP/PRODUCT_NO=G-1010\r\nSG1 7f25deca 4614717ECAA82D18   Star Jacker [v1]/COUNTRY=JP,AU,NZ,EU/PRODUCT_NO=G-1010\r\nSG1 df162201 4E12707CC9A72C18   Star Jacker [v1]/COUNTRY=TW/PRODUCT_NO=B-010\r\nSG1 3fe59505 4614717ECAA82D18   Star Jacker [v2]/COUNTRY=JP,EU/PRODUCT_NO=G-1010\r\nSG1 e0816bb7 8C0D518BC539701D   Star Soldier [DahJee]/COUNTRY=TW/PRODUCT_NO=GA006/EMU_MAPPER=15\r\nSG1 084cc13e 05318ACB15C32F6E   Super Tank/COUNTRY=JP/PRODUCT_NO=C-66\r\nSG1 4c48b7ac 012387C913AD6D5F   Super Tank/COUNTRY=KR\r\nSG1 d0c3df3f FE4329CC1AAC42C2   Super Tank/COUNTRY=TW/PRODUCT_NO=R-066\r\nSG1 5cbd1163 9B0BF9E544D9A0BF   Tank Battalion [DahJee]/COUNTRY=TW/PRODUCT_NO=GR-014/EMU_MAPPER=15\r\nSG1 dd4a661b 830D8CF823BC2CE1   Terebi Oekaki/COUNTRY=JP/PRODUCT_NO=GB-800/EMU_INPUTS=TVOEKAKI/EMU_MAPPER=7\r\nSG1 c550b4f0 CD9116D2B1B1D880   TwinBee [Jumbo]/COUNTRY=TW/PRODUCT_NO=GB-003/EMU_MAPPER=15\r\nSG1 160535c5 D9D0ED81D45D08B0   Wonder Boy [v0]/COUNTRY=JP,AU/PRODUCT_NO=C-69\r\nSG1 e8f0344d 60AEE7ED6EDF1DB4   Wonder Boy [v1]/COUNTRY=JP/PRODUCT_NO=C-69\r\nSG1 953fc2b2 5AACE8048BDE1C89   Wonder Boy [v1]/COUNTRY=TW/PRODUCT_NO=R-070\r\nSG1 e2fd5201 0B6F31D372EC70B4   Yamato/NAME_KR=Doksuri Jeonham/COUNTRY=JP,AU,NZ,EU,KR/PRODUCT_NO=G-1008,SG33C\r\nSG1 9c7497ff 5339D4A226DFF108   Yamato [40k map]/COUNTRY=JP/PRODUCT_NO=G-1008\r\nSG1 b65a093f 62ECC4B953D967A2   Yamato/COUNTRY=TW/PRODUCT_NO=W-008\r\nSG1 bb0f1930 574798B4CFFB3517   Yie Ar Kung-Fu/COUNTRY=TW/PRODUCT_NO=R-103\r\nSG1 fc87463c 99538E695B7C0D39   Yie Ar Kung-Fu II [DahJee]/COUNTRY=TW/PRODUCT_NO=GA-008/EMU_MAPPER=15\r\nSG1 7c55057c 00489F9C32A19812   Zanac [DahJee]/COUNTRY=TW/PRODUCT_NO=GR-013/EMU_MAPPER=15\r\nSG1 905467e4 237439957A2DF103   Zaxxon/COUNTRY=JP,TW,KR/PRODUCT_NO=G-1038,B-038\r\nSG1 49cae925 2B773494792BF002   Zaxxon/COUNTRY=TW/PRODUCT_NO=B-038\r\nSG1 bc5d20df 1C80273C5B02376D   Zippy Race/COUNTRY=JP,AU/PRODUCT_NO=C-26,G-1026\r\nSG1 bcf441a5 3FA6213659FE1F4E   Zippy Race/COUNTRY=TW/PRODUCT_NO=B-026\r\nSG1 093830d8 93DD3B768470FCEF   Zoom 909/COUNTRY=JP/PRODUCT_NO=C-47\r\nSG1 9943fc2b 8C2C4196989F0C2E   Zoom 909/COUNTRY=TW/PRODUCT_NO=R-047\r\n\r\n; Bad dumps\r\nSG1 8201b53d 005544CB075676C9   Championship Lode Runner/COUNTRY=JP,AU/FLAGS=BAD/COMMENT=2 bad bytes.\r\nSG1 dc4383cc 5BF7BDD18D354618   Congo Bongo [v1] [Overdump]/COUNTRY=JP,AU,NZ,EU/FLAGS=BAD/PRODUCT_NO=G-1007/COMMENT=Overdump, padded with 00.\r\nSG1 b09e2e6d 5BF7BDD18D354618   Congo Bongo [v1] [Overdump]/COUNTRY=JP,AU,NZ,EU/FLAGS=BAD/PRODUCT_NO=G-1007/COMMENT=Overdump, padded with FF.\r\nSG1 d4c8c6d7 E3234656B5D7438F   Flicky/FLAGS=BAD/COUNTRY=JP/COMMENT=3 bad bytes.\r\nSG1 4831210b A9EF65B1A5C8F7EE   Safari Race/FLAGS=BAD\r\nSG1 54d5bec3 3AB53AF88CD283FE   Sindbad Mystery/FLAGS=BAD/COUNTRY=JP,AU,NZ,EU/COMMENT=1 bad byte.\r\nSG1 72542786 B4242BD5DE3E2CE0   Monaco GP [24k]/FLAGS=BAD/COUNTRY=JP,AU,NZ,EU/COMMENT=Middle unused 16k memory region contains data from Safari Hunting.\r\n\r\n; Homebrews\r\nSG1 b1cbec5a 781CA0E7EF3207BD   S_sniper/FLAGS=HOMEBREW/AUTHORS=Maechiko\r\nSG1 56abc493 BA07B1875BCCF2EE   Omikuji/FLAGS=HOMEBREW/AUTHORS=Maechiko\r\n\r\n;-----------------------------------------------------------------------------\r\n; DATA - SEGA COMPUTER 3000 (SC-3000)\r\n;-----------------------------------------------------------------------------\r\n\r\nSC3 58e40603 B10E843B4BCF6008   AutoCom [Build 3] [v1.1c] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0460/FLAGS=PROTO\r\nSC3 9e3cd6aa 896B913FF09CC4EC   AutoCom [Build 4] [v1.1c] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0460/FLAGS=PROTO\r\nSC3 f414ef13 6FB7909683131509   AutoCom [Build 5] [v1.1c] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0460/FLAGS=PROTO\r\nSC3 50548508 5B9C9F8BCE28BC2D   AutoCom [Build 6] [v2.0c] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0460/FLAGS=PROTO\r\nSC3 b04144b2 E696937ADBE46652   AutoCom [Build 7] [v2.0c] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0460/FLAGS=PROTO\r\nSC3 cc905af0 FBFECD896F4B31C6   AutoCom [Build 8] [v2.0(T)c] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0460/FLAGS=PROTO\r\nSC3 f691f9c7 A498D750D50A8638   Basic Level II [v1.0] /COUNTRY=JP/PRODUCT_NO=B-10/EMU_MAPPER=1\r\nSC3 cdf7bdf3 B2B7D236E23087F6   Basic Level II [v1.0b]/COUNTRY=JP/PRODUCT_NO=B-10/EMU_MAPPER=1\r\nSC3 b7ec1307 DF5AC95DDE23851B   Basic Level II [v1.0] [PAL]/COUNTRY=NZ/PRODUCT_NO=B-10/EMU_MAPPER=1\r\nSC3 a46e3c73 EE421209CF077A65   Basic Level III [v1.0]/COUNTRY=JP/PRODUCT_NO=B-30/EMU_MAPPER=1\r\nSC3 55f47493 0061FB18D417772A   Basic Level III [v1.1]/COUNTRY=JP/PRODUCT_NO=B-30,B-40,B-41/EMU_MAPPER=1/COMMENT=Level III A, Level III B and SK III use same ROM data. \r\nSC3 5d9f11ca 242CE123F9157D21   Basic Level III [v1.0] [PAL]/COUNTRY=EU,AU,NZ/PRODUCT_NO=B-30,B-40/EMU_MAPPER=1/COMMENT=Level III A and Level III use same ROM data.\r\nSC3 345c8bc8 CD315B439CEE36A4   Chuugaku Hisshuu Eibunpou (Chuugaku 1-Nen)/COUNTRY=JP/PRODUCT_NO=E-105/COMMENT=Educational Software: English Grammar (Junior High School 1st year)\r\nSC3 d4c473b2 577B6DD9FD8F2D2F   Chuugaku Hisshuu Eibunpou (Chuugaku 2-Nen)/COUNTRY=JP/PRODUCT_NO=E-112/COMMENT=Educational Software: English Grammar (Junior High School 2nd year)\r\nSC3 9bafd9e9 F9010E587DA5BFBF   Chuugaku Hisshuu Eisakubun (Chuugaku 1-Nen)/COUNTRY=JP/PRODUCT_NO=E-104/EMU_MAPPER=5/COMMENT=Educational software: English Composition (Junior High School 1st year)\r\nSC3 975106b6 8C043060FC8CF464   Chuugaku Hisshuu Eisakubun (Chuugaku 1-Nen) [40k map]/COUNTRY=JP/PRODUCT_NO=E-104/EMU_MAPPER=5/COMMENT=Educational software: English Composition (Junior High School 1st year)\r\nSC3 581dce41 F4F5FC7EF064F356   Chuugaku Hisshuu Eisakubun (Chuugaku 2-Nen)/COUNTRY=JP/PRODUCT_NO=E-111/COMMENT=Educational Software: English Composition (Junior High School 2nd year)\r\nSC3 3657b285 DAD462F244A8040E   Chuugaku Hisshuu Eisakubun (Chuugaku 2-Nen) [40k map]/COUNTRY=JP/PRODUCT_NO=E-111/COMMENT=Educational Software: English Composition (Junior High School 2nd year)\r\nSC3 6ccb297a ECF917D715120BFB   Chuugaku Hisshuu Eitango (Chuugaku 1-Nen)/COUNTRY=JP/PRODUCT_NO=E-103/COMMENT=Educational software: English Vocabulary (Junior High School 1st year)\r\nSC3 8507216b 86502CA2E84C8E9A   Chuugaku Hisshuu Eitango (Chuugaku 2-Nen)/COUNTRY=JP/PRODUCT_NO=E-110/COMMENT=Educational Software: English Vocabulary (Junior High School 2nd year)\r\nSC3 4f599483 3E22B4565C6E1EAE   Chuugaku Hisshuu Eitango (Chuugaku 2-Nen) [40k map]/COUNTRY=JP/PRODUCT_NO=E-110/COMMENT=Educational Software: English Vocabulary (Junior High School 2nd year)\r\nSC3 78a37cbc 0C8784F17E89F5FC   Home Basic/COUNTRY=JP/PRODUCT_NO=B-50/EMU_MAPPER=1\r\nSC3 f9c81fe1 F2544D2C76A5988E   Kagaku (Gensokigou Master)/COUNTRY=JP/PRODUCT_NO=E-107/COMMENT=Educational Software: Chemistry (Chemical Symbols Master)\r\nSC3 129d6359 DE9469099090EC10   Nihonshi Nenpyou/COUNTRY=JP/PRODUCT_NO=E-108/COMMENT=COMMENT=Educational Software: Japanese History Chronology\r\nSC3 2ec28526 92CFAC110866B4C0   Music/COUNTRY=JP/PRODUCT_NO=E-101/EMU_MAPPER=1\r\nSC3 622010e1 F363D14ADA372658   Music/COUNTRY=AU,NZ,EU/PRODUCT_NO=E-101/EMU_MAPPER=1\r\nSC3 3274ee48 3EA1F4B0ED61240B   Sekaishi Nenpyou/COUNTRY=JP/PRODUCT_NO=E-109/COMMENT=Educational Software: World History Chronology\r\nSC3 6fc61f24 8FE363BCA1155F5A   SegaCom [Build 0] [Proto]/COUNTRY=AU/PRODUCT_NO=SC0430/FLAGS=PROTO\r\nSC3 0b175710 96E87AA3A81B5949   SegaCom [Build 1] [v1.0c]/COUNTRY=AU/PRODUCT_NO=SC0430\r\nSC3 819d0252 AA32B2A4F9BE9780   SegaCom [Build 2] [v1.1c]/COUNTRY=AU/PRODUCT_NO=SC0430\r\nSC3 5fde25bb 268DB0683B8EBBB1   Tanoshii Sansuu (Shougaku 4-Nen Ge)/COUNTRY=JP/PRODUCT_NO=E-113/COMMENT=Educational Software: Arithmetic (Elementary School 4th year Vol. 2)\r\nSC3 573e04dd 5CE3033D4B895855   Tanoshii Sansuu (Shougaku 4-Nen Jou)/COUNTRY=JP/PRODUCT_NO=E-106/COMMENT=Educational Software: Arithmetic (Elementary School 4th year Vol. 1)\r\nSC3 7c400e3b AA10A654A612E6AE   Tanoshii Sansuu (Shougaku 4-Nen Jou) [40k map]/COUNTRY=JP/PRODUCT_NO=E-106/COMMENT=Educational Software: Arithmetic (Elementary School 4th year Vol. 1)\r\nSC3 6a96978d 933EBD35FDA0326E   Tanoshii Sansuu (Shougaku 5-Nen Ge)/COUNTRY=JP/PRODUCT_NO=E-114/COMMENT=Educational Software: Arithmetic (Elementary School 5th year Vol. 2)\r\nSC3 419d75d5 84E40A994C53C492   Tanoshii Sansuu (Shougaku 5-Nen Jou)/COUNTRY=JP/PRODUCT_NO=E-116/COMMENT=Educational Software: Arithmetic (Elementary School 6th year Vol. 1)\r\nSC3 d0d18e70 27D1FABE8F6A87D0   Tanoshii Sansuu (Shougaku 6-Nen Ge)/COUNTRY=JP/PRODUCT_NO=E-115/COMMENT=Educational Software: Arithmetic (Elementary School 6th year Vol. 2)\r\nSC3 8b5e6e1b 46397F7619AA3990   Tanoshii Sansuu (Shougaku 6-Nen Jou)/COUNTRY=JP/PRODUCT_NO=E-117/COMMENT=Educational Software: Arithmetic (Elementary School 6th year Vol. 1)\r\nSC3 ae4f92cf 1916AF8D8DF9E52A   Uranai Angel Cutie/COUNTRY=JP/PRODUCT_NO=E-119\r\n\r\n; Bad Dumps\r\nSC3 155fd01f 242CE122F9157C23   Basic Level III [v1.0] [PAL]/FLAGS=BAD/COMMENT=1 bad byte. Auto patched.\r\nSC3 6aa0279d 0261FB18D318752A   Basic Level III [v1.1]/FLAGS=BAD/EMU_MAPPER=1/COMMENT=Two bad bytes. Auto-patched.\r\nSC3 22f4f92a BB95690B9391EC2C   Nihonshi Nenpyou/FLAGS=BAD/PRODUCT_NO=E-108/COMMENT=COMMENT=Educational Software: Japanese History Chronology\r\nSC3 b67ea1c4 F563D149DA372558   Music/COUNTRY=AU,NZ,EU/FLAGS=BAD/PRODUCT_NO=E-101/EMU_MAPPER=1/COMMENT=1 bad byte. Fixed.\r\n\r\n;-----------------------------------------------------------------------------\r\n; DATA - SEGA SUPER CONTROL STATION (SF-7000)\r\n;-----------------------------------------------------------------------------\r\n\r\nSF7 ad19c0a0 A55FE3E37F6681D0   Complete Arcade Pack Collection, The/COUNTRY=NZ\r\nSF7 5aeee6ee 134342342A7B424D   HuCAL\r\nSF7 a7b1da17 1787122D7B8052D6   Sega Logo v1.0e\r\n\r\n;-----------------------------------------------------------------------------\r\n; DATA - OTHELLO MULTIVISION (OMV)\r\n;-----------------------------------------------------------------------------\r\n\r\nOMV a8b5b57f BCD11989FBA90F1E   007 James Bond [v2.6] [40k map]/COUNTRY=JP/VERSION=2.6/PRODUCT_NO=OM-G008\r\nOMV 90160849 511AFC9B86848A6A   007 James Bond [v2.7]/COUNTRY=JP/VERSION=2.7/PRODUCT_NO=OM-G008\r\nOMV 76d6c64d 501DFC9B82848D69   007 James Bond [v2.7]/COUNTRY=TW/PRODUCT_NO=W-009\r\nOMV c91551da 6ECC9480122FEA87   Challenge Derby [A]/COUNTRY=JP/PRODUCT_NO=OM-G005\r\nSG1 02bc891f AA094B0ED7E79A9C   Challenge Derby [A] [40k map]/COUNTRY=JP/PRODUCT_NO=OM-G005\r\nOMV c5f014dc F92E3438A5D4569E   Challenge Derby [B] [40k map]/COUNTRY=JP/PRODUCT_NO=OM-G005\r\nOMV 61fa9ea0 33335D5204BB9D8F   Guzzler/COUNTRY=JP/PRODUCT_NO=OM-G002\r\nOMV eb808158 206A757920D7DCB5   Guzzler/COUNTRY=TW/PRODUCT_NO=W-006\r\nOMV 547dd7fd 250D4ABC368057BB   Okamoto Ayako no Match Play Golf [A]/COUNTRY=JP/PRODUCT_NO=OM-G006 ; [EDITOR NOTE] : labelled A/B based on the fact that B has more code than A. Unsure of the exact differences.\r\nOMV 49d3db2c 25724877DA819DB2   Okamoto Ayako no Match Play Golf [B]/COUNTRY=JP/PRODUCT_NO=OM-G006\r\nOMV b60492d5 26714877DA819DB2   Okamoto Ayako no Match Play Golf [B]/COUNTRY=TW/PRODUCT_NO=B-021\r\nOMV 77db4704 5B068CAB72E35CB7   Q*bert/COUNTRY=JP/PRODUCT_NO=OM-G001\r\nOMV 885fa64d 32C4026057CD592B   San-nin Mahjong/COUNTRY=JP/PRODUCT_NO=OM-G004\r\nOMV 6fd17655 14C2FF9659CC5C14   San-nin Mahjong/COUNTRY=TW/PRODUCT_NO=W-013\r\nOMV 0e641f36 A86A3F948077CF55   San-nin Mahjong [40k map]/COUNTRY=JP/PRODUCT_NO=OM-G004A\r\nOMV d23b0e3e 4D8CE1A95FD56FFA   Space Armor [v10] [v0] [40k map]/COUNTRY=JP/PRODUCT_NO=OM-G007\r\nOMV d5fdb4a3 838699F2C256CA8A   Space Armor [v20] [v1]/COUNTRY=JP,TW/PRODUCT_NO=OM-G007,W-016\r\nOMV 9b661d04 4E0E70ECB54EC184   Space Armor [v20] [v1]/COUNTRY=TW/PRODUCT_NO=W-016\r\nOMV ac4f0a5c 4CA7AF13C260F633   Space Armor [v20] [v2]/COUNTRY=JP/PRODUCT_NO=OM-G007\r\nOMV bbd87d8f DD4EE8250BFB259D   Space Mountain/COUNTRY=JP/PRODUCT_NO=OM-G003A,OM-G004\r\nOMV c5a67b95 5B5A6A24D5CE0B0F   Othello Multivision [BIOS]/COUNTRY=JP/FLAGS=BIOS\r\n\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n; OLD DATA (to be verified / sorted out before converting)\r\n;-----------------------------------------------------------------------------\r\n;-----------------------------------------------------------------------------\r\n\r\n---- MASTER SYSTEM BAD DUMPS ----\r\n9D9AD0FA4B7344FD,Alex Kidd in Miracle World,ID=G-1306,VER=Export,COMMENT=This dump will work but a byte is wrong. You might want to look for the good dump.\r\n7ACEE06A678FF682,Alex Kidd in Shinobi World,BAD,COMMENT=This dump will work but a byte is wrong. You might want to look for the good dump.\r\nE71464BFE1BB77CF,Alex Kidd: The Lost Stars,ID=G-1347,BAD\r\nEC1883774FF7FDBF,Astro Warrior,ID=G-1312,BAD\r\nFD9CB764170567C9,Castelo Rá-Tim-Bum,VER=Brazilian,BAD\r\n58AE94E16F8DD5B4,Enduro Racer,ID=G-1322,BAD\r\n914DC1AEAB372AA7,Fantastic Dizzy,Mapper=3,BAD,TVTYPE=PAL/SECAM\r\nCEDEE0CC40083030,Gokuaku Doumei Dump Matsumoto,VER=Japanese,ID=G-1302,COMMENT=Japanese version of Pro Wrestling. This dump is slighty incorrect.,BAD\r\n75BA56063B17C95A,Great Volleyball,ID=G-1317,VER=Export,BAD\r\n6E32F08336B0FA0D,Masters of Combat,BAD\r\n8363C47AA02D1DF2,Micro Machines,Mapper=3,BAD,TVTYPE=PAL/SECAM\r\n5EF11842A570D86A,Monopoly [A],COMMENT=The second half of this ROM is useless and can be safely removed.\r\nE11345F078025D00,Penguin Land,JAPNAME=Doki Doki Penguin Land,VER=Export,ID=G-1334,BAD\r\n910728C9B9AC1CF6,Pro Wrestling,BAD\r\n312F9C13C82FBE3C,Shadow Dancer,BAD\r\n87B23674DB921898,Strider,BAD\r\n4D6F1F46EEB2132C,Super Kick Off,BAD\r\n5286A12D022F2702,R-Type,ID=G-1364,BAD,COMMENT=This dump contains one bad byte. It will work but you might want to look for the good dump.\r\n7715F237A0952EE8,Wonder Boy in Monster Land,BAD\r\n\r\n---- SF-7000 ----\r\n8AFD7D1C2386B087,Crocky,BAD,VER=French,COMMENT=Floppy disk file allocation table is missing entrys for the game program.\r\n275F28FBF8ADCBE7,Kamikaze,VER=French,COMMENT=The original tape game was ported to a SF-7000 disk by Marc Le Douarain. It is known not to run properly in auto-boot mode so you first have to load the Disk Basic then boot Kamikaze from it.\r\n32505C23950676EE,Sega Disk Basic v1.0p,VER=1.0p,COMMENT=This is the original disk as provided with SF-7000 systems sold in France.\r\n04DDAC7564D37A4D,Sega Disk Basic v1.0p + Yeno Demo,VER=1.0p,COMMENT=This is the original disk to which was added a separately provided demonstration.\r\nB8077BB4C4963E7A,Poseidon Wars / Space Panic / Rambo,COMMENT=This disk contains three amators programs by Marc Le Douarain. Rambo is unfinished and so will not be playable past the title screen.,AUTHORS=Marc le Douarain\r\n2D2F639451F2C0AA,Yeno Draw [Face 1],AUTHORS=Marc le Douarain\r\nBE14C62C214ED2FB,Yeno Draw [Face 2],AUTHORS=Marc le Douarain\r\n\r\n---- GAME GEAR ----\r\n50513CEA88DD577D,Iron Man X-O Manowar in Heavy Metal,VER=USA  ; PRODUCT_NO=T-81398\r\nDFBD34655C7A6293,Wagan Land [A],ID=T-14047,VER=Japanese\r\nC7BD34655C7A62AB,Wagan Land [B],ID=T-14047,VER=Japanese\r\n\r\n---- GAME GEAR BAD DUMPS ----\r\n92CFF74D6DAEC57B,Bart vs. The World (The Simpsons),JAPNAME=Bart World,VER=International,BAD\r\n47D7D87C28BE3870,Chicago Syndicate,BAD\r\n1F888E6BA55ACB96,Griffin,BAD\r\n505B123BE8CD341F,Land of Illusion,BAD\r\nEE09D1B37475F6A6,PGA TOUR Golf II,VER=English,BAD\r\nFC1058B0D816D826,Predator 2,BAD\r\n9D6E278FAC1FEE86,R.B.I. Baseball '94,VER=English,BAD\r\n97403601CB2901FD,Sailor Moon S,ID=T-133017,VER=Japanese,BAD\r\n0278F5B6235484E0,Sonic Blast,BAD\r\nF7A0D2156165A21A,Sonic Blast,BAD\r\n2532BB34C10FBA30,Ultimate Soccer,BAD\r\n4AC066A25C14027C,World Series Baseball,VER=English,Mapper=4,BAD\r\n\r\n---- COLECO VISION ----\r\n36E08CEDA41FBBF3,2010 - The Graphic Action Game,DATE=1984\r\nF04C1831F731A5AE,Adam's Musicbox Demo,DATE=1987\r\nB84FC388F1E31EBC,Alcazar - The Forgotten Fortress,DATE=1985\r\nE58BBDF86F202428,Alphabet Zoo,DATE=1984\r\nEBEB109FE7FB6B2E,Amazing Bumpman,DATE=1986\r\n2B29847663943982,Antarctic Adventure (alt),DATE=1984\r\nF171BEB28CD46E60,Antarctic Adventure,DATE=1984\r\n631102E59B886F13,Aquattack,DATE=1984\r\n10F54BB38E577A9E,Artillery Duel,DATE=1983\r\n8BA52F31C2A57693,BC's Quest for Tires,DATE=1983\r\nEDD2795EF15B9886,BC's Quest for Tires II - Grog's Revenge (24k) (alt),DATE=1984\r\nC0704F70A3DF424D,BC's Quest for Tires II - Grog's Revenge (32k) (bad),DATE=1984\r\n34F411A6909EF4FF,BC's Quest for Tires II - Grog's Revenge (32k),DATE=1984\r\n7C535948CDC450AF,Beamrider,DATE=1983\r\nBD8519D1474BB092,Blockade Runner,DATE=1984\r\n55CE5522544806C4,Boulder Dash,DATE=1984\r\n3F6A16DABB021E8C,Brain Strainers,DATE=1984\r\n4B29DE86674CC8AD,Bump 'N' Jump,DATE=1982-84\r\nA97BBBEA5ABEFD22,Bump 'N' Jump (Mattel),DATE=1982-84\r\n71872823FB082C8E,BurgerTime (Mattel),DATE=1982-83\r\n6021C2B1A1797F73,BurgerTime,DATE=1982-84\r\n32B90C82E73B8FD6,Cabbage Patch Kids - Adventures in the Park (alt),DATE=1983-84\r\n1C4D93DC1E94EA8C,Cabbage Patch Kids - Adventures in the Park,DATE=1983-84\r\n666F9F113565548D,Cabbage Patch Kids Picture Show,DATE=1984\r\n33795675FF0C7C02,Campaign '84,DATE=1983\r\n156689CF758BF23B,Carnival,DATE=1982\r\n4B482412AD424701,Centipede,DATE=1983\r\n218412D27961AEEF,Choplifter,DATE=1982-84\r\n1E8412D37961AEF1,Choplifter (alt),DATE=1982-84\r\nCACE62C2877C6CD5,Chuck Norris - Super Kicks,DATE=1983\r\nB4393EAB78B73CBF,Coleco Vision BIOS (different font),DATE=1982\r\nF60E5F2FE8CBBA01,Coleco Vision BIOS (no title delay),DATE=1982\r\nF20F5F30E8CCBB01,Coleco Vision BIOS (original),DATE=1982\r\n64D45120BD7083A7,Coleco Vision Noise Generator,COMMENT=Public Domain.,DATE=1996\r\nC28F7C08B831A1A1,Congo Bongo,DATE=1984\r\n28C77AC3E23CD3E3,Cosmic Avenger (alt),DATE=1982\r\n26C77AC3E23CD3E5,Cosmic Avenger,DATE=1982\r\n72679E2CC3743CEA,Cosmic Crisis,DATE=1983\r\n5A5B3BB6F64E17FF,Cosmo Fighter 2,DATE=1996-97,COMMENT=Public Domain\\, by Marcel de Kogel.\r\nC0BC2014250F1606,Dam Busters (The),DATE=1984\r\n716B8625360F53E1,Dance Fantasy,DATE=1984\r\n0BE2C0CCB77E3E14,Defender,DATE=1980-83\r\nACF9C3A3B1AA9802,Destructor,DATE=1984\r\nC16A5CA79189D1E7,Dig Dug [Proto],PROTO,DATE=1984-2001,COMMENT=Released at Classic Gaming Expo 2001.\r\n8FFFEFBB0C6760F5,Donkey Kong (16k),DATE=1982\r\n8BCA6CBAF1282F3D,Donkey Kong (24k) (Adam),DATE=1982\r\nAD6D7822CB270F4B,Donkey Kong Jr,DATE=1982-83\r\n0FD988AA6F2FFE4A,Dr. Seuss's Fix-Up The Mix-Up Puzzler,DATE=1984\r\nDCA68C6FCED322C0,DragonFire,DATE=1984\r\n71247B1A6BCF6537,Dukes of Hazzard (The),DATE=1984\r\nB1D4E1CC4D9C29BC,Escape From The Mind Master [Proto],PROTO,DATE=1983\r\nF78598381CD1883F,Evolution,DATE=1983\r\n90CDC5B5E0188EA3,Facemaker,DATE=1983\r\n58D31DFD90013EEC,Fall Guy [Proto],PROTO,DATE=1983\r\n638614C207B15237,Fathom,DATE=1983\r\n5FA1C7BF2871A839,Flipper Slipper,DATE=1983\r\nFFAB3E2A37E2963F,Fortune Builder,DATE=1984\r\nDB8B0459092C21E7,Fraction Fever,DATE=1983\r\nDE9C1463F8F976A8,Frantic Freddy,DATE=1983\r\n3B658A1D2FA28C5C,Frenzy! (alt),DATE=1982-83\r\n3723E8FA60A1C7FC,Frenzy!,DATE=1982-83\r\n8C1AF7FF9FBE8582,Frogger,DATE=1982-83,COMMENT=Overdumped ROM.\r\nE634E77B5B24E124,Frogger,DATE=1982-83\r\nF418D401DE0AC275,Frogger II - ThreeDeep!,DATE=1984\r\n107053B62DB51F76,From Out Of The Jungle,DATE=1984\r\n94C4659844142330,Frontline (alt),DATE=1983\r\n96BD669C43152231,Frontline,DATE=1983\r\n060F88EF6F4914A8,Galaxian (alt),DATE=1983\r\n4E9E3EDDEDE7091C,Galaxian,DATE=1983\r\nCE6AE2FCD9B2500F,Gateway to Apshai,DATE=1984\r\n71053199D9693D41,Gorf,DATE=1981-83\r\n2D4E683D06C0D149,Gust Buster,DATE=1983\r\nF1EBE8ABF2B3727A,Gyruss,DATE=1984\r\n9DF82C37507F5EDB,H.E.R.O.,DATE=1984\r\nAEFE3A8B06E7FDA5,Heist (The) (alt),DATE=1983\r\nAFFE3A8906E7FCA7,Heist (The),DATE=1983\r\n53E618B9374A7FF6,Illusions,DATE=1984\r\n7211BB1BED4F501B,It's Only Rock'n'Roll,DATE=1984\r\n3381234BABB9E793,James Bond,DATE=1984\r\n1A1C2B970A36D0F8,Joust [Proto],PROTO,COMMENT=Released at Classic Gaming Expo 2001.\r\n99200D019849BF99,Juke Box,DATE=1984\r\n273AB38581885D01,Jumpman Junior (alt),DATE=1984\r\n253AB38581885D03,Jumpman Junior,DATE=1984\r\n1DAFE2E7AABA7493,Jungle Hunt,DATE=1982-83\r\n9DD3E66C3BF718F4,Ken Uston Blackjack-Poker,DATE=1983\r\n6537CC74D2649A54,Kevtris (alt),DATE=1996,COMMENT=Public Domain.\r\n4893B2A2A33EE50B,Kevtris,DATE=1996,COMMENT=Public Domain.\r\n956CC97F766F5A78,Keystone Kapers,DATE=1983-84\r\n0B287537C1889345,Kill Barney in Tokyo,DATE=1997,COMMENT=Public Domain.\r\n11D89E3CF37DC10C,Killer Instinct,DATE=1997,COMMENT=Public Domain.\r\n565CE17442132C78,Lady Bug,DATE=1982\r\n805765B7785F1224,Linking Logic,DATE=1984\r\n00F4BE822F5984C0,Logic Levels,DATE=1984\r\n3239B806B62136CA,Looping,DATE=1983\r\n6775323548472C02,M.A.S.H. [Proto],PROTO,DATE=1983\r\nD6D812105A9498AA,Memory Manor,DATE=1984,COMMENT=Overdumped ROM.\r\n6BEC09882DCA4CD5,Memory Manor,DATE=1984\r\n02A2D25E20635851,Meteoric Shower,DATE=1983\r\n37FBB52968DEB0FA,Miner 2049er (alt),DATE=1983\r\n39FBB42868DDAFFC,Miner 2049er,DATE=1983\r\n7147C2395C0E7E65,Monkey Academy (alt),DATE=1984\r\n7EC2AD0905263DA2,Monkey Academy,DATE=1984\r\n976BD98BBDBFBA64,Montezuma's Revenge,DATE=1984\r\n4DA655F21AEC754B,Moon Patrol [Proto],PROTO,DATE=1982-84\r\n58ACC5A302F91F7A,Moonsweeper (alt),DATE=1983\r\n58ACC7A302F91F78,Moonsweeper,DATE=1983\r\n6850266144333B0F,Motocross Racer (alt),DATE=1984\r\n6A50266146333B0B,Motocross Racer,DATE=1984\r\n299112293A050DBF,Mountain King,DATE=1983-84\r\n7828BE970037676D,Mousetrap,DATE=1982,COMMENT=Overdumped ROM.\r\n7A72C2A7A81509E5,Mousetrap,DATE=1982\r\nD04BA2BAA441DCC8,Mr Do! (alt),DATE=1983\r\nCE4BA2BAA441DCCA,Mr Do!,DATE=1983\r\nBDEA9BD82126524D,Mr Do's Castle,DATE=1983\r\n6630EB6F74B630B6,Nova Blast,DATE=1983\r\nE149C996EB04CBBD,Oil's Well,DATE=1984\r\n52C6239CBF8F7863,Omega Race,DATE=1981-83\r\n345BB2CF7DFE7401,One on One,DATE=1984\r\nB6DAF461664FE87E,Pac-Man [Proto],PROTO,DATE=1983-2001,COMMENT=Released at Classic Gaming Expo 2001.\r\n263619940498312A,Pepper II,DATE=1983\r\n3A79A80393FEF31E,Pitfall II - Lost Caverns,DATE=1983-84\r\n49FE5C16443C6067,Pitstop (alt),DATE=1983\r\n48FF5C16443C6067,Pitstop,DATE=1983\r\nCC5F8A89ED2E990E,Popeye,DATE=1983\r\n16A14D51D6A988A4,Porky's [Proto],PROTO,DATE=1983.\r\n6E259BE900489C05,Purple Dinosaur Massacre,DATE=1996\r\n83BA0ED8DE992244,Q*bert (alt),DATE=1983\r\n81BA0FD8DE992245,Q*bert,DATE=1983\r\n6A76D5ACA0B88DBA,Q*bert II,DATE=1984\r\nE4E9DB8118F1A42A,Quest for Quintana Roo,DATE=1983\r\nF11FB33671A0E214,Robin Hood,DATE=1984\r\nF21FB43671A0E212,Robin Hood (alt),DATE=1984\r\nB0F8E4FB563A6D7C,Roc 'N Rope,DATE=1983-84\r\n125786D75BDDB151,Rock N Bolt,DATE=1984,FLICKER\r\n2EBA5541D8FB1996,Rocky Super-Action Boxing,DATE=1983\r\nCE800F1108054441,Rolloverture,DATE=1983\r\n5357F8FCCDFA2D6E,Sammy Lightfoot (alt),DATE=1983\r\n5557F809CD072D52,Sammy Lightfoot,DATE=1983\r\nF1799E6C2AE7F784,Sector Alpha (alt),DATE=1983\r\n7DC5357F0568623B,Sector Alpha (alt2),DATE=1983\r\nDA77FCF286DA243D,Sector Alpha,DATE=1983\r\n9B48B7CCE0E5587D,Sewer Sam,DATE=1984\r\n5F92264DD14E2657,Sir Lancelot,DATE=1983\r\nA21CF664C4DA6DDD,Skiing,DATE=1986\r\nE5A25CE5D2ABC8F3,Slither,DATE=1983\r\nE54C25DE0DB133DB,Slurpy,DATE=1984\r\n60B2331F9205FB0A,Smurf Paint 'n Play Workshop,DATE=1983\r\n271BAA0346276C38,Smurf Rescue,DATE=1982\r\n4099857131AA9ABC,Space Fury (alt),DATE=1983\r\n867C3D65E31D5C00,Space Fury,DATE=1983\r\n9BCF131E71A52B24,Space Invasion,DATE=1998,COMMENT=Public Domain.\r\n68010C0A08190858,Space Panic,DATE=1983\r\n6F4ABE31951F1A8A,Spectron,DATE=1983\r\n956A960EC6F4BEE5,Spy Hunter,DATE=1983-84\r\n0446C08E65D2A58C,Squish 'Em Sam!,DATE=1983\r\n2D519ECC5E4BC8A7,Star Fortress,DATE=1997,COMMENT=Public Domain.\r\nDC1DC54454218EFB,Star Trek - Strategic Operations Simulator,DATE=1984\r\n97B2C2B74C25FFCE,Star Wars - The Arcade Game,DATE=1984\r\n708443560A88469B,Strike It! (alt),DATE=1983\r\n92F6C2D88518F64B,Strike It!,DATE=1983\r\nAF657FDB54733D8E,Subroc (alt),DATE=1983\r\n3CA816E9AF65E128,Subroc,DATE=1983\r\n3426761D89884AB8,Super Action Football (alt),DATE=1984\r\nDB8AB6F935B343C1,Super Action Football,DATE=1984\r\n37277320868949B7,Super Action Soccer,DATE=1984\r\nD4703CD3C02808BD,Super Controller Tester,DATE=1983\r\nF0CE15DAFF053A15,Super Cross Force (alt),DATE=1983\r\nDD9F9E3FF63A482F,Super Cross Force,DATE=1983\r\n5BDB2884F18A742F,Super DK! (Adam),DATE=1983\r\nE3FB4CB589EE4664,Super DK!,DATE=1983\r\n887B110A729AE8EE,Super-Action Baseball (alt),DATE=1983\r\nD0ADA176737B83FB,Super-Action Baseball,DATE=1983\r\n34BAAD0F376DF3BF,Tank Wars,DATE=1983\r\n988FFA89E2FAFB7F,Tapper,DATE=1984\r\n7051F166A0849331,Telly Turtle,DATE=1984\r\n3E1986B5BF4CCB98,Test Cartridge\r\nA6311979966CE6AF,Threshold,DATE=1983\r\nDA143B7DA982CD8A,Tic Tac Toe (alt),DATE=1996,COMMENT=Public Domain.\r\nDC0C27939B88F28B,Tic Tac Toe,DATE=1996,COMMENT=Public Domain.\r\nBD41972A4DB97FBC,Time Pilot,DATE=1983\r\nC505C676CDF90430,Tomarc the Barbarian,DATE=1984\r\nA0A3E152BFD66C89,Tournament Tennis,DATE=1984\r\n02AEBA5A447F6316,Tunnels & Trolls (Adam) (Demo),DATE=1983\r\nAFBA321B01ACC8D5,Turbo,DATE=1982\r\nFCD438F82A087955,Tutankham,DATE=1983,COMMENT=Overdumped ROM.\r\n30544295B698381F,Tutankham,DATE=1983\r\nBECDB6C87C2F91BB,Up 'N Down,DATE=1984\r\nBE8A5418E98DC90D,Venture,DATE=1982\r\nFF5EE460D2D9C1F3,Victory,DATE=1983\r\n5573347539400A0C,Video Hustler [Proto],PROTO,DATE=1984\r\nAABE49D18686036F,War Games,DATE=1983-84\r\nBA0CD56F9D92FEC9,War Room (24k),DATE=1983\r\n2D0898A666208E79,War Room (32k),DATE=1983\r\n0C4692EB0F447B63,Wing War,DATE=1983\r\nFD21DBA359149265,Winky Trap,DATE=1997,COMMENT=Public Domain.\r\nC9B30746D0A6FDC4,Wizard of Id's Wizmath,DATE=1984\r\nFD0A2D53B9678ACF,Word Feud,DATE=1984\r\n520280344E0AABF5,Yolk's on You (The) [Proto],PROTO,DATE=1983\r\n2B586CD9585B8BFA,Zaxxon,DATE=1982\r\n26324DB05C14310A,Zenji,DATE=1984\r\n\r\n---- COLECO VISION BAD DUMPS ----\r\nC0704F70A3DF424D,BC's Quest for Tires II - Grog's Revenge (32 k),DATE=1984,BAD\r\n032464D2FF4F094C,Buck Rogers - Planet Of Zoom,DATE=1983,BAD\r\n55A1FBCAE860AC51,Decathlon,DATE=1983,BAD\r\nE4DB5FC9CBB30497,Facemaker,DATE=1983,BAD\r\n71043199D9693C43,Gorf,DATE=1981-83,BAD\r\n53E618B937497FF7,Illusions,DATE=1984,BAD\r\n9FD3E66C3BF718F2,Ken Uston Blackjack-Poker,DATE=1983,BAD\r\nAFE0D9D1CAB23F0C,Learning With Leeper,DATE=1983,BAD\r\n3039B806B62136CC,Looping,DATE=1983,BAD\r\nE049C996EB04CBBE,Oil's Well,DATE=1984,BAD\r\nFAC47CF877CD7713,Pitfall!,DATE=1983,BAD\r\n48FE5B16443C6069,Pitstop,DATE=1983,BAD\r\nCB5F8A89ED2E990F,Popeye,DATE=1983,BAD\r\nBB6A5AB6B169A20F,River Raid,DATE=1982-84,BAD,FLICKER\r\n8EE99C25FC6AEE74,Slurpy,DATE=1984,BAD\r\n291BAA0346276C36,Smurf Rescue,DATE=1982,BAD\r\n976A950EC6F4BEE4,Spy Hunter,DATE=1983-84,BAD\r\n2EE9BD8C4DBAD5C4,Star Trek - Strategic Operations Simulator,DATE=1984,BAD\r\n99B589157F3BFA60,Super Cobra,DATE=1983,BAD\r\n9AB589147F3BF961,Super Cobra,DATE=1983,BAD\r\n978FFA89E2F9FB81,Tapper,DATE=1984,BAD\r\nC505C675CDF90332,Tomarc the Barbarian,DATE=1984,BAD\r\nC08A5418E98DC90B,Venture,DATE=1982,BAD\r\n2D586CD9585B8BF8,Zaxxon,DATE=1982,BAD\r\n\r\n---- HOMEBREW SEGA 8-BITS ROMS ----\r\n158CB0CABB981979,Birthday Card,VER=1,AUTHORS=Heliophobe\r\nF79EAFD4B8972079,Birthday Card,VER=2,AUTHORS=Heliophobe\r\n9316111BBB5E37DB,Charles Doty's Text Demo,VER=1,AUTHORS=Charles Doty\r\nB43B2032181B4C40,Color Check,AUTHORS=Dave\r\n2072E5B90F9D2DF7,Damiana,VER=1,AUTHORS=Heliophobe\r\n1F79E6B113F81EA8,Damiana,VER=2,AUTHORS=Heliophobe\r\n160D59BD3F8FC633,Elite Gaiden,VER=0.1.0,AUTHORS=Ricardo Bittencourt\r\n4F084DB74098B31A,Elite Gaiden,VER=0.1.28,AUTHORS=Ricardo Bittencourt\r\nD133AE33C55913EA,Game Gear Demo,AUTHORS=Charles Mac Donald\r\nACF5878232012AF9,GG High Resolution Graphics Demo,VER=1.02,AUTHORS=Charles Mac Donald\r\n2E2F74C63947B732,GG Turrican Demo,VER=0.90,AUTHORS=Martin Konrad\r\n31AE4F5F2F606F75,Good Advice,VER=1,AUTHORS=Heliophobe\r\n363D52651F4794DC,Interactive Sprite Test,AUTHORS=Charles Mac Donald,FLICKER\r\n2BA427D4F4171D0E,Not Only Words,AUTHORS=Maxim\r\n666376D33288FA3A,Mega Drive 6-Button Controller Test,AUTHORS=Charles Mac Donald\r\nB65FA3FEE5FEDF88,Music Station,VER=Demo,AUTHORS=Ricardo Bittencourt,MAPPER=0\r\nE38A4D98CB653846,Only Words,AUTHORS=Mike Gordon\r\n5694EE3448B239C1,Pretty Photo,AUTHORS=Maxim\r\n8E7662AF258B0B30,64-Color Palette Test Program,AUTHORS=Charles Mac Donald\r\n433E5C932667E41F,Scroll Test Program,AUTHORS=Charles Mac Donald\r\nD4E33E7972A85127,SG1000/SC3000 Information Database,VER=1\r\n2464136D1B405845,Simple Sprite Demo,AUTHORS=Heliophobe\r\nC23010310D22435B,Snail Music Demo,AUTHORS=Eric Quinn\r\n3FD64CA4D3EB99A4,SMS Cast,AUTHORS=Zoop,VER=1.0\r\nC207598D7A91C680,SMSC's Text Demo,VER=1\r\n84225E96769DD083,SMSC's Text Demo,VER=2\r\nA3E72D1C7869A2AA,SMS Chip-8 Interpreter,AUTHORS=Maxim,VER=0.10\r\n9A362896C76D96A8,SMS Chip-8 Interpreter,AUTHORS=Maxim,VER=0.11\r\n94F3A78C8378BC8F,SMS Palette,VER=1,AUTHORS=Zoop\r\nA43B75EE89CADC8F,SMS Power,VER=31,AUTHORS=Zoop\r\n5A7D658DA018CEB1,SMS Sound Test 1.1,VER=1.1,AUTHORS=Heliophobe\r\nC554A3F5ACCBEFE9,SMS VDP Test 1,AUTHORS=Flavio Morsoletto\r\nBB9D4DDD3E478772,Synth Test,AUTHORS=Heliophobe\r\nD0CCF9AF67F5B4AC,V Counter Test Program,VER=1,AUTHORS=Charles Mac Donald\r\n311A4B64115BACEE,VRAM Write Test Program,VER=1,AUTHORS=Charles Mac Donald\r\n2C1B4764105CADF5,VRAM Write Test Program,VER=2,AUTHORS=Charles Mac Donald\r\n59B4D4964FC597DE,Zoop'em Up,AUTHORS=Martin Konrad\r\n28255C1B1BF8EE3B,Z80 Instruction Exerciser,VER=0.10,AUTHORS=Various\r\n8D133348145094ED,Z80 Port Dumper,AUTHORS=Charles Mac Donald\r\n\r\n---- TRANSLATED ROMS ----\r\n56C13DB5D14D14C5,Aerial Assault,TRANS=FR,COMMENT=Translated by Luke.\r\n4EA630D8F2D52F0E,Aladdin,TRANS=BR,COMMENT=Hacked and Translated by ?.\r\nD0819C0AFBB8D086,Alex Kidd in Miracle World,TRANS=BR,COMMENT=Translated by Darth Vader of Emuroms Translations.\r\n317C8A79010670D9,California Games,TRANS=BR,COMMENT=Hacked and translated by Lennon of Emuboarding.\r\n94BB64515E0E038D,Blade Eagle 3D,TRANS=BR,COMMENT=Translated by X-DooMer of Emuroms Translations.\r\n67CF7597C00B6A89,Enduro Racer,TRANS=BR,COMMENT=Translated by Overflow of Emuroms Translations.\r\nBAC363840BFFC5CD,Golden Axe Warrior,TRANS=BR,COMMENT=Translated by Alvs of Emuroms Translations.\r\nF8B226730B4B78EF,Hang On,TRANS=BR,COMMENT=Translated by X-DooMer of Emuroms Translations.\r\nB481282F7C2B7C51,Hook,TRANS=BR,COMMENT=Translated by Alvs of Emuroms Translations.\r\nA17FA9EE49BD281B,Kenseiden,TRANS=BR,COMMENT=Translated by Alvs of Emuroms Translations.\r\n3902684008B29AC9,Phantasy Star Gaiden,TRANS=BR,COMMENT=Translated by CBT\\, based on the hack and translation by Magic Translations.\r\nFB440E0D8B87088C,Phantasy Star Gaiden,TRANS=EN,COMMENT=Hacked and Translated by Magic Translations.\r\nC74BC0424D8872A5,Phantasy Star Gaiden,TRANS=EN,VER=Bold Font,COMMENT=Hacked and Translated by Magic Translations.\r\n49C76FF9183253EB,R-Type,ID=G-1364,TRANS=BR,COMMENT=Hacked and translated by Lennon of Emuboarding.\r\n1E04362C6B0A32D5,SD Gundam Winner's History,ID=G-133027,TRANS=EN,COMMENT=Hacked and translated by Dave and Joe of Gaijin Production.\r\nAA760140B795F261,Soldados do Tempo,TRANS=BR,COMMENT=Hacked and Translated by Lennon of Emuboarding.\r\n156677E162D50DE9,Strider,TRANS=BR,COMMENT=Hacked and translated by Lennon of Emuboarding.\r\nF49A9D2BA7DD3BEB,Sylvan Tale,TRANS=EN,COMMENT=Hacked and translated by Aeon Genesis.\r\nE9D8EABD927B7912,Wonder Boy III: The Dragon's Trap,TRANS=FR,COMMENT=Translated by Macrotrads.\r\n971B81476C829404,Wonder Boy in Monster World,TRANS=FR,COMMENT=Translated by Macrotrads.\r\n53B9652C0D44DC36,Yu Yu Hakusho II,ID=G-3354,TRANS=EN,COMMENT=Hacked and translated by Dave and Joe of Gaijin Production.\r\n\r\n---- HACKED ROMS ----\r\n---- This part is a big mess. To be cleaned.\r\n8CBC70EA0E4351BC,Phantasy Star [HK01],HACK,ID=G-1341,VER=English,COMMENT=This version was hacked with changed characters and objects names to match better the Japanese version.\r\nADD146F3F43B57C3,Phantasy Star [Pat Johnson],HACK,ID=G-1341,VER=English,COMMENT=This version has some minor changes compared to the original version.\r\n8EF38073E8EABEFC,Sonicboy in Monsterland,HACK,AUTHORS=Yuski the Dog\r\nA9DE2B7D8841AE5A,Treinamento do Mymo,HACK,AUTHORS=Yuski the Dog\r\n9188FC95BE86CD45,Sonicboy 3: Eggman's Room [A],HACK,VER=A,AUTHORS=Yuski the Dog\r\n6BE41DBAF792FC55,Sonicboy 3: Eggman's Room [B],HACK,VER=B,AUTHORS=Yuski the Dog\r\n63711799EA445FEF,Sonicboy 2: The Eggman's Trap,HACK,AUTHORS=Yuski the Dog\r\n7E04A3B5B88826C0,Pokemon Secreto,HACK,AUTHORS=Yuski the Dog\r\nB99B1B5D6A932F08,Rodrigo em: O Resgate,HACK,AUTHORS=Yuski the Dog\r\n185F21C461686576,Rodrigo 2 em: Mate o Leonardo,HACK,AUTHORS=Yuski the Dog\r\n25EBADCAC9736BD2,Pokemon Amarelo,HACK,AUTHORS=Yuski the Dog\r\n26ED9FCCC4701D31,Pokemon Azul,HACK,AUTHORS=Yuski the Dog\r\n83C09599CA531161,Felipe em Ação,HACK,AUTHORS=Yuski the Dog\r\n6ECA835AED978DDA,Treinamento do Guerreiro Lobo I,HACK,AUTHORS=Yuski the Dog\r\n9A3C67F3438C5AA7,Treinamento do Guerreiro Lobo II,HACK,AUTHORS=Yuski the Dog\r\n399A792FAD110FB8,Guerreiro Lobo,HACK,AUTHORS=Yuski the Dog\r\nB22597E52D095621,Sonic vs. Os Mauniks,HACK,AUTHORS=Yuski the Dog\r\nB827A32E86B8838F,Magali no Castelo do Dragão,HACK,AUTHORS=Yuski the Dog\r\n26A4CCB6449BE5F0,Master Mega Man,HACK,AUTHORS=EmuBoarding\r\n418AB9F7117FCD28,Jornada do Mymo,HACK,AUTHORS=Yuski the Dog\r\nF3DEFC7C14AE20D5,Jornada do Mymo II,HACK,AUTHORS=Yuski the Dog\r\n31B8AFC0C55B7018,Master Zelda,HACK,AUTHORS=EmuBoarding\r\n9031A508D695D651,Natal do Mymo,HACK,COMMENT=Hacked version of Psycho Fox,AUTHORS=Yuski the Dog\r\n82A1301330003832,Pokemon Master,HACK,AUTHORS=Yuski the Dog\r\nF2E1A2E9FA6D9C9F,Teddy Boy & Geraldinho,HACK,AUTHORS=Yuski the Dog\r\n4406BFBEC28646AB,Pokemon Vermelho,HACK,AUTHORS=Yuski the Dog\r\nB14AEAA29C79F272,Master Smash Brothers,HACK,AUTHORS=EmuBoarding\r\nB16033737A9347F5,Pokemon Legend,HACK,AUTHORS=EmuBoarding\r\nB881C3B91A5EFFD4,Master Mario Bros,HACK,AUTHORS=Yuski the Dog\r\nE99105D877617C55,Rodrigo 2 em: Mate o Papai Noel - Versão de Natal,HACK,AUTHORS=Yuski the Dog\r\nD88C705C6BB4D5DC,Rodrigo O Resgate,HACK,COMMENT=Hacked version of Wonder Boy,AUTHORS=Yuski the Dog\r\n71988B4470C047B1,Sonicboy 4,VER=A,HACK,COMMENT=Hacked version of Wonder Boy in Monster World,AUTHORS=Yuski the Dog\r\n8199554D6AC34CCB,Sonicboy 4,VER=B,HACK,COMMENT=Hacked version of Wonder Boy in Monster World,AUTHORS=Yuski the Dog\r\n2833EE67174B8A64,R.H.W. 2000,HACK,COMMENT=Hacked version of Psycho Fox,AUTHORS=Yuski the Dog\r\nAAAD7B0A23CBB77F,Wonder Boy III DC,HACK,COMMENT=Hacked version of Wonder Boy III: The Dragon's Trap,AUTHORS=Yuski the Dog\r\n9592610A1DB0D4CD,Xaropinho,HACK,COMMENT=Hacked version of Mappi,AUTHORS=Yuski the Dog\r\n3BFC388B71CD1BAD,Mônica 3,HACK,COMMENT=Hacked version of Wonder Boy in Monster World,AUTHORS=Yuski the Dog\r\n553652BFEAA1EFEA,Sonic RPG,HACK,COMMENT=Hacked version of Phantasy Star,AUTHORS=Yuski the Dog\r\n5DB5943F04B770F0,Jornada do Krazy,HACK,AUTHORS=Yuski the Dog\r\n50C9BC3D97E07106,Treinamento do Mymo [B],HACK,AUTHORS=Yuski the Dog\r\nFE4FDAA6EA7A8847,Jornada do Mymo [B],HACK,AUTHORS=Yuski the Dog\r\n82A5838252DB1C8B,Mônica 3,HACK,AUTHORS=Yuski the Dog\r\n\r\n"
  },
  {
    "path": "meka/meka.pat",
    "content": ";-----------------------------------------------------------------------------\r\n; MEKA - Patches Database\r\n; http://www.smspower.org/meka\r\n;-----------------------------------------------------------------------------\r\n; Patches available in the default MEKA distribution are meant to fix\r\n; or improve game/software behavior. This patching functionnality can \r\n; also be used as a basic cheating tool.\r\n; For technical help, check http://www.smspower.org/dev\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Syntax:\r\n;   [crc]\r\n;   commands...\r\n;\r\n; CRC can be in any of the following format:\r\n;  - [*]                                Match and apply patch to any file\r\n;  - [xxxxxxxxxxxxxxxx]                 Match meka.nam format CRC\r\n;  - [mekacrc:xxxxxxxxxxxxxxxx]         \"\r\n;  - [crc32:xxxxxxxx]                   Match CRC32\r\n;\r\n; Commands:\r\n;  - ROM[<addr>] = <byte> [,<byte>..]   Write given byte(s) at given ROM address, on loading\r\n;  - MEM[<addr>] = <byte> [,<byte>..]   Write given byte(s) at given memory map address, every 1/60th second \r\n;\r\n; In memory map, RAM range is C000-DFFF.\r\n;\r\n; All values are in hexadecimal base.\r\n;\r\n; An ACTION REPLAY code can be easily converted in MEKA patching format:\r\n;     00xx-xxyy -> MEM[xxxx] = yy\r\n; eg: 00CF-4A02 -> MEM[CF4A] = 02\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Generic, pause-button hack [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Can be useful for VGM logging purpose. Read instruction at:\r\n;   http://www.smspower.org/music/tools/pausehack/index.shtml\r\n; Author: Maxim\r\n;-----------------------------------------------------------------------------\r\n;[*]\r\n;ROM[0066] = FB, 18, FE\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Battle Out Run\r\n;-----------------------------------------------------------------------------\r\n; Activate and enforce FM Unit support.\r\n; Author: Sonic of 8!\r\n;-----------------------------------------------------------------------------\r\n;[crc32: c19430ce]\r\n;MEM[DE00] = 01\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Double Hawk\r\n;-----------------------------------------------------------------------------\r\n; Activate and enforce FM Unit support.\r\n; Author: Sonic of 8!\r\n;-----------------------------------------------------------------------------\r\n;[crc32: 8370f6cd]\r\n;MEM[DD00] = 01\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Dynamite Dux\r\n;-----------------------------------------------------------------------------\r\n; Activate and enforce FM Unit support.\r\n; Author: Sonic of 8!\r\n;-----------------------------------------------------------------------------\r\n;[crc32: 0e1cc1e0]\r\n;MEM[D000] = 01\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Rambo III\r\n;-----------------------------------------------------------------------------\r\n; Activate and enforce FM Unit support.\r\n; Author: Sonic of 8!\r\n;[crc32: da5a7013]\r\n;MEM[DE80] = 01\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Summer Games\r\n;-----------------------------------------------------------------------------\r\n; Activate and enforce FM Unit support.\r\n; Author: Sonic of 8!\r\n;[crc32: 8da5c93f]\r\n;MEM[C001] = 01\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Super Basketball [Demo]\r\n;-----------------------------------------------------------------------------\r\n; Activate and enforce FM Unit support.\r\n; Author: Sonic of 8!\r\n;[crc32: 0dbf3b4a]\r\n;MEM[C001] = 01\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Wonder Boy III: The Dragon's Trap [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Activate FM Unit support in European/US mode (original game allows it only in Japanese mode)\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 679e1676]\r\nROM[025B] = 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Monica em: O Resgate [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Activate FM Unit support in European/US mode (original game allows it only in Japanese mode)\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 22cca9bb]\r\nROM[025B] = 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; American Pro Football [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Fix a bug preventing the game to function if FM Unit is detected.\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 3727d8b2]\r\nROM[05A7] = AF, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Walter Payton Football [SMS]\r\n; Fix a bug preventing the game to function if FM Unit is detected.\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 3d55759b]\r\nROM[0592] = AF, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Sports Pad Soccer [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Fix a bug preventing the game to function if FM Unit is not detected.\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 41c948bf]\r\nROM[0173] = 0C\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Wanted [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Fix a bug preventing the game to function if FM Unit is detected.\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 5359762d]\r\nROM[045D] = 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Sega Basic Level 3 1.0 (Export) [SC-3000]\r\n;-----------------------------------------------------------------------------\r\n; Bad dump, byte 0 is incorrect. Patch it.\r\n; Author: Ricardo Bittencourt\r\n;-----------------------------------------------------------------------------\r\n[crc32: 155fd01f]\r\nROM[0000] = C3\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Sega Basic Level 3 1.1 (Japanese) [SC-3000]\r\n;-----------------------------------------------------------------------------\r\n; Hardware check patch\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: 6aa0279d]\r\nROM[689c] = 00, 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Music [BAD] [SC-3000]\r\n;-----------------------------------------------------------------------------\r\n; This dump has byte 0 incorrect. Patch it.\r\n; Author: Ricardo Bittencourt\r\n;-----------------------------------------------------------------------------\r\n[crc32: b67ea1c4]\r\nROM[0000] = C3\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; 20 em 1 [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Disable the first controller port read, done outside of a loop.\r\n; Inputs are updated by interrupt, and at the time the value was loaded,\r\n; interrupts did not happens. It is very tricky and probably due to bad \r\n; programming and timing issues, but I don't know why it doesn't emulate well.\r\n; Author: Bock\r\n;-----------------------------------------------------------------------------\r\n[crc32: f0f35c22]\r\nROM[0FB5] = DD, 4E, FF\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Alex Kidd in Miracle World BIOS [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Allows the BIOS dump to run as a cartridge.\r\n;-----------------------------------------------------------------------------\r\n[crc32: cf4a09ea]\r\nROM[17EDE] = 00, 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Alex Kidd in Miracle World BIOS [SMS] (KR)\r\n;-----------------------------------------------------------------------------\r\n; Allows the BIOS dump to run as a cartridge.\r\n;-----------------------------------------------------------------------------\r\n[crc32: 9c5bad91]\r\nROM[1FA13] = 00, 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Hang On / Safari Hunt BIOS [SMS]\r\n;-----------------------------------------------------------------------------\r\n; Allows the BIOS dump to run as a cartridge.\r\n;-----------------------------------------------------------------------------\r\n[crc32: 91e93385]\r\nROM[1C12F] = 00, 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; SMS v2.0 BIOS [SMS]\r\n; Allows the BIOS dump to run as a cartridge.\r\n;-----------------------------------------------------------------------------\r\n[crc32: b3d854f8]\r\nROM[02C5] = 00\r\n;ROM[114] = 00, 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Sonic the Hedgehog BIOS [SMS]\r\n; Allows the BIOS dump to run as a cartridge.\r\n;-----------------------------------------------------------------------------\r\n[crc32: 81c3476b]\r\nROM[26FA] = 00, 00, 00\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Majesco BIOS [GG]\r\n;-----------------------------------------------------------------------------\r\n[crc32: 0ebea9d4]\r\nROM[00A7] = 00\r\n;-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/meka.thm",
    "content": ";-----------------------------------------------------------------------------\r\n; MEKA - Themes\r\n; http://www.smspower.org/meka\r\n;-----------------------------------------------------------------------------\r\n; To create your own themes, the easiest way is to use MEKA Configurator:\r\n;    http://www.smspower.org/maxim/mconfig/\r\n; Otherwise, you can manually edit this file.\r\n; If you create any great themes, please send them to me !\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n; Notes:\r\n; - Supported picture files are: PNG, BMP, PCX and TGA.\r\n; - Colors are defined in #RRGGBB format, where each components is encoded \r\n;   as a 8-bit hexadecimal value.\r\n; - Available effects: blood, hearts, snow\r\n; - Available background_picture display mode: center, stretch, stretch_int, tile\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Ocean]\r\nauthors                             = Puyolin, Bock\r\nbackground_color                    = #9AC7C7\r\nbackground_grid_color               = #9AC7C7\r\nwindow_border_color                 = #052D2D\r\nwindow_background_color             = #005A5A\r\nwindow_titlebar_color               = #008282\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #9AC7C7\r\nwindow_text_color                   = #9AC7C7\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #052D2D\r\nmenu_background_color               = #008282\r\nmenu_border_color                   = #052D2D\r\nmenu_selection_color                = #009A9A\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #9AC7C7\r\nmenu_gradient                       = 16%-100% #005656\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Classic]\r\nauthors                             = Bock\r\nbackground_color                    = #FFFFFF\r\nbackground_grid_color               = #C0C0C9   ; default: background_color\r\nwindow_border_color                 = #11214D\r\nwindow_background_color             = #1D357A\r\nwindow_titlebar_color               = #2549AA\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #A2A2CB\r\nwindow_titlebar_gradient\t\t\t= 50%-100% #001576\r\nwindow_text_color                   = #A2A2CB\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #11214D   ; default: window_border_color\r\nmenu_background_color               = #2549AA\r\nmenu_border_color                   = #11214D\r\nmenu_selection_color                = #4D72D3\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #A2A2CB\r\nmenu_gradient                       = 16%-100% #000D6E\r\nwidget_generic_background_color     = #2549AA   ; default: menu_background_color\r\nwidget_generic_selection_color      = #4D72D3   ; default: menu_selection_color\r\nwidget_generic_border_color         = #11214D   ; default: window_border_color\r\nwidget_generic_text_color           = #FFFFFF   ; default: window_text_highlight_color\r\nwidget_generic_text_unactive_color  = #A2A2CB   ; default: window_text_color\r\nwidget_listbox_background_color     = #2549AA   ; default: menu_background_color\r\nwidget_listbox_border_color         = #11214D   ; default: menu_border_color\r\nwidget_listbox_selection_color      = #4D72D3   ; default: menu_selection_color\r\nwidget_listbox_text_color           = #FFFFFF   ; default: menu_text_color\r\nwidget_scrollbar_background_color   = #1D357A   ; default: window_background_color\r\nwidget_scrollbar_scroller_color     = #4D72D3   ; default: menu_selection_color\r\nwidget_statusbar_background_color   = #2549AA   ; default: menu_background_color\r\nwidget_statusbar_border_color       = #11214D   ; default: menu_border_color\r\nwidget_statusbar_text_color         = #FFFFFF   ; default: menu_text_color\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Bloodlust]\r\nauthors                             = Bock\r\nbackground_color                    = #000000\r\nbackground_grid_color               = #000000\r\nwindow_border_color                 = #7A000D\r\nwindow_background_color             = #8E0000\r\nwindow_titlebar_color               = #BF0000\r\nwindow_titlebar_text_color          = #F7DFDF\r\nwindow_titlebar_text_unactive_color = #D38E8E\r\nwindow_titlebar_gradient            = 44%-100% #901010\r\nwindow_text_color                   = #BBAAAA\r\nwindow_text_highlight_color         = #F7DFDF\r\nwindow_separators_color             = #7A000D\r\nmenu_background_color               = #BF0000\r\nmenu_border_color                   = #7A000D\r\nmenu_selection_color                = #D33129\r\nmenu_text_color                     = #F7DFDF\r\nmenu_text_unactive_color            = #D38E8E\r\nmenu_gradient                       = 16%-100% #7F0000\r\neffect\t\t\t\t\t\t\t\t= blood\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Girl Power]\r\nauthors                             = Bock\r\nbackground_color                    = #FF7EBF\r\nbackground_grid_color               = #FF7EBF\r\nwindow_border_color                 = #7E003D\r\nwindow_background_color             = #FF419E\r\nwindow_titlebar_color               = #FF007E\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #F3B7DF\r\nwindow_titlebar_gradient            = 00%-100% #BF003E\r\nwindow_text_color                   = #FBD3F3\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #7E003D\r\nmenu_background_color               = #FF007E\r\nmenu_border_color                   = #7E003D\r\nmenu_selection_color                = #FF5AAA\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #F3B7DF\r\nmenu_gradient                       = 28%-100% #C70046\r\neffect\t\t\t\t\t\t\t\t= hearts\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Deep Purple]\r\nauthors                             = BTD BTD\r\nbackground_color                    = #9686FF\r\nbackground_grid_color               = #9686FF\r\nwindow_border_color                 = #11214D\r\nwindow_background_color             = #3D357A\r\nwindow_titlebar_color               = #7249C7\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #A2A2A2\r\nwindow_titlebar_gradient            = 00%-100% #421997\r\nwindow_text_color                   = #A2A2CB\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #11214D\r\nmenu_background_color               = #7249C7\r\nmenu_border_color                   = #11214D\r\nmenu_selection_color                = #8A7A9A\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #A2A2A2\r\nmenu_gradient                       = 00%-100% #4A219F\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[SMS Power!]\r\nauthors                             = Tincho DJ, Bock\r\nbackground_color                    = #00669A\r\nbackground_grid_color               = #00669A\r\nwindow_border_color                 = #003566\r\nwindow_background_color             = #0072A2\r\nwindow_titlebar_color               = #0082B3\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #E3E3E3\r\nwindow_text_color                   = #F3F3F3\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #003566\r\nmenu_background_color               = #0080B0\r\nmenu_border_color                   = #003566\r\nmenu_selection_color                = #1B9BCC\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #B0B0B0\r\nmenu_gradient                       = 33%-100% #004273\r\nwidget_generic_text_unactive_color  = #C0C0C0\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Monochrome]\r\nauthors                             = Limbs a Flyin'\r\nbackground_color                    = #000000\r\nbackground_grid_color               = #3D3D3D\r\nwindow_border_color                 = #3D3D3D\r\nwindow_background_color             = #1D1D1D\r\nwindow_titlebar_color               = #3D3D3D\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #828282\r\nwindow_titlebar_gradient            = 00%-100% #000000\r\nwindow_text_color                   = #828282\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #3D3D3D\r\nmenu_background_color               = #3D3D3D\r\nmenu_border_color                   = #3D3D3D\r\nmenu_selection_color                = #828282\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #828282\r\nmenu_gradient                       = 00%-100% #000000\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Alex Kidd]\r\nauthors                             = Myau of Algol\r\nbackground_color                    = #00E2C5\r\nbackground_picture                  = \"Themes/AlexKidd.png\" stretch_int\r\nwindow_border_color                 = #151515\r\nwindow_background_color             = #00868A\r\nwindow_titlebar_color               = #00AAB3\r\nwindow_titlebar_text_color          = #000000\r\nwindow_titlebar_text_unactive_color = #00515A\r\nwindow_text_color                   = #00007A\r\nwindow_text_highlight_color         = #000000\r\nwindow_separators_color             = #151515\r\nmenu_background_color               = #00AAB3\r\nmenu_border_color                   = #151515\r\nmenu_selection_color                = #009A9A\r\nmenu_text_color                     = #000000\r\nmenu_text_unactive_color            = #00515A\r\nmenu_gradient                       = 16%-100% #007E87\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Phantasy Star]\r\nauthors                             = Myau of Algol\r\nbackground_color                    = #C34141\r\nbackground_grid_color               = #C34141\r\nbackground_picture                  = \"Themes/PhantasyStar.png\" stretch_int\r\nwindow_border_color                 = #000000\r\nwindow_background_color             = #C3864D\r\nwindow_titlebar_color               = #E3CB62\r\nwindow_titlebar_text_color          = #000000\r\nwindow_titlebar_text_unactive_color = #000000\r\nwindow_titlebar_gradient            = 00%-100% #C3AB42\r\nwindow_text_color                   = #000000\r\nwindow_text_highlight_color         = #000000\r\nwindow_separators_color             = #000000\r\nmenu_background_color               = #E3CB62\r\nmenu_border_color                   = #000000\r\nmenu_selection_color                = #C39A00\r\nmenu_text_color                     = #000000\r\nmenu_text_unactive_color            = #000000\r\nmenu_gradient                       = 37%-100% #C3AB42\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Psycho Fox]\r\nbackground_color                    = #FF00FF\r\nbackground_grid_color               = #FF00FF\r\nbackground_picture                  = \"Themes/PsychoFox.png\" stretch_int\r\nwindow_border_color                 = #DFB7B7\r\nwindow_background_color             = #DF5E5E\r\nwindow_titlebar_color               = #FF7E7E\r\nwindow_titlebar_text_color          = #FFFFFF\r\nwindow_titlebar_text_unactive_color = #FFDFDF\r\nwindow_titlebar_gradient            = 75%-100% #DF5E5E\r\nwindow_text_color                   = #E7E7E7\r\nwindow_text_highlight_color         = #FFFFFF\r\nwindow_separators_color             = #DFB7B7\r\nmenu_background_color               = #FF7E7E\r\nmenu_border_color                   = #DFB7B7\r\nmenu_selection_color                = #FF3D00\r\nmenu_text_color                     = #FFFFFF\r\nmenu_text_unactive_color            = #FFDFDF\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Ninja Gaiden]\r\nauthors                             = Excremedies, Kurt Roliz\r\nbackground_color                    = #000000\r\nbackground_grid_color               = #000000\r\nbackground_picture                  = \"Themes/NinjaGaiden.png\" stretch\r\nwindow_border_color                 = #000041\r\nwindow_background_color             = #002141\r\nwindow_titlebar_color               = #210041\r\nwindow_titlebar_text_color          = #C3C3C3\r\nwindow_titlebar_text_unactive_color = #828282\r\nwindow_titlebar_gradient            = 50%-100% #00000D\r\nwindow_text_color                   = #C3C3C3\r\nwindow_text_highlight_color         = #C3C3C3\r\nwindow_separators_color             = #000041\r\nmenu_background_color               = #210041\r\nmenu_border_color                   = #000041\r\nmenu_selection_color                = #C31919\r\nmenu_text_color                     = #C3C3C3\r\nmenu_text_unactive_color            = #828282\r\nmenu_gradient                       = 16%-100% #000005\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Callus]\r\nauthors                             = Dr. Squeegee\r\nbackground_color                    = #000000\r\nbackground_grid_color               = #000000\r\nwindow_border_color                 = #008200\r\nwindow_background_color             = #000000\r\nwindow_titlebar_color               = #004100\r\nwindow_titlebar_text_color          = #C3FFC3\r\nwindow_titlebar_text_unactive_color = #828282\r\nwindow_text_color                   = #00FF00\r\nwindow_text_highlight_color         = #C3FFC3\r\nwindow_separators_color             = #008200\r\nmenu_background_color               = #004100\r\nmenu_border_color                   = #008200\r\nmenu_selection_color                = #00C300\r\nmenu_text_color                     = #C3FFC3\r\nmenu_text_unactive_color            = #828282\r\n;-----------------------------------------------------------------------------\r\n\r\n;-----------------------------------------------------------------------------\r\n[Amiga Workbench 1.3]\r\nauthors                             = Dr. Squeegee\r\nbackground_color                    = #0051B3\r\nbackground_grid_color               = #0051B3\r\nwindow_border_color                 = #000000\r\nwindow_background_color             = #0051B3\r\nwindow_titlebar_color               = #FFFFFF\r\nwindow_titlebar_text_color          = #0051B3\r\nwindow_titlebar_text_unactive_color = #000000\r\nwindow_text_color                   = #FFFFFF\r\nwindow_text_highlight_color         = #0051B3\r\nwindow_separators_color             = #000000\r\nmenu_background_color               = #FFFFFF\r\nmenu_border_color                   = #000000\r\nmenu_selection_color                = #FF8A00\r\nmenu_text_color                     = #0051B3\r\nmenu_text_unactive_color            = #000000\r\n;-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/meka.txt",
    "content": "\n  MEKA 0.80-ALPHA - Documentation\n ===========================\n  Multi machine emulator for MS-Windows, GNU/Linux, etc.\n  (c) in 1998-2025 by MEKA team (Omar Cornut, Marat Fayzullin, Mitsutaka Okazaki, Maxim & more, full list below).\n ==========================================================================\n  Homepage: http://www.smspower.org/meka\n  License in 'sources.txt' file (BSD-like for most parts)\n ==========================================================================\n  This documentation is best viewed with a fixed width font.\n  Please forgive my sometimes flaky english.\n\n----------------------------------------------------------------------------\n Level 0 : Documents index\n----------------------------------------------------------------------------\n\n   meka.txt      : main documentation\n   changes.txt   : changelog\n   compat.txt    : compatibility list\n   debugger.txt  : debugger, development, hacking tools\n   multi.txt     : multiplayer games list\n   sources.txt   : how to compile, license\n   tech.txt      : technical diagrams\n\n If you are looking for how to donate to the MEKA project, press Up, Down,\n Right, Left and start directly at Level 6. Documentation are cool.\n----------------------------------------------------------------------------\n\n----------------------------------------------------------------------------\n Level 1 : Introduction\n----------------------------------------------------------------------------\n\n MEKA is a multi machine emulator, originally started as a Sega Master System\n emulator, and generally oriented toward Z80-based Sega 8-bit systems.\n MEKA emulates the following systems:\n\n  - Sega Game 1000        / SG-1000  / Japan, Oceania\n  - Sega Computer 3000    / SC-3000  / Japan, Oceania, Europe\n  - Super Control Station / SF-7000  / Japan, Oceania, Europe\n  - Sega Mark III         / MK3      / Japan\n     + FM Unit Extension  / MK3+FM   / Japan\n  - Sega Master System    / SMS      / World Wide\n  - Sega Game Gear        / GG       / World Wide\n  - ColecoVision          / COLECO   / America, Europe\n  - Othello Multivision   / OMV      / Japan\n\n MEKA is developped and coordinated by:\n\n > Omar Cornut (Bock)\n   E-mail: omar AT miracleworld DOT net\n\n With work from the following handsome people:\n\n > Marat Fayzullin (RST38H)     Zilog Z80 CPU emulation core. Implemented with modifications in MEKA.\n > Mitsutaka Okazaki            Software Yamaha 2413 emulator (EMU2413).\n > Maxim                        Software PSG emulator.\n > Hiromitsu Shioya (Hiro-shi)  Original sound engine (now obsolete).\n > Ulrich Cordes                FDC765 emulator for SF-7000. Implemented with modifications by Marc Le Douarain.\n > Thomas Bernard (Nanard)      FDC765 emulator improvements.\n > Valerie Tching (Kittie)      Initial version of the Memory Editor.\n > Johan Euphrosine (Proppy)    GNU/Linux+OSX tweaks.\n > DJRobX                       Blitters and video improvements, HQ2X interface.\n > Maxim Stephin (MaxSt)        HQ2X graphics filter.\n > Dirk Stevens                 Eagle graphics filter.\n\n MEKA in its original flavor was a program for MS-DOS and compatible systems.\n MEKAW is the codename for the MS-Windows version of MEKA.\n MEKANIX is the codename for the GNU/Linux version of MEKA.\n\n The MS-DOS version has been discontinued after version 0.70 (April 2005).\n You can still grab older versions from the official site.\n\n The Windows version is the main development version.\n\n The GNU/Linux version should be working but needs a maintainer.\n Could it be you?\n\n Now let me tell you more about the cool systems that MEKA emulates!\n\n -- on the Sega side --\n\n The SG-1000, for \"Sega Game 1000\", was released in Japan in July 1983.\n Bbased on the same components as the MSX1 hardware, it is the first known\n Sega home console system. It was later distributed by Grandstand in New Zealand.\n\n The SC-3000, for \"Sega Computer 3000\", is a variation of the SG-1000 extending\n it with a keyboard and the possibility to plug various peripherals.\n Such peripherals include a tape recorder (SR-1000) for reading data in and out\n from the computer, a printer (SP-400), a modem (John Sands' Micromodem 3) and\n giant extension called the Super Control Station (SF-7000) that extend the\n SC-3000 with a 3\" floppy disk drive, a Centronics printer port, and additional\n memory. The SC-3000 was released in November 1983 in Japan, and then was sold\n in various countries around the world (mostly Oceania and Europe), usually\n coming packaged with a BASIC programming cart.\n\n Later, Sega released some updates to these systems, including, but not\n limited to the SC-3000h (a re-release of the SC-3000 with a hard keyboard),\n and the SG-1000 II (also called Mark II). The SK-1100, for \"Sega Keyboard\"\n was an upgrade to the SG-1000 and SG-1000-II to be able to use keyboard\n software such as the BASIC or the Music Editor.\n\n The Mark III, released in 1985, is the first Master System compatible system.\n It still have the necessary ports to plug the keyboard. A FM Unit extension\n was available at the release of the Master System, providing the system with\n a YM2413 chip for FM synthesis. The FM Unit is supported by most games\n released in Japan between 1986 and 1988 and a few games later developped by\n Japanese teams. Out Run is the first game featuring support for the FM Unit.\n\n The Mark III is backward compatible with SG-1000/SC-3000 games, although its\n video chip implement a darker, slighty incorrect color palette (compared to\n an original SG-1000 or SC-3000).\n\n In 1986 came the Sega Master System, two years after Nintendo released their\n crappy gray box. It was sold just about everywhere, but the Japanese version\n embedded the YM2413 FM extension.\n Other differences with the Mark III are the 3-D Glasses mini jack port and\n the embedded rapid fire unit, none of them being available on non-Japanese\n units. The Master System is also backward compatible with the older systems,\n although it has the same palette issue as the Mark III when emulating old\n video modes.\n\n The Master System had an interesting success in Brazil, where Tec Toy, the\n official distributor, released plenty of ports from Game Gear, unreleased\n games and sometimes even original games of their own, up to 1997.\n The Master System II was rebranded \"Master System 3\" in Brasil and got\n released countless times under different packaging variants.\n The Master System Super Compact series of systems are handheld systems\n connecting to a TV thru an antenna receptor. It also got released in pink\n color and renamed the Master System Girl.\n\n Tec Toy is still around and continuing to release Sega systems.\n From December 2002 and practically every year until 2009 (more to come?),\n Tec Toy released new variants of \"Master System 3 Collection\" packaged\n with dozens/hundreds of games.\n\n In July 2004, Tec Toy released the \"Master System Handy\" in the form of\n a controller (similarly to the Super Compact models) and embedding 8 games.\n\n The Sega Game Gear was released in 1991. It is basically a portable Master\n System with a smaller screen, a communication port (for dual player gaming)\n and a bigger palette (4096 colors available instead of 64). Although old\n SG-1000/SC-3000 video modes are still supported, their default palette\n was removed so most SG-1000/SC-3000 software have wrong colors on a\n Game Gear (software modification allows fixing that).\n\n -- on the other side --\n\n There was a machine called the Othello Multivision, released in Japan,\n which is in fact a SG-1000 with a new shape (pretty small, and embed an\n incomplete keyboard) and an Othello game in ROM. Eight game cartridges\n were specifically released for it. They are fully compatible with SG-1000.\n\n (following text by Tincho DJ)\n\n In 1982, Coleco (COnnecticut LEather COmpany) released the ColecoVision.\n In those years, Atari led the home video games market with Atari 2600, a\n 8-bit console released in 1978. Coleco wanted to release ColecoVision with\n Donkey Kong, the Nintendo's arcade smash hit. But it wasn't possible; Mattel\n (the Intellivision manufacturer) and Atari released this game first. Anyway,\n Coleco could release Donkey Kong four months later, acquiring KING KONG's\n rights from Universal Studios (Nintendo had been demanded by Universal, due\n to suspicious similarities between Donkey Kong and King Kong. Some months\n later, Nintendo won). This wasn't the last controversy in which Coleco was\n involved. In 1983, a cartridge adaptor was released by Coleco. This adaptor\n would let you use Atari 2600 cartridge on the ColecoVision. Of course, Atari\n demanded Coleco; but Coleco won.\n\n Later, Coleco released Adam, a computer based on Colecovision hardware. It\n wasn't very successful. Colecovision's time was running out, and production\n was stopped in 1984.\n\n----------------------------------------------------------------------------\n Level 2 : Features\n----------------------------------------------------------------------------\n\n Graphics\n --------\n Original VDP (Video Display Processor) functionnalities were implemented as\n accurately as possible (within my given time and brain ressources), including\n some obscure features, so most games should be displaying accurately.\n\n MEKA emulates the following display modes:\n\n  - TMS9918 mode 0 (Graphics)\n  - TMS9918 mode 1 (Text)\n  - TMS9918 mode 2 (Graphics)\n  - TMS9918 mode 3 (Multicolor)\n  - SMS/GG mode 4\n  - SMS PAL extended 224-lines mode\n\n Including proper scrolling, line-based raster effect and sprite collision,\n sprite flickering (optional), and some VDP variation emulation.\n\n If your computer is slower and cannot cope with MEKA (<300 Mhz), you may\n want to try using Massage or BrSMS. Both of those MS-DOS based emulators\n are faster, although not as compatible.\n\n\n Sound\n -----\n MEKA emulates both sound hardware featured in the supported systems:\n\n  - SN-76496 Programmable Sound Generator (PSG) by Texas Instrument\n  - YM-2413 FM Generator (FM) by Yamaha\n\n Although technically better, the FM hardware is only supported by certain\n Master System games, mostly released between between 1986 and 1989.\n As mentionned earlier, this hardware only exists as an add-on for the\n Sega Mark III, or in the Japanese Sega Master System. So for most users,\n FM music will sound unusual.\n\n FM emulation is disabled by default, but if you are interested in hearing\n how an extended Mark III or a Japanese Master System would sound, you can\n freely enable it back in the SOUND menu of the emulator.\n\n The 4 channels of the Programmable Sound Generator are emulated in near\n perfection. Data gathered from various studies (including, but not\n limited to excellent work done by Maxim) allows perfection to go as far\n as generating noises using the same sequence of pseudo random numbers\n as a real PSG!\n\n The Yamaha YM-2413 chipset features 9 channels, 15 pre-defined instruments,\n and 1 user definable instrument. 3 channels can be used for percussions,\n and the chipset provides hardware vibrato and amplitude modulation.\n\n\n Peripherals\n -----------\n MEKA supports/emulates the following peripherals:\n\n  - Standard, two buttons joypad:\n    [all systems]\n    Control with keyboard or joypads.\n\n  - Light Phaser:\n    [Master System]\n    Control the cursor with mouse, shoot with first button (by default).\n    Gangster Town supports 2 Light Phasers, but there's currently no way\n    to control two separates Light Phasers in the emulator (but you can assign\n    your mouse to both of them on the same time and double fire-power).\n\n  - Paddle Control (ala Steering Wheel):\n    [Mark III / Master System]\n    This analog paddle is supported by a few japanese games.\n    It is possible to use a standard keyboard or digital joystick, but a\n    mouse is HIGHLY recommended to simulate a Paddle Control.\n    Galactic Protector supports 2 Paddle Controls on the same time.\n\n  - Sports Pad:\n    [Mark III / Master System]\n    This heavy trackball is supported by a few sports games.\n    Control with mouse. First and second buttons have the usual behavior.\n    Sports games supports 2 Sports Pad, but there's currently no way to\n    control two separates Sports Pad in the emulator (you can assign your\n    mouse to both of them on the same time, thought).\n\n  - SK-1100 Keyboard:\n    [Sega Computer 3000]\n    Used in all Sega Computer 3000 specific programs such as the Sega BASIC.\n    Control with your computer keyboard. See key assignements below in this\n    document.\n\n  - 3-D Glasses:\n    [Mark III / Master System]\n    MEKA let you play 3-D games using three differents methods.\n\n    - The first method is handled on the software side and the one you\n      are likely to use without any particular hardware.\n      MEKA can show either left or right eyes screens, removing the huge\n      jerky flickering that you can see when showing both eyes screens.\n      As a result of showing only one side, the framerate is halved by two.\n\n    - A more interesting method is to use real 3-D glasses.\n      If you tell MEKA to keep 3-D rendering as is (showing both sides),\n      you will be able to enjoy the effect by using a video card such as\n      the ASUS AGP-V6600, which uses the same technology. I did not try\n      it myself so I cannot confirm, but you should be able to play 3-D\n      games with MEKA using such video card and its dedicated 3-D glasses.\n\n    - Last but not least, the greatest way of playing 3-D games is to use\n      real Sega Master System 3-D glasses! The TECH.TXT include description\n      and schematic of a simple adaptor to plug such glasses on your computer,\n      through COM ports. MEKA supports SMS 3-D glasses plugged this way and\n      will communicate with them to enable/disable each eyes in sync with\n      emulation.\n\n  - Terebi Oekaki (TV Draw) Graphic Board:\n    [Sega Game 1000 / Sega Computer 3000 / Mark III / Master System]\n    This is a graphic board and pen set which was available in Japan only,\n    and directly connected to a drawing software cartridge.\n    Control with mouse. First button simulates a pen press, and second\n    button simulates the pen being away from the graphic board, so you\n    can control the cursor with a joypad as well.\n\n Using dedicated adapters, it is also possible to plug and use Sega Master\n System controllers into your computer. Please read the TECH.TXT about it.\n\n\n Interface\n ---------\n MEKA includes a dedicated graphical user interface (GUI).\n It should not requires particular skill to use. Just use your mouse to\n point and click. Experienced users that are sick of using mice are also\n able to use keyboard shortcuts to activate certain functions. However, to\n give you some fun - or, due to me being a lazy bastard - they aren't all\n documented or functionnal.\n\n The graphical user interface is a bit slow, and a fast machine (300+ MHz)\n is recommended to use it in optimal conditions, without having to skip\n frames. Of course, the interface can be disabled (pressing Escape) and\n emulation speed is not affected.\n\n The current state of this thing is that I wrote the GUI code a long time\n ago and that it is severely outdated now. I want to make plenty of update\n and add new features to it, but that will be when I'll find enough time.\n\n\n Other things\n ------------\n A lot of work has been done on various things, some described below:\n\n  - ZIP file support: you can keep your ROM compressed in the ZIP file\n    format to save space, MEKA does know how to handle them.\n\n  - Patching system: this allows you to tell MEKA to patch a ROM on loading,\n    without having to modify the original file, or to patch memory (RAM, etc.)\n    at runtime. It can be used as a basic cheating functionnality.\n    This part requires tweaking the \"MEKA.PAT\" file manually or using a tool.\n\n  - Localized messages inside the emulator. Thanks to translating contributor,\n    MEKA is usable in variety of languages.\n\n  - Save states. You can load and save in-game, using F5 and F7 keys, with\n    up to a hundred slots for storing a game state (change with F6 and F8).\n    In addition, it is possible to load old Massage states by renaming them\n    to the MEKA naming convention. MEKA will automatically convert them.\n\n  - BIOS inclusion. You can play the snail game in MEKA, provided you know\n    how to access to it (alright, if you forgot, try pressing UP+1+2).\n    Originally, MEKA was supposed to use my own reprogrammed BIOS. Then I\n    found that someone already dumped them so I stopped working on mine and\n    included the original one instead.\n    MEKA even includes the Japanese Master System BIOS, which you can check\n    by setting the machine to Japanese and booting it without any game loaded.\n    It shows a little demo with a scrolling ground and plays the Space Harrier\n    music theme, taking advantage of both sound chipsets.\n\n  - A precise compatibility list. MEKA was heavily tested by myself.\n    Also thanks to all people who reported bugs, and Mxs, Jossa, Tincho DJ,\n    for their past help with Game Gear and ColecoVision lists.\n\n  - A game database, with full name, ROM image checksum, product numbers,\n    required peripherals, and comments in some cases. A lot of time was spent\n    building and updating this unique database. This permit to display full\n    game name and select specific emulation feature per game, although this\n    database is not needed for MEKA to function properly in most cases.\n    This database is kept updated to reflect various game versions, and is\n    one of the fundation element of a full-featured web site in the work.\n\n  - Logging of sound output to VGM (and WAV) format. VGM is a logging format\n    developed by the S8-Dev community of SMS Power. For more information,\n    and a music archive, go to http://www.smspower.org/Music\n    Logging of WAV only works for PSG sound (YM-2413 FM is not yet logged).\n\n  - Definable video modes with some nice fullscreen effects available such\n    as TV scanline simulation or HQ2X graphic enhancer.\n\n  - Debugging features, making MEKA useful for various programming/debugging\n    or even cheating purposes:\n     - Full featured Z80 debugger\n     - Palette Viewer\n     - Tiles Viewer\n     - Tilemap Viewer\n     - Memory Editor\n     - Technical Information summary\n    Read the \"DEBUGGER.TXT\" file for more information.\n\n  - Easter eggs / secret features: edit everything, click everywhere, try\n    all keys combinaisons... and you may get lucky several times!\n    Or unlucky playing Mario.\n\n----------------------------------------------------------------------------\n Level 3 : \"Does it work ?\"\n----------------------------------------------------------------------------\n\n I tried to make MEKA as compatible I could make it.\n Unfortunatly, not every single game is working perfectly with it. If you\n want to know which, be sure to check the compatibility list provided in\n the COMPAT.TXT file.\n\n If you found or suspect any bug or glitch that is not mentionned in the\n compatibility list, please report it to me. Your help in spotting bugs\n is precious.\n\n----------------------------------------------------------------------------\n Level 4 : \"I just checked it... Heh ! where did you got all these games ?!\"\n----------------------------------------------------------------------------\n\n SMS Power! - http://www.smspower.org\n\n This is our Internet home, and new ROM images are regularly made available\n from here. However, it is of your responsability to find ROM images.\n You may want to check links or use Internet search engine.\n Although SMS Power's current occupation is to release new ROM images, we\n are comitted to slowly evolve into a full-featured Sega 8-bit web museum,\n with hundred of pages that will make you drop Opa Opa tears and consider\n building a time machine.\n\n----------------------------------------------------------------------------\n Level 5 : Usage\n----------------------------------------------------------------------------\n\n Simply execute the \"MEKA.EXE\" (or \"MEKAW.EXE\", depending on the version\n you are using) file, and MEKA should be up and running.\n\n Command line\n ------------\n You can also run MEKA from the command line and pass it a filename parameter.\n\n Command line options are also available:\n\n   -HELP -?         Display command line help\n   -SETUP           Start with the setup screen\n   -LOAD <n>        Load savestate <n> on startup\n   -LOG <file>      Log message to file <file> (appending it)\n   -NOELEPHANT      Just what it says\n\n Keys\n ----\n The default keyboard mapping is detailled in sections below.\n\n Common to all systems\n ---------------------\n  D-Pad ............................. Arrow Keys (default)\n  Button 1 .......................... Left Control (default)\n  Button 2 .......................... Left Alternate (default)\n\n Master System / SG-1000\n -----------------------\n  Soft Pause ........................ Space\n    This is the same pause as if you pressed the button on a real machine.\n    It can be used only if the game supports it at the moment you press it.\n    On some game, pressing pause will get you a menu, etc..\n\n  Hard Pause ........................ F12\n    This \"special\" pause with simply freeze the game, without changing\n    anything. It is usable everytime, everywhere.\n\n  Soft Reset ........................ Backspace\n    This is the same reset as if you pressed the button on a real machine.\n    It can be used only if the game supports it at the moment you press it.\n    On some emulated systems that does not support software reset, like the\n    Game Gear, pressing this key will actually produces an hard reset.\n\n  Hard Reset ........................ ALT+Backspace\n    This \"special\" reset with completly reset the emulated system.\n    It is usable everytime, everywhere.\n\n Game Gear\n ---------\n  Start ............................. Space\n  Hard Reset ........................ Backspace\n\n SC-3000/SF-7000 (anytime using the SK-1100, in fact)\n ----------------------------------------------------\n  Soft Reset ........................ Break\n\n Other keys are mapped at the same place as the Sega Keyboard (SK-1100).\n So be sure to look at the provided picture carefully. For example:\n\n  Control ........................... Caps Lock\n  Graph ............................. Left Control\n\n The \"Pi\" key, also used to type the \"Ro\" kana in Japanese, has\n unfortunately no equivalent on today's PC keyboard of most countries.\n Because of this, you can also either use the backslash key on the\n bottom left of your keyboard, OR the slash key on the keypad, to\n replace the missing \"Pi\" key.\n\n See a paragraph below about how to use SC-3000 and SF-7000 software.\n\n ColecoVision\n ------------\n  Numeric Pad ....................... Keys 0 to 9, Minus and Equal\n\n Miscellaneous keys\n ------------------\n  Switch between GUI and Game mode... Escape\n  Switch fullscreen/windowed......... ALT+Enter\n\n  Switch to next fullscreen blitter ....................... F1\n  Switch between automatic and standard frameskipping ..... F2\n  Decrease speed (automatic) or frameskip (standard) ...... F3\n  Increase speed (automatic) or frameskip (standard) ...... F4\n\n  Save Game State ................... F5\n  Load Game State ................... F7\n  Previous State Slot ............... F6\n  Next State Slot ................... F8\n\n  Show FPS counter .................. ALT+F\n\n  Change emulated peripheral ........ F9\n  Enable/Disable Sega keyboard ...... CTRL+F9\n\n  Enable/Disable sprites ............ F11\n  Enable/Disable background ......... CTRL+F11\n\n  Enable/Disable debugger ........... Scroll Lock (*1)\n\n  Close current window .............. CTRL+F4\n  Cycle thru inputs windows ......... CTRL+TAB\n\n  Quit emulator ..................... ALT+F4\n  Save screen to a file ............. PrintScreen\n\n  (*1) Debugger must be activated. See \"How to use the debugger\".\n\n\n How to use SC-3000 and SF-7000 Software\n ---------------------------------------\n  Original SC-3000 games were the same as for SG-1000, being provided as\n  cartridge and thus loading the ROM is the only thing you need to do to\n  make them run. However, since the SC-3000 provided a BASIC cartridge,\n  and more over, the SF-7000 an easy way to store programs (on floppy\n  disks), homemade programs may prove being trickier to load.\n\n  SF-7000 disks are rarely self-bootable (this is of course the case of\n  the Disk Basic), and for most of them they need to be run from inside\n  of the Disk Basic. Once it is loaded and running, load the floppy disk\n  (.SF7 extension) you want to use, and type the FILES command to be given\n  a list of files on the disk.\n\n  To load a specified program, use LOAD \"program name\" where the program\n  name is usually ending with the .BAS extension. You can move your cursor\n  to the line the FILES listing gave you, add the LOAD command and press\n  enter, that'll do it. Afterward, the RUN command will start the program.\n\n  The cassette drive (CLOAD command on Disk Basic, and LOAD on original)\n  is not yet emulated and thus you will not be able to use it now :-(\n  Note that I am always looking for SC-3000 tapes, if you have some you\n  can part, they might prove being useful in the future. I am gathering\n  many of them currently, and of course hope to be able to work on tape\n  emulation someday (Aaron, I'm hearing you :)\n\n How to use the debugger\n -----------------------\n  Please read to the \"DEBUGGER.TXT\" documentation file.\n\n\n----------------------------------------------------------------------------\n Level 6 : \"I still like MEKA !\" - How to help\n----------------------------------------------------------------------------\n\n Thanks. If you want to help further development and support the software\n and general Sega 8-bit support, your donations are welcome and helpful.\n\n  - Donate Sega 8-bit related items:\n    I love it! Software, hardware, cartridges, cards, tapes, posters,\n    magazines, goodies, documents, source codes, development kits, samples,\n    trivias, prototypes, all welcome!\n\n  - Donate money:\n    Money helps me to purchase games related to the SMS Power! project, as\n    well as getting weird pieces of related Sega 8-bit hardware/items.\n\n You can donate the amount of your choice.\n < This section of the documentation used to contain a detailed equation\n suggesting how much to donate based on your computer power (supposedly\n related to your income) but such practice are so 1998, so I deleted it. >\n\n It is suggested to donate via PayPal.com because it is more convenient.\n My PayPal account is linked to my e-mail address (as seen at the top of\n this documentation).\n\n If you want to use another form of payment or considering an unusual\n type of donation, please contact me to discuss details.\n\n < This section of the documentation used to contain funny treats and\n comments to encourage you to make a donation, but such practice are so\n 2001, so I deleted it. >\n\n Donating users will be granted access to SMS Power! releases area,\n and most importantly they feel warm and nice inside.\n\n Enjoy!\n\n----------------------------------------------------------------------------\n Level 7 : Source code and development\n----------------------------------------------------------------------------\n\n As for 2005/04/03, MEKA source code is now available to all users.\n Your input and improvements are welcome.\n Please refer to SOURCES.TXT for more information about developping for MEKA.\n License is also included in SOURCES.TXT (it is a custom BSD-like license\n for most parts).\n\n You can download the source code on MEKA homepage:\n    http://www.smspower.org/meka\n\n Latest work-in-progress version:\n    http://www.smspower.org/meka/wip\n\n Any development related dicussion are held in a dedicated forum:\n    http://www.smspower.org/forums/viewforum.php?f=7\n\n----------------------------------------------------------------------------\n Level 8 : I am a freak, tell me everything !\n----------------------------------------------------------------------------\n\n Here is a quick description of the ressource files that comes with MEKA:\n\n --MEKA.CFG-- or --MEKAW.CFG--\n This is the configuration file where MEKA stores most of the options\n and user definable parameters. Some are accessible from the interface,\n but some are only available by manually editing this file.\n Most of it should be self explanatory, but here are some comments:\n\n Screenshots and music dump filename templates are configurable using the\n following syntax:\n\n    ...%[.name_max_length]s...%[0number_padding]d.file_format\n\n Where things inside brackets are optional and '...' is anything you want.\n When I say \"anything you want\", you can truly put anything you want, with\n two exceptions:\n  - if you want to use spaces, replace them with asterix (*) characters.\n  - if you want to use %, double them - or be prepared for a crash.\n\n Some examples should make it easier to grasp:\n\n screenshots_filename_template =\n\n  %.5s_%02d.png (DOS default setting)\n  Limit game name to 5 characters and pad capture number to 2 characters.\n  Save file in PNG format.\n  Playing \"Psycho Fox.SMS\" will get you capture filenames such as\n  \"Psych_01.png\" or \"Psych_42.png\".\n\n  %s-%02d.png (Windows & UN*X default setting)\n  Does not limit game name, pad capture number to 2 characters.\n  Save file in PNG format.\n  Playing \"Psycho Fox.SMS\" will get you capture filenames such as\n  \"Psycho Fox-01.png\" or \"Psycho Fox-42.png\".\n\n  %s*(%d).bmp\n  Does not limit game name, and let capture number as it is.\n  Save file in BMP format.\n  Playing \"Psycho Fox.SMS\" will get you capture filenames such as\n  \"Psycho Fox (1).bmp\" or \"Psycho Fox (42).bmp\".\n\n Available file format for screenshots are PNG (default), BMP, PCX, TGA.\n Incorrect use of this feature can leads MEKA to crash in a horrible and\n painful way. You were warned.\n\n --MEKA.BLT--\n This file contains the configuration for fullscreen video modes.\n It is self documented. I strongly suggest giving it a look to enable\n the best video modes for your system (see Level 6 of this documentation).\n Maxim's MEKA Configurator allows you to edit this file easily:\n    http://www.smspower.org/maxim/mconfig/\n\n --MEKA.INP--\n This file contains inputs configuration. It is automatically rewritten by\n MEKA when quitting, and most of its options are available from the GUI.\n However, experienced users may want to tweak with it and try to use some\n of the top-secret options it offers.\n Maxim's MEKA Configurator allows you to edit this file easily:\n    http://www.smspower.org/maxim/mconfig/\n\n --MEKA.MSG--\n This file contains text messages used in MEKA and allows you to create\n translation in new languages or dialect using latin characters.\n An extension to use asian (or other) type of characters is planned but\n unfortunately not to be done very soon.\n\n --MEKA.NAM--\n This file contains the name, product numbers and comments database that\n are used by MEKA.\n\n --MEKA.PAT--\n This file allows you to tell MEKA to apply simple patches to a ROM on\n loading, or to memory (RAM, etc.) an runtime.\n Nothing extraordinary but programmers and hackers will find such feature\n useful. Additionnally, it can be used as a basic cheating functionnality,\n and you can convert Pro Action Replay codes to MEKA patching system easily.\n The file is self documented.\n\n --MEKA.THM--\n This file contains themes available from the user interface. If available\n GUI colors are boring you, this is the place to check. The file is also self\n documented.\n Maxim's MEKA Configurator or Lilac's Wonder Theme allows you to edit this\n file easily. Both tools are linked from MEKA homepage.\n You can also get pictures for uses with some of the default themes at:\n    http://www.smspower.org/meka/themes\n\n --MEKA.DAT--\n This file contains data used by the emulator and its interface. Editing\n it will shows you a bunch of garbage so it is not a really good idea.\n\n----------------------------------------------------------------------------\n Level 9 : Cool things to do when playing games is not enough\n----------------------------------------------------------------------------\n\n Check out http://www.smspower.org and participate to the healthy debates\n on the forum. Also check out the developer section, documentations, homebrew\n games, hardware hacks and various projects being made by the community.\n\n Check out http://www.smspower.org/Music for a great Sega 8-bit music\n archive, informations, tools and a forum.\n\n Check out http://www.smspower.org/meka/wip for latest work-in-progress\n versions of MEKA, with new great features you never dreamed of.\n\n Play Wonder Boy III: The Dragon's Trap over and over until you figure out\n you cannot get bored with it.\n\n If you are unsure about other games to play, here is a personal selection:\n\n  - Sega Game 1000:\n    - The Castle\n    - H.E.R.O.\n    - Ninja Princess\n    - Pitfall II\n\n  - Sega Master System:\n    - Alex Kidd in Miracle World\n    - Aztec Adventure (Nazca '88)\n    - California Games\n    - Cyborg Hunter (Chouon Senshi Borgman)\n    - Double Dragon\n    - Fantasy Zone\n    - Fantasy Zone II - The tears of Opa-Opa\n    - Gangster Town\n    - Golden Axe Warrior\n    - Kenseiden\n    - Kung Fu Kid (Makai Retsuden)\n    - Out Run\n    - Penguin Land (Doki Doki Penguin Land)\n    - Phantasy Star\n    - Power Strike (Aleste)\n    - Power Strike II\n    - Psycho Fox\n    - Rastan\n    - R-Type\n    - Shinobi\n    - Ultima IV\n    - Wonder Boy in Monster Land (Super Wonder Boy Monster World)\n    - Wonder Boy III: The Dragon's Trap (Monster World II)\n    - Y's - The Vanished Omens (Ys)\n    - Zillion\n\n Enjoy!\n\n----------------------------------------------------------------------------\n Level 10 : MEKA was made using...\n----------------------------------------------------------------------------\n\n  Compilers/assemblers:\n  - Microsoft Visual C++\n  - GCC\n  - NASM\n\n  Librairies:\n  - Allegro 5 (video and inputs features), by the Allegro team.\n    http://www.talula.demon.co.uk/allegro/\n  - zlib (compression library), by Jean-loup Gailly and Mark Adler.\n    http://www.gzip.org/zlib/\n  - libpng (PNG file format manipulation), by Guy Eric Schalnat,\n    Andreas Dilger, Glenn Randers-Pehrson and others.\n    http://www.libpng.org/pub/png/libpng.html\n\n  Tools:\n  - UPX (executable compressor), by Markus Oberhumer and Laszlo Molnar.\n    http://upx.sourceforge.net/\n  - Paint Shop Pro 4, to draw icons and graphics, by Jasc Software.\n    http://www.jasc.com/products/\n\n----------------------------------------------------------------------------\n Level 11 : Last Boss\n----------------------------------------------------------------------------\n\n To defeat the Vampire Dragon, stay at the bottom middle of the screen\n and wait for him to come level with you.  When he comes close, jump and\n hit his cape. When he goes down, below the screen, fly up so he won't\n come up and hit you! Repeat this procedure until he is destroyed. You\n will get the SALAMANDER CROSS and be able to change into Hu-Man.\n\n (Written by Clint Dyer, for Sega of America)\n\n----------------------------------------------------------------------------\n Level 12 : End Credits\n----------------------------------------------------------------------------\n\n In addition to people listed as MEKA development contributors at the top of\n this document, I would like to thank the following persons:\n\n Maxim,\n  restless support on countless Sega 8-bit projects and the modern SMS Power! wiki backend.\n  can't list all of them! too many goodness! you used it? he made it.\n  http://www.smspower.org/maxim\n\n Phillip Smith,\n  hardware hacker extraordinary. Designed custom SMS readers and led me\n  to dumping in my early days :)\n\n Mike Gordon,\n  hardware hacker extraordinary. Designed SMS Reader among other stuff.\n  http://www.smspower.org/Development/SMSReader\n\n Andrew Lindsay:\n  hardware hacker extraordinary. Funded The SMS Preservation Society (1996-1997)\n  an inspiring and so prolific website. Designed MKI reader.\n\n Nicolas Warren (Heliophobe),\n  Nicolas is the author of SMEG, SMS emulator for Dreamcast, and has made\n  various contributions to the SMS development scenes such as Tetracycline,\n  Damiana or the Nine Pixels demo. He was a cheery longtime contributor to\n  SMS Power! forums and to be missed. RIP.\n\n Charles Mac Donald,\n  proficient hardware and software hacker, he reverse engineered and\n  documented countless video game hardware.\n  http://cgfm2.emuviews.com\n\n Casiopea, Masato, RedS, Sankichi, Skyhigh, Toshi, Yakmo, Yoneda, Yujiro,\n  japanese friends and protector of Sega 8-bit love on the archipel.\n  lots of invaluable support, dumps, fun, game trading and friendlyness.\n  http://bto8.smspower.org (Casiopea)\n  http://www.loose-logic.com (Masato)\n  http://bto8.smspower.org/segapower (Toshi)\n  http://village.infoweb.ne.jp/~fwik0826/ (Yoneda Mitsunori)\n  http://www.geocities.co.jp/Playtown-Denei/8588/ (Yujiro)\n\n David Michel,\n Nicolas Hamel,\n Richard Bush,\n Nicolas Lannier,\n James McKay,\n  invaluable help and inspiration in my early emulation/programming days.\n\n Eric Quinn,\n  http://www.smspower.org/seganotebook/\n\n Marc Le Douarain,\n  for help with SF-7000 emulation and dumps of his old disks.\n  http://membres.multimania.fr/mavati/sf7000/\n\n Youltar,\n  for his general support, SmsCartPad adapters, 3-D glasses and rapid fire\n  schematics, artworks.\n  http://www.smspower.org/smscartpad\n\n Westone team,\n  for making Wonder Boy III: The Dragon's Trap - such a lovely game :)\n  http://www.westone.co.jp\n\n Lasse Reinikainen & Image/Helsinki/Finland, Emilie Skog, Marat Fayzullin,\n Ricardo Bittencourt, Martin Konrad, Anonymous Jon, Super Majik Spiral Crew,\n Richard Talbot Watkins, Sean Young, MrLee, Billy Jr, Richard Mitton,\n Leonard Silva de Oliveira, Flavio Morsoletto, Charles Doty, Leonardo Pires,\n Christopher Coleman, MXS, Sam Pettus, Chris White, Jonathan Griffith, Puyolin,\n Olivier Aichelbaum (ACBM), Dominique Toussaint, friends and family etc.\n\n Everybody who supported MEKA, SMS Power! or just loves the SMS!\n And of course thanks to SEGA!\n\n----------------------------------------------------------------------------\n  .         .              .            .          .        .         .\n     Goodnight Brave Warrior,   .             .                  .\n   . Goodnight Monster-land.         .            .    .      .           .\n       .        .     .         .         .               .        .\n .        __________      .            .            .                  .\n    .    /          \\        .    .          .           .          .\n        |____________|     .            .                       .        .\n .       |     ___  |           .                .      .             .\n      .  |    |   | |   .     .       .     .                .\n  .      |    |   | |             .                .                .   .\n----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/multi.txt",
    "content": "-----------------------------------------------------------------------------\r\n MEKA - Multiplayer Games List\r\n-----------------------------------------------------------------------------\r\n Please e-mail me in case you notice any mistake or missing game.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA MASTER SYSTEM (SMS)\r\n-----------------------------------------------------------------------------\r\n MULTIPLAYER GAMES\r\n-----------------------------------------------------------------------------\r\n Note: this list also includes games where players have to alternate, if the\r\n multiplayer mode is actually designed that way (eg: events in sports games).\r\n-----------------------------------------------------------------------------\r\n American Baseball                                      2P\r\n American Pro Football                                  2P\r\n Andre Agassi Tennis                                    2P\r\n Ashura                                                 2P\r\n Basket Ball Nightmare                                  2P\r\n Battlemaniacs                                          2P\r\n Bubble Bobble                                          2P\r\n Buggy Run                                              2P\r\n California Games                                       8P\r\n California Games II                                    8P\r\n Champions of Europe                                    2P\r\n Columns                                                2P\r\n Cosmic Spacehead (mini games)                          2P\r\n Cyborg Z                                               2P\r\n Dodgeball King                                         2P\r\n Double Dragon                                          2P\r\n Double Hawk                                            2P\r\n Double Target: Cynthia no Nemuri                       2P\r\n Dr. Robotnik's Mean Bean Machine                       2P\r\n Dragon - The Bruce Lee Story                           2P\r\n Family Games                                           4P\r\n Fantasy Zone: The Maze                                 2P\r\n Final Bubble Bobble                                    2P\r\n F1                                                     2P\r\n Gain Ground                                            2P\r\n Galactic Protector                                     2P      Paddle Control\r\n Game Box Esportes Radicais                             8P\r\n Gangster Town                                          2P      Light Phaser\r\n Gauntlet                                               2P\r\n George Foreman's KO Boxing                             2P\r\n Gokuaku Doumei Dump Matsumoto                          2P\r\n Golfamania                                             2P\r\n GP Rider                                               2P\r\n Great Baseball                                         2P\r\n Great Basketball                                       2P\r\n Great Football                                         2P\r\n Great Golf                                             4P\r\n Great Ice Hockey                                       2P      Sports Pad\r\n Great Soccer                                           2P\r\n Great Volleyball                                       2P\r\n Heavyweight Champ                                      2P\r\n James \"Buster\" Douglas Knockout Boxing                 2P\r\n Joe Montana Football                                   2P\r\n Jogos de Verão II                                      8P\r\n Masters of Combat                                      2P\r\n Micro Machines                                         2P\r\n Monopoly                                               10P\r\n Mortal Kombat                                          2P\r\n Mortal Kombat II                                       2P\r\n Mortal Kombat 3                                        2P\r\n Ms. Pac-Man                                            2P\r\n NBA Jam                                                2P\r\n Nekkyuu Koushien                                       2P\r\n Opa Opa                                                2P\r\n Parlour / Party Games                                  4P\r\n Pat Riley Basketball [Proto]                           2P\r\n PGA TOUR Golf                                          4P\r\n Pit Fighter                                            2P\r\n Pro Wrestling                                          2P\r\n Putt & Putter                                          2P\r\n Quartet                                                2P\r\n Rambo - First Blood Part II                            2P\r\n Rampage                                                2P\r\n Rampart                                                2P\r\n R.C. Grand Prix                                        4P\r\n Reggie Jackson Baseball                                2P\r\n Rocky                                                  2P\r\n Sangokushi 3                                           2P\r\n Satellite 7                                            2P\r\n Scramble Spirits                                       2P\r\n Secret Command                                         2P\r\n Sega Chess                                             2P\r\n Sega World Tournament Golf                             4P\r\n Sensible Soccer                                        2P\r\n Slap Shot                                              2P\r\n Smash TV                                               2P\r\n Speedball                                              2P\r\n Speedball 2                                            2P\r\n Sports Pad Football                                    2P      Sports Pad\r\n Sports Pad Soccer                                      2P      Sports Pad\r\n Spy vs Spy                                             2P\r\n Street Fighter II'                                     2P\r\n Summer Games                                           8P\r\n Super Kick Off                                         2P\r\n Super Monaco GP                                        2P\r\n Super Off Road                                         2P\r\n Super Space Invaders                                   2P\r\n Super Tennis                                           2P\r\n Super Tetris                                           2P\r\n Tennis Ace                                             2P\r\n The Pro Yakyuu Pennant Race                            2P\r\n Time Soldiers                                          2P\r\n Trivial Pursuit Genus Edition                          6P\r\n Ultimate Soccer                                        2P\r\n Walter Payton Football                                 2P\r\n Wimbledon                                              2P\r\n Wimbledon II                                           2P\r\n Winter Olympics                                        4P\r\n World Class Leaderboard                                4P\r\n World Cup Italia '90                                   2P\r\n World Cup '93 (Tecmo)                                  2P\r\n World Cup USA 94                                       2P\r\n World Games                                            4P\r\n World Soccer                                           2P      (Sports Pad)\r\n WWF WrestleMania Steel Cage Challenge                  2P\r\n-----------------------------------------------------------------------------\r\n GAMES WITH PLAYER ALTERNATING POSSIBILITY\r\n-----------------------------------------------------------------------------\r\n Note: games marked in the list above are not repeated there.\r\n-----------------------------------------------------------------------------\r\n Action Fighter                                         2P\r\n Alien 3                                                2P\r\n Alien Syndrome                                         2P\r\n Asterix                                                2P\r\n Asterix and the Secret Mission                         2P\r\n Astro Flash                                            2P\r\n Astro Warrior                                          2P\r\n Astro Warrior / Pit Pot                                2P\r\n Black Belt                                             2P\r\n Chapolim x Drácula - Um Duelo Assustador               2P\r\n Choplifter                                             2P\r\n Cloud Master                                           2P\r\n Comical Machine Gun Joe                                2P\r\n Fantasy Zone                                           2P\r\n Fushigi no Oshiro Pit Pot                              2P\r\n Geraldinho                                             2P\r\n Ghost House                                            2P\r\n Hang On / Astro Warrior (Astro Warrior only)           2P\r\n Hokuto No Ken                                          2P\r\n Incredible Crash Dummies, The                          2P\r\n Kung Fu Kid                                            2P\r\n Makai Retsuden                                         2P\r\n My Hero                                                2P\r\n Renegade                                               2P\r\n Road Rash                                              2P\r\n Rygar                                                  2P\r\n Sapo Xulé O Mestre do Kung Fu                          2P\r\n Sapo Xulé S.O.S. Lagoa Poluída                         2P\r\n Seishun Scandal                                        2P\r\n Sitio do Picapau Amarelo                               2P\r\n Teddy Boy                                              2P\r\n Teddy Boy Blues                                        2P\r\n The Ninja                                              2P\r\n TransBot                                               2P\r\n TV Colosso (As Aventuras da)                           2P\r\n Wonder Boy                                             2P\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SEGA GAME 1000 (SG-1000) & OTHELLO MULTIVISION (OMV)\r\n-----------------------------------------------------------------------------\r\n MULTIPLAYER GAMES\r\n-----------------------------------------------------------------------------\r\n Champion Baseball                                      2P\r\n Champion Billiards                                     2P\r\n Champion Boxing                                        2P\r\n Champion Golf                                          2P\r\n Champion Ice Hockey                                    2P\r\n Champion Kendou                                        2P\r\n Champion Pro Wrestling                                 2P\r\n Champion Soccer                                        2P\r\n Champion Tennis                                        2P\r\n Home Mah-Jong                                          2P\r\n Hyper Sports (Konami no)                               2P\r\n Okamoto Ayako no Match Play Golf                       2P\r\n Othello                                                2P\r\n-----------------------------------------------------------------------------\r\n GAMES WITH PLAYER ALTERNATING POSSIBILITY\r\n-----------------------------------------------------------------------------\r\n Note: games marked in the list above are not repeated there.\r\n-----------------------------------------------------------------------------\r\n Bank Panic                                             2P\r\n Bomb Jack                                              2P\r\n Chack'n Pop                                            2P\r\n Choplifter                                             2P\r\n Doki Doki Penguin Land                                 2P\r\n Dragon Wang                                            2P\r\n Elevator Action                                        2P\r\n Exerion                                                2P\r\n Gulkave                                                2P\r\n H.E.R.O.                                               2P\r\n James Bond 007                                         2P\r\n Ninja Princess                                         2P\r\n Pitfall II                                             2P\r\n Pop Flamer                                             2P\r\n Rock n' Bolt                                           2P\r\n Sega Flipper                                           2P\r\n Sega Galaga                                            2P\r\n Shinnyushain Tooru Kun (Konami no)                     2P\r\n Sindbab Mystery                                        2P\r\n Space Armor                                            2P\r\n Space Invaders                                         2P\r\n Space Mountain                                         2P\r\n Space Slalom                                           2P\r\n Star Jacker                                            2P\r\n Super Tank                                             2P\r\n Wonder Boy                                             2P\r\n Yamato                                                 2P\r\n Zoom 909                                               2P\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n OTHER SYSTEMS\r\n-----------------------------------------------------------------------------\r\n <uncomplete>\r\n-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/setup.bat",
    "content": "@echo off\r\nmekaw.exe /setup\r\n"
  },
  {
    "path": "meka/sources.txt",
    "content": "----------------------------------------------------------------------------\r\n MEKA Sources\r\n Short guide to compilation, first-time hacking and various technical notes\r\n----------------------------------------------------------------------------\r\n Quick links:\r\n - Homepage:    http://www.smspower.org/meka\r\n - Forum:       http://www.smspower.org/forums/viewforum.php?f=7\r\n - SVN:         svn://svn.smspower.org/svn/meka\r\n - SVN Trunk:   svn://svn.smspower.org/svn/meka/trunk/meka\r\n----------------------------------------------------------------------------\r\n Also refer to TODO.txt file for a (messy) list of possible improvements.\r\n----------------------------------------------------------------------------\r\n\r\n---------------------------------------------------------------------------\r\n Note to the knowledge-savy person:\r\n - MEKA FEATURES INCORRECT EMULATION BEHAVIOURS.\r\n - MEKA IS NOT THE BEST REFERENCE OF HOW THINGS ARE OR WORKS.\r\n MEKA is an old piece of software, most of which was essentially written\r\n pre-2000. Although MEKA is still competitive in term of available features,\r\n newer emulators are generally more accurate emulation-wise.\r\n The SMS Power! development Forums and Wiki are a betterd place to share\r\n up to date knowledge about hardware and emulation.\r\n---------------------------------------------------------------------------\r\n\r\n---------------------------------------\r\n MEKA License\r\n---------------------------------------\r\n\r\nApplies to hq2x.c, hq2x16.asm, hq2x32.asm:\r\n\r\n  HQ2X is originally distributed under GPL license, which legally would\r\n  not fit in MEKA (with its current license). An alternate license has\r\n  been requested to the author, Maxim Stephin, who answered:\r\n\r\n    \"Ah, just use it... I don't care much about legal stuff.\r\n     As long as it's not used in a commercial product, of course.\"\r\n\r\n  Overidding GPL terms.\r\n  commercial usage).\r\n\r\nApply to all code by Omar Cornut (see MEKA.txt)\r\n\r\n #1 This source code comes free, without any warantee given.\r\n\r\n #2 Any modification of this software must have this license preserved,\r\n    and source code made available under the same condition.\r\n\r\n #3 Reuse of program source code and data authorized for any purpose.\r\n\r\nApply to everything else:\r\n\r\n  Unlicensed. Gray area. Kernel Panic. Ahah!\r\n\r\nPlease contact us for any question.\r\n\r\n\r\n---------------------------------------\r\nINDEX\r\n---------------------------------------\r\n\r\n- Before anything else...\r\n- Introduction\r\n- Technology\r\n- Source repository\r\n- How to Compile\r\n- How to create distribution packages\r\n- Hope\r\n\r\n---------------------------------------\r\n Before anything else...\r\n---------------------------------------\r\n\r\nThis document is only a quick introduction to some aspect of MEKA development.\r\nFor any further discussion, please visit MEKA development forum:\r\n\r\n        http://www.smspower.org/forums/viewforum.php?f=7\r\n\r\nI'd be happy to discuss anything over there, answers questions, and see\r\nhow we can all work together in a happy world while holding hands and\r\nplaying games using yet another hand.\r\n\r\n\r\n---------------------------------------\r\n Introduction\r\n---------------------------------------\r\n\r\nMEKA has been in development since summer 1998 (it was actually my first\r\nproper project using C as programming language), and most of its codebase\r\nwas written in 1998-2000, an era when MEKA was a closed source software.\r\n\r\nThat is to say that although MEKA is now free software and open-source,\r\nit hasn't been developed under this premise, and the code is pretty much\r\nthe work of a disturbed adolescent mind learning its way around programming.\r\n\r\nIn the past decade most of my energy has been put toward other projects,\r\nbut MEKA still gets some occasional love and care. May the code be useful\r\nand hope some people can contribute in keeping MEKA an up to date software\r\nand making it better.\r\n\r\n\r\n---------------------------------------\r\n Technology\r\n---------------------------------------\r\n\r\nSee MEKA.TXT documentation, chapter 11, for a summary of the various\r\nlibrairies and technologies used by MEKA.\r\n\r\n\r\n---------------------------------------\r\n Source repository\r\n---------------------------------------\r\n\r\nMEKA code is hosted on a public Subversion (SVN) repository.\r\n\r\nSVN repository  @ svn://svn.smspower.org/svn/meka\r\nSVN trunk       @ svn://svn.smspower.org/svn/meka/trunk/meka\r\n\r\nAnonymous login allows read-only access.\r\n\r\nPlease e-mail me patches and they will be applied if deemed useful.\r\n\r\nSVN write accesses are granted on a per-user basis.\r\nI am totally open to giving access to people demonstrating their value\r\nto the project.\r\n\r\n\r\n---------------------------------------\r\n How to Compile\r\n---------------------------------------\r\n\r\nNote: Several of the libraries belows are patched or compiled with\r\nspecific settings on my computer. This is for the main purpose of\r\nlinking required libraries along with the executable, while stripping\r\nunused features. You may not need that, just keep in mind that your\r\nexecutables may be bigger than the ones provided on MEKA homepage.\r\n\r\nI. Compile for Microsoft Windows:\r\n\r\n - Requires Microsoft Visual Studio 2008 (9.0) C++ compiler.\r\n - MEKA solution is located in srcs\\projects\\msvc\\Meka.sln\r\n\r\nII. Compile for GNU/Linux and other UN*X based systems:\r\n\r\n - You are smart guys, you can figure it out!\r\n - Install Allegro library, latest WIP.\r\n   - https://www.allegro.cc/\r\n   - $ ./configure --enable-static\r\n   - $ make\r\n   - $ make install\r\n   - $ For Ubuntu see notes on Allegro website\r\n - Compile !\r\n   - Use provided Makefile.\r\n - Contact us thru the forum for any help. :)\r\n\r\n\r\n---------------------------------------\r\n How to create distribution packages\r\n---------------------------------------\r\n\r\nNote: require 'make', 'zip' and 'upx'\r\n\r\nIn trunk/ directory (the directory containing the executable):\r\n\r\n# make -f srcs/Makefile dist_src\r\n# make -f srcs/Makefile dist_bin_win32\r\n# make -f srcs/Makefile dist_bin_unix\r\n\r\n---------------------------------------\r\n Just getting started!\r\n---------------------------------------\r\n\r\nHave fun!\r\n\r\n----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/Makefile",
    "content": "#------------------------------------------------------\r\n# MEKA - Makefile\r\n#------------------------------------------------------\r\n# Best viewed with TAB=4\r\n#------------------------------------------------------\r\n# Use 'help' rule ('make help') to get command line help.\r\n# Read SOURCES.TXT for help compiling.\r\n#------------------------------------------------------\r\n\r\n#------------------------------------------------------\r\n# MEKA may be difficult to compile! Refer to documentation.\r\n# The build process was made for my own usage of my own computer,\r\n# and there might be some leftover of that time (hardcoded paths,\r\n# hand modified libraries...). \r\n# Of course, MEKA should be leaning toward ease of compilation, \r\n# so feel free to comment or correct things.\r\n#------------------------------------------------------\r\n# May require those environment variables:\r\n#   DXSDKDIR    Set to DirectX SDK directory [win32]\r\n#   NASM        Set to NASM executable\r\n#   ZLIBDIR     Set to ZLIB directory\r\n#   LIBPNGDIR   Set to LIBPNG directory\r\n# Beware that the Makefile won't notify you if one of them\r\n# if used (will use empty strings, can cause compilation error)\r\n#------------------------------------------------------\r\n\r\n#------------------------------------------------------\r\n# System target to compile MEKA for (dos|unix|win32)\r\n# All systems must currently run on X86 architecture.\r\n# - unix  : UN*X system. Makefile up to date. May require system/library tweaking.\r\n# - win32 : Windows 32-bits. Makefile NOT up to date (can be updated). Hard-coded paths. Prefer using MsVc\\Meka.sln (MSVC++ 7.1)\r\n# - dos   : MS-DOS or compatible. Could work. Not maintained anymore.\r\n# TODO: Add command-line parameter to select this\r\n#------------------------------------------------------\r\n\r\n# code found on:\r\n# http://stackoverflow.com/questions/714100/os-detecting-makefile\r\n# Did not try to detect DOS, maybe this link can help:\r\n# http://www.opensource.apple.com/source/X11proto/X11proto-57/freetype/freetype-2.4.4/builds/dos/detect.mk\r\nifeq ($(OS),Windows_NT)\r\n\tSYSTEM = win32\r\nelse\r\n\tUNAME_S := $(shell uname -s)\r\n\tifeq ($(UNAME_S),Linux)\r\n\t    SYSTEM = unix\r\n\tendif\r\n\tifneq (,($findstring BSD,$(UNAME_S)))\r\n\t    SYSTEM = unix\r\n\tendif\r\n\tifeq ($(UNAME_S),Darwin)\r\n\t    SYSTEM = macosx\r\n\tendif\r\nendif\r\n\r\n#------------------------------------------------------\r\nBUILD = release\r\n# BUILD = debug\r\n#------------------------------------------------------\r\nOBJCFLAGS = \"\"\r\n\r\n#---[ DOS/DJGPP ]--------------------------------------\r\nifeq ($(SYSTEM), dos)\r\n#--- Executable name\r\nEXE     = ../meka.exe\r\n#--- Output directory\r\nOD      = obj\r\n#--- Compilation\r\nCC      = gcc -Werror\r\nCC_OUT  = -o\r\nLINKER  = gcc\r\nASM     = nasm\r\nOTYPE   = coff\r\n#--- Tools\r\nRM      = rm\r\nMV      = ren\r\nMKDIR   = mkdir\r\n#--- Definitions\r\nDEF_OS  = -DARCH_DOS\r\nINC_OS  = -I$(LIBPNGDIR) -I$(ZLIBDIR)\r\n#--- Libraries\r\nLIB_OS  = -lm -L$(LIBPNGDIR)\r\nALL_FILES=*.*\r\nendif\r\n\r\n#---[ UNIX/GCC ]---------------------------------------\r\nifeq ($(SYSTEM), unix)\r\n#--- Executable name\r\nEXE     = ../meka\r\n#--- Output directory\r\nOD      = obj\r\n#--- Compilation\r\nCC      = g++\r\nCC_OUT  = -o\r\nLINKER  = g++\r\nASM     = nasm\r\nOTYPE   = elf\r\nifeq (FreeBSD,$(UNAME_S))\r\nCC      = c++\r\nLINKER  = c++\r\nendif\r\n#--- Tools\r\nRM      = rm\r\nMV      = mv\r\nMKDIR   = mkdir\r\n#--- Definitions\r\nDEF_OS  = -DARCH_UNIX -DASM_SYMBOLS_REQUIRE_UNDERSCORE\r\nINC_OS  = -Ilibs -I../include\r\nINC_OS  += $(shell pkg-config --cflags allegro-5)\r\n#--- Libraries\r\nLIB_OS  = \r\nALL_FILES=*\r\nendif\r\n\r\n#---[ MACOSX/Clang ]---------------------------------------\r\nifeq ($(SYSTEM), macosx)\r\n#--- Executable name\r\nEXE     = ../meka\r\n#--- Output directory\r\nOD      = obj\r\n#--- Compilation\r\nCC      = clang++\r\nCC_OUT  = -o\r\nLINKER  = clang++\r\nASM     = nasm\r\nOTYPE   = macho\r\n#--- Tools\r\nRM      = rm\r\nMV      = mv\r\nMKDIR   = mkdir\r\n#--- Definitions\r\nDEF_OS  = -DARCH_MACOSX -DUNIX\r\nINC_OS  = -Ilibs -I../include -I/usr/local/include\r\n#--- Libraries\r\nLIB_OS = -l freetype -framework OpenGL -framework CoreFoundation -framework OpenAL -framework AudioToolbox -framework AppKit -framework IOKit -framework Foundation\r\nLIB_PATHS = -L/usr/local/lib\r\nALL_FILES=*.*\r\n#--- Platform specific object\r\nOBJ_PLATFORM = $(OD)/platform/macosx/osxhelpers.o\r\nendif\r\n\r\n#---[ WINDOWS/MSVC ]-----------------------------------\r\nifeq ($(SYSTEM), win32)\r\n#--- Executable name\r\nEXE     = ../mekaw.exe\r\n#--- Output directory\r\nOD      = objw\r\n#--- Compilation\r\nCC      = runner.exe cl @ -nologo\r\nCC_OUT  = -Fo\r\nLINKER  = runner.exe link @\r\nASM     = nasmw\r\nOTYPE   = win32\r\n#--- Tools\r\nRM      = rm\r\nMV      = mv\r\nMKDIR   = md\r\nRC      = rc\r\n\r\n#--- Definitions\r\nDEF_OS  = -DARCH_WIN32\r\nINC_OS  = -I$(LIBPNGDIR) -I$(ZLIBDIR)\r\n\r\n#--- Libraries\r\nLIB_OS          = kernel32.lib user32.lib gdi32.lib comdlg32.lib ole32.lib ddraw.lib winmm.lib dsound.lib dinput.lib dxguid.lib\r\nLIB_PATHS       = -libpath:$(MSVCDIR)/lib/ -libpath:$(MSVCDIR)/PlatformSDK/lib/ -libpath:$(DXSDKDIR)/lib\r\n\r\n#--- Resources\r\nRESSOURCES = mekaw.res\r\n\r\nALL_FILES=*.*\r\nendif\r\n\r\n#-----------------------------------------------------\r\n# Option : Sound emulation and output\r\n#-----------------------------------------------------\r\nOBJ_SOUND = $(OD)/sound/sound.o $(OD)/sound/s_misc.o $(OD)/sound/sound_logging.o $(OD)/sound/psg.o $(OD)/sound/fmeditor.o $(OD)/sound/wav.o $(OD)/sound/vgm.o $(OD)/sound/fmunit.o\r\nOBJ_SOUND += $(OD)/sound/emu2413/emu2413.o $(OD)/sound/emu2413/mekaintf.o\r\n\r\n#-----------------------------------------------------\r\n# Option : ZIP support\r\n#-----------------------------------------------------\r\nOBJ_ZIP = $(OD)/unzip.o\r\nifneq ($(SYSTEM), win32)\r\nLIB_ZIP = -lz\r\nelse\r\nLIB_ZIP = $(ZLIBDIR)/zlibs.lib\r\nendif\r\n#-----------------------------------------------------\r\n\r\n#-----------------------------------------------------\r\n# Option : PNG Support\r\n#-----------------------------------------------------\r\nOBJ_PNG = \r\nifneq ($(SYSTEM), win32)\r\nLIB_PNG = -lpng\r\nelse\r\nLIB_PNG = $(LIBPNGDIR)/libpng.lib\r\nendif\r\n#-----------------------------------------------------\r\n\r\n#-----------------------------------------------------\r\n# Libraries\r\n#-----------------------------------------------------\r\n\r\n# Allegro\r\nifeq ($(SYSTEM), dos)\r\nLIB_ALLEG = -lalleg\r\nendif\r\n\r\nifeq ($(SYSTEM), unix)\r\nLIB_ALLEG = `pkg-config --cflags --libs allegro-5 allegro_image-5 allegro_audio-5 allegro_font-5 allegro_primitives-5 allegro_ttf-5`\r\nendif\r\n\r\nifeq ($(SYSTEM), macosx)\r\nLIB_ALLEG = -lallegro -lallegro_font -lallegro_audio -lallegro_primitives -lallegro_main -lallegro_image -lallegro_ttf\r\nendif\r\n\r\nifeq ($(SYSTEM), win32)\r\nLIB_ALLEG = alleg_s.lib\r\nendif\r\n\r\n# Full library list\r\nifeq ($(SYSTEM), win32)\r\nLIB = $(LIB_PATHS) $(RESSOURCES)\r\nLIB += $(LIB_ALLEG) $(LIB_SOUND) $(LIB_ZIP) $(LIB_OS) -nodefaultlib:msvcrt\r\nelse\r\nLIB = $(LIB_PATHS) $(LIB_ALLEG) $(LIB_SOUND) $(LIB_OS) $(LIB_PNG) $(LIB_ZIP)\r\nendif\r\n\r\n#-----------------------------------------------------\r\n# Objects to create and link\r\n#-----------------------------------------------------\r\n\r\nOBJ_GUI   = $(OD)/gui.o $(OD)/g_action.o $(OD)/g_box.o $(OD)/g_menu.o $(OD)/g_menu_i.o $(OD)/g_menu_t.o $(OD)/g_mouse.o $(OD)/g_init.o $(OD)/g_tools.o $(OD)/g_widget.o $(OD)/g_update.o $(OD)/desktop.o $(OD)/skin.o $(OD)/skin_bg.o $(OD)/skin_fx.o\r\nOBJ_GAPPS = $(OD)/app_cheatfinder.o $(OD)/app_filebrowser.o $(OD)/app_game.o $(OD)/app_options.o $(OD)/textbox.o $(OD)/app_mapview.o $(OD)/app_tileview.o $(OD)/app_textview.o $(OD)/app_techinfo.o $(OD)/app_memview.o $(OD)/app_palview.o $(OD)/app_about.o\r\nOBJ_EMU   = $(OD)/mainloop.o $(OD)/ioports.o $(OD)/commport.o $(OD)/vmachine.o $(OD)/bios.o $(OD)/country.o $(OD)/bmemory.o $(OD)/mappers.o $(OD)/eeprom.o $(OD)/beam.o $(OD)/tvtype.o\r\nOBJ_INP   = $(OD)/inputs.o $(OD)/inputs_c.o $(OD)/inputs_f.o $(OD)/inputs_i.o $(OD)/inputs_t.o $(OD)/inputs_u.o $(OD)/lightgun.o $(OD)/periph.o $(OD)/rapidfir.o $(OD)/tvoekaki.o $(OD)/glasses.o $(OD)/sk1100.o\r\nOBJ_FEAT  = $(OD)/checksum.o $(OD)/db.o $(OD)/vlfn.o $(OD)/patch.o $(OD)/saves.o\r\nOBJ_CFG   = $(OD)/config.o\r\nOBJ_MISC  = $(OD)/allegro4to5.o  $(OD)/misc.o $(OD)/build.o $(OD)/fonts.o $(OD)/file.o $(OD)/data.o $(OD)/tools.o $(OD)/keyinfo.o $(OD)/drivers.o $(OD)/message.o $(OD)/capture.o $(OD)/errors.o $(OD)/sdsc.o $(OD)/setup.o $(OD)/libmisc.o $(OD)/libparse.o\r\n#OBJ_BLIT  = $(OD)/blit.o $(OD)/blitintf.o $(OD)/hq2x.o $(OD)/hq2x16.o $(OD)/hq2x32.o\r\nOBJ_BLIT  = $(OD)/blit.o $(OD)/blitintf.o $(OD)/hq2x.o\r\nOBJ_CPU   = $(OD)/machine.o $(OD)/cpu.o\r\nOBJ_VIDEO = $(OD)/video.o $(OD)/video_m2.o $(OD)/video_m5.o $(OD)/video_c.o $(OD)/vdp.o $(OD)/palette.o $(OD)/effects.o $(OD)/fskipper.o\r\nOBJ_MACH  = $(OD)/sg1ksc3k.o $(OD)/sf7000.o $(OD)/coleco.o $(OD)/fdc765.o\r\n\r\n#-----------------------------------------------------\r\n# Includes directory\r\n#-----------------------------------------------------\r\nINCLUDES = -I. $(INC_OS)\r\n\r\n#-----------------------------------------------------\r\n# Preprocessor Definitions\r\n#-----------------------------------------------------\r\nDEFINES = $(DEF_OS)\r\n# DEFINES += -DDEBUG_WHOLE\r\n# DEFINES += -DDEBUG_IO\r\n# DEFINES += -DDEBUG_PAGES\r\n# DEFINES += -DDEBUG_MEM\r\n# DEFINES += -DDEBUG_VDP\r\n# DEFINES += -DDEBUG_PALETTE\r\n\r\n#-----------------------------------------------------\r\n# Option : Debugger\r\n#-----------------------------------------------------\r\nOBJ_CPU += $(OD)/debug.o $(OD)/debugger.o $(OD)/debughelper.o $(OD)/datadump.o\r\n\r\n#-----------------------------------------------------\r\n# Compiler Flags\r\n#-----------------------------------------------------\r\nifeq ($(SYSTEM), win32)\r\n# Win32\r\n# (Note:TARGET unsupported for Win32 makefile compilation)\r\nCFLAGS = -W2 -Gd -Ox -GB -MT\r\nelse\r\n\r\n# UNIX/MS-DOS/MAC\r\nifndef CFLAGS\r\n\r\n# RELEASE build\r\nifeq ($(BUILD), release)\r\nCFLAGS = -Wall -O3 -ffast-math -fno-strength-reduce -funroll-all-loops -fomit-frame-pointer -x c++\r\nendif\r\n\r\n# DEBUG build\r\nifeq ($(BUILD), debug)\r\nCFLAGS = -Wall -g -ggdb\r\nendif\r\nCFLAGS += -Wno-ignored-optimization-argument\r\nCFLAGS += -Wno-deprecated-register\r\n\r\nendif\r\n\r\nendif\r\n\r\nCFLAGS += $(INCLUDES) $(DEFINES)\r\n\r\n#-----------------------------------------------------\r\n# Z80 CPU Cores\r\n#-----------------------------------------------------\r\n\r\nOBJ_CPU += $(OD)/z80marat.a\r\n\r\n#-----------------------------------------------------\r\n# Complete Objects List\r\n#-----------------------------------------------------\r\nOBJ_MEKA = $(OD)/meka.o $(OBJ_CPU) $(OBJ_VIDEO) $(OBJ_EMU) $(OBJ_INP) $(OBJ_FEAT) $(OBJ_MISC) $(OBJ_CFG) $(OBJ_GUI) $(OBJ_GAPPS) $(OBJ_SOUND) $(OBJ_MACH) $(OBJ_ZIP) $(OBJ_PNG) $(OBJ_BLIT) $(OBJ_TOOLS) $(OBJ_LIBS) $(OBJ_PLATFORM)\r\n\r\n#-----------------------------------------------------\r\n# Linking Rule\r\n#-----------------------------------------------------\r\nexe : makedir $(EXE)\r\n\r\n$(EXE)  : $(OBJ_MEKA)\r\nifneq ($(SYSTEM), win32)\r\n\t$(LINKER) -o $@ $(OBJ_MEKA) $(LIB)\r\nelse\r\n\t$(LINKER) -nologo -release -subsystem:windows -out:$@ -section:.text,erw -section:.data,erw -section:.bss,erw $(OBJ_MEKA) $(LIB)\r\nendif\r\n\r\n#-----------------------------------------------------\r\n# Compiling Rules\r\n#-----------------------------------------------------\r\n\r\n# Custom Dependencies\r\n$(OD)/gui.o : gui.cpp gui.h shared.h meka.h\r\n$(OD)/build.o : build.cpp\r\n$(OD)/g_menu.o : g_menu.cpp g_menu.h g_menu_t.cpp g_menu_t.h g_menu_i.cpp g_menu_i.h\r\n$(OD)/g_menu_i.o : g_menu.cpp g_menu.h g_menu_t.cpp g_menu_t.h g_menu_i.cpp g_menu_i.h\r\n$(OD)/g_menu_t.o : g_menu.cpp g_menu.h g_menu_t.cpp g_menu_t.h g_menu_i.cpp g_menu_i.h\r\n# $(OD)/cpu.o : cpu.cpp cpu.h shared.h meka.h\r\n# $(OD)/palette.o : palette.cpp palette.h video.h shared.h meka.h\r\n# $(OD)/inputs.o : inputs.cpp inputs.h keyboard.cpp keyboard.h keyb_map.h\r\n# $(OD)/data.o : data.cpp data.h g_colors.h\r\n\r\n# CPU emulators related compilation\r\n$(OD)/z80marat.a : z80marat/Z80.cpp z80marat/Z80.h z80marat/Codes.h z80marat/CodesED.h z80marat/CodesCB.h z80marat/CodesXX.h z80marat/Tables.h z80marat/CodesXCB.h z80marat/Debug.cpp z80marat/Z80Call.cpp z80marat/Z80DebugHelpers.cpp\r\n\t$(CC) $(CFLAGS) -c z80marat/Z80.cpp $(CC_OUT)$@\r\n\r\n$(OD)/debug.o : z80marat/Debug.cpp z80marat/Z80.h\r\n\t$(CC) $(CFLAGS) -c z80marat/Debug.cpp $(CC_OUT)$@\r\n\r\n$(OD)/debughelper.o : z80marat/Z80DebugHelpers.cpp z80marat/Z80.h\r\n\t$(CC) $(CFLAGS) -c z80marat/Z80DebugHelpers.cpp $(CC_OUT)$@ \r\n\r\n# Generic Rules\r\n\r\n$(OD)/%.o : %.cpp %.h\r\n\t$(CC) $(CFLAGS) -c $< $(CC_OUT)$@\r\n\r\n$(OD)/%.o : %.c %.h\r\n\t$(CC) $(CFLAGS) -c $< $(CC_OUT)$@\r\n\r\n$(OD)/%.o : %.asm\r\n\t$(ASM) $(DEF_OS) -f $(OTYPE) $< -o $@\r\n\r\n$(OD)/%.a : %.asm\r\n\t$(ASM) $(DEF_OS)-f $(OTYPE) $< -o $@\r\n\r\n$(OD)/sound/%.o : sound/%.cpp sound/%.h\r\n\t$(CC) $(CFLAGS) -c $< $(CC_OUT)$@\r\n\r\n$(OD)/platform/macosx/%.o : platform/macosx/%.mm platform/macosx/%.h\r\n\t$(CC) $(OBJCFLAGS) -c $< $(CC_OUT)$@\r\n\r\n#-----------------------------------------------------\r\n# Help\r\n#-----------------------------------------------------\r\n\r\nhelp :\r\n\t@echo \"Rules:\"\r\n\t@echo \"  exe             - Build executable, independent of platform\"\r\n\t@echo \"  dist            - Build sources and binary distribution\"\r\n\t@echo \"  dist_src        - Build sources distribution\"\r\n\t@echo \"  dist_bin_dos    - Build binary DOS distribution\"\r\n\t@echo \"  dist_bin_win32  - Build binary Win32 distribution\"\r\n\t@echo \"  dist_bin_unix   - Build binary UNIX distribution\"\r\n\t@echo \"  clean           - Clean most object files (excluding z80 stuff, etc.)\"\r\n\t@echo \"  clean_all       - Clean object files\"\r\n\t@echo \"  makedir         - Create output directories\"\r\n\r\n#-----------------------------------------------------\r\n# Distribution\r\n#-----------------------------------------------------\r\n\r\nifeq ($(SYSTEM), unix)\r\ndist :  dist_src dist_bin_unix\r\nelse\r\ndist :  dist_src dist_bin_dos dist_bin_win32\r\nendif\r\n\r\ndist_src :\r\n\t@echo Creating Dist/meka-src.zip\r\n#   This change in directories does not work in Linux.\r\n#   Changed all the relative paths below to fix it.\r\n#   Another approach is:\r\n#   http://stackoverflow.com/questions/1789594/how-to-write-cd-command-in-makefile\r\n#   cd ..\r\n\t-$(MKDIR) ../Dist\r\n\tzip -9 ../Dist/meka-src.zip ../meka.blt ../meka.dat ../meka.inp ../meka.msg ../meka.nam ../meka.pat ../meka.thm\r\n\tzip -9 ../Dist/meka-src.zip ../*.cfg ../*.txt ../icons.zip ../setup.bat\r\n\tzip -9 -r ../Dist/meka-src.zip ../Data/$(ALL_FILES)\r\n\tzip -9 -r ../Dist/meka-src.zip ../Themes/$(ALL_FILES)\r\n\tzip -9 -r ../Dist/meka-src.zip ../libs/$(ALL_FILES)\r\n\tzip -9 -D ../Dist/meka-src.zip ../srcs/$(ALL_FILES)\r\n\tzip -9 -r ../Dist/meka-src.zip ../srcs/datasrc/$(ALL_FILES)\r\n#   I dont have this folder on linux\r\n\t-zip -9 -r ../Dist/meka-src.zip ../srcs/docs/$(ALL_FILES)\r\n\tzip -9 -r ../Dist/meka-src.zip ../srcs/sound/*.h ../srcs/sound/*.cpp\r\n\tzip -9 -r ../Dist/meka-src.zip ../srcs/sound/emu2413/*.h ../srcs/sound/emu2413/*.cpp\r\n\tzip -9 -r ../Dist/meka-src.zip ../srcs/z80marat/$(ALL_FILES)\r\n\t@echo Deleting VisualStudio temporary files, be sure that VisualStudio is closed.\r\n\t-$(RM) -f srcs/MsVc/*.ncb\r\n#   I dont have this folder on linux\r\n\t-zip -9 -D ../Dist/meka-src.zip ../srcs/MsVc/$(ALL_FILES)\r\n#   zip -9 -r Dist/meka-src.zip srcs/mithril/*.*\r\n#   zip -9 -r Dist/meka-src.zip srcs/z80mame/*.*\r\n#   zip -9 -r Dist/meka-src.zip srcs/z80mk/*.*\r\n#   zip -9 -r Dist/meka-src.zip srcs/z80raze/*.*\r\n\t@echo Done!\r\n\t\r\ndist_bin_dos :\r\n\t@echo Creating Dist/meka.zip\r\n\tcd ..\r\n\t-$(MKDIR) Dist\r\n\t@echo Stripping and compressing\r\n\t-strip meka.exe\r\n\t-upx -9 meka.exe\r\n\t@echo Packaging\r\n\tzip -9 Dist/meka.zip meka.blt meka.cfg meka.dat meka.exe meka.inp meka.msg meka.nam meka.pat meka.thm\r\n\tzip -9 Dist/meka.zip icons.zip\r\n\tzip -9 Dist/meka.zip meka.txt changes.txt compat.txt debugger.txt multi.txt tech.txt \r\n\tzip -9 Dist/meka.zip -r Data/*.*\r\n\tzip -9 Dist/meka.zip -r Themes/*.png Themes/README.txt\r\n\t@echo Done!\r\n\t@echo -- Check MEKA.BLT ! --\r\n\t@echo -- Check MEKA.INP ! Joypad auto, on --\r\n\r\ndist_bin_win32 :\r\n\t@echo Creating Dist/mekaw.zip\r\n\tcd ..\r\n\t-$(MKDIR) Dist\r\n\t@echo Compressing\r\n\t-libs/dist_win/upx.exe -9 mekaw.exe\r\n\t@echo Packaging\r\n\tlibs/dist_win/zip.exe -9 Dist/mekaw.zip meka.blt meka.dat mekaw.cfg mekaw.exe meka.inp meka.msg meka.nam meka.pat meka.thm\r\n\tlibs/dist_win/zip.exe -9 Dist/mekaw.zip icons.zip setup.bat\r\n\tlibs/dist_win/zip.exe -9 Dist/mekaw.zip meka.txt changes.txt compat.txt debugger.txt multi.txt tech.txt\r\n\tlibs/dist_win/zip.exe -9 Dist/mekaw.zip -r Themes/*.png Themes/Credits.txt\r\n\tlibs/dist_win/zip.exe -9 Dist/mekaw.zip -r Data/*.*\r\n\t@echo Done!\r\n\t@echo -- Check MEKA.BLT ! --\r\n\t@echo -- Check MEKA.INP ! Joypad auto, on --\r\n\r\n# Not sure if this still work\r\nifeq ($(SYSTEM), unix)\r\ndist_bin_unix :\r\n\t@echo Creating Dist/mekanix.tgz\r\n\t@echo Compressing\r\n\t-upx -9 ../meka\r\n\t@echo Packaging\r\n\t-mkdir ../Dist/\r\n\t-mkdir ../Dist/mekanix/\r\n\tcp ../meka ../meka.blt ../meka.cfg ../meka.dat ../meka.inp ../meka.msg ../meka.nam ../meka.pat ../meka.thm ../icons.zip ../Dist/mekanix/\r\n\tcp ../meka.txt ../changes.txt ../compat.txt ../debugger.txt ../multi.txt ../tech.txt ../Dist/mekanix/\r\n\tcp -R ../Themes ../Dist/mekanix/\r\n\tcp -R ../Data ../Dist/mekanix/\r\n\ttar cvzf ../Dist/mekanix.tgz ../Dist/mekanix\r\n\trm -fR ../Dist/mekanix/\r\n\t@echo Done!\r\n\t@echo -- Check MEKA.BLT ! --\r\n\t@echo -- Check MEKA.INP ! Joypad auto, on --\r\nendif\r\n\r\n# Cleaning rules -------------------------------------\r\nclean :     clean_backup\r\n\t$(RM) -f $(OD)/*.o\r\n\t$(RM) -f $(OD)/sound/*.o\r\n\t$(RM) -f $(OD)/sound/emu2413/*.o\r\n\r\nclean_all : clean\r\n\t$(RM) -f $(OD)/*.a\r\n\t$(RM) -f MsVc/*.ncb\r\n\r\nclean_backup :\r\n\t$(RM) -f *~ *.c~ *.cpp~ *.h~\r\n\t$(RM) -f sound/*.c~ sound/*.cpp~ sound/*.h~\r\n\t$(RM) -f sound/emu2413/*.c~ sound/emu2413/*.h~\r\n\r\nclean_sound :\r\n\t$(RM) -f $(OD)/sound/*.o\r\n\r\n# Directories\r\nmakedir: $(OD) $(OD)/sound $(OD)/sound/emu2413 $(OD)/platform/macosx\r\n$(OD):\r\n\t-$(MKDIR) $(OD)\r\n$(OD)/sound:\r\n\t-$(MKDIR) $(OD)/sound\r\n$(OD)/sound/emu2413:\r\n\t-$(MKDIR) $(OD)/sound/emu2413\r\n\r\n$(OD)/platform/macosx:\r\n\t@$(MKDIR) -p $(OD)/platform/macosx\r\n#------------------------------------------------------\r\n# EOF\r\n#------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/allegro4to5.cpp",
    "content": "#include \"shared.h\"\r\n#include \"palette.h\"\r\n\r\nvoid al_draw_hline(int x1, int y, int x2, ALLEGRO_COLOR c)\r\n{\r\n   al_draw_line(x1, y+0.5f, x2+1, y+0.5f, c, 0);\r\n}\r\n\r\nvoid al_draw_vline(int x, int y1, int y2, ALLEGRO_COLOR c)\r\n{\r\n   al_draw_line(x+0.5f, y1, x+0.5f, y2+1, c, 0);\r\n}\r\n\r\nbool alx_color_equals(const ALLEGRO_COLOR* c1, const ALLEGRO_COLOR* c2)\r\n{\r\n    const float f = fabs(c1->r - c2->r) + fabs(c1->g - c2->g) + fabs(c1->b - c2->b) + fabs(c1->a - c2->a);\r\n    return f < 1/255.0f;\r\n}\r\n\r\nvoid alx_locked_draw_filled_rectangle(ALLEGRO_LOCKED_REGION* dst_region, int x1, int y1, int x2, int y2, ALLEGRO_COLOR color)\r\n{\r\n    ALLEGRO_BITMAP *dst = al_get_target_bitmap();\r\n    const int color_format = al_get_bitmap_format(dst);\r\n    switch (al_get_pixel_format_bits(color_format))\r\n    {\r\n    case 16:\r\n        {\r\n            const u16 host_color16 = (u16)Palette_MakeHostColor(color_format, color);\r\n            const u32 host_color32 = host_color16 | (host_color16 << 16);\r\n\r\n            const int dst_pitch = dst_region->pitch >> 1;\r\n            u16* dst_data_line = (u16*)dst_region->data + (y1 * dst_pitch + x1);\r\n            const int x_len32 = (x2 - x1) >> 1;\r\n            for (int y = y1; y != y2; y++, dst_data_line += dst_pitch)\r\n            {\r\n                u32* dst_data = (u32 *)dst_data_line;\r\n                for (int x = x_len32; x != 0; x--)\r\n                    *dst_data++ = host_color32;\r\n            }\r\n            break;\r\n        }\r\n    case 32:\r\n        {\r\n            const u32 host_color32 = Palette_MakeHostColor(color_format, color);\r\n\r\n            const int dst_pitch = dst_region->pitch >> 2;\r\n            u32* dst_data_line = (u32*)dst_region->data + (y1 * dst_pitch + x1);\r\n            const int x_len32 = (x2 - x1);\r\n            for (int y = y1; y != y2; y++, dst_data_line += dst_pitch)\r\n            {\r\n                u32* dst_data = (u32 *)dst_data_line;\r\n                for (int x = x_len32; x != 0; x--)\r\n                    *dst_data++ = host_color32;\r\n            }\r\n            break;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "meka/srcs/allegro4to5.h",
    "content": "\r\nvoid al_draw_hline(int x1, int y, int x2, ALLEGRO_COLOR c);\r\nvoid al_draw_vline(int x, int y1, int y2, ALLEGRO_COLOR c);\r\n\r\nbool alx_color_equals(const ALLEGRO_COLOR* c1, const ALLEGRO_COLOR* c2);\r\nvoid alx_locked_draw_filled_rectangle(ALLEGRO_LOCKED_REGION* dst_region, int x1, int y1, int x2, int y2, ALLEGRO_COLOR color);\r\n"
  },
  {
    "path": "meka/srcs/app_about.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - about.c\r\n// About Box - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"desktop.h\"\r\n#include \"g_widget.h\"\r\n#include \"inputs_t.h\"\r\n#include \"app_about.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_app_about_box     AboutBox;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void         AboutBox_Layout(bool setup);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    AboutBox_Switch()\r\n{\r\n    int menu_pos = 4;\r\n#ifdef MEKA_Z80_DEBUGGER\r\n    menu_pos += 1;\r\n#endif\r\n\r\n    AboutBox.active ^= 1;\r\n    gui_box_show (AboutBox.box, AboutBox.active, TRUE);\r\n    gui_menu_toggle_check (menus_ID.help, menu_pos);\r\n}\r\n\r\nstatic void     AboutBox_Layout(bool setup)\r\n{\r\n    t_app_about_box *app = &AboutBox;   // Global instance\r\n    const int dragon_h = al_get_bitmap_height(Graphics.Misc.Dragon);\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (setup)\r\n        widget_closebox_add(app->box, (t_widget_callback)AboutBox_Switch);\r\n\r\n    // Draw MEKA dragon sprite\r\n    al_draw_bitmap(Graphics.Misc.Dragon, 16, (app->box->frame.size.y - dragon_h) / 2, 0);\r\n\r\n    // Print about information lines\r\n    {\r\n        int y = 12;\r\n        Font_SetCurrent((t_font_id)g_config.font_about);\r\n        for (int i = 0; i < 4; i ++)\r\n        {\r\n            char buffer[256];\r\n            switch (i)\r\n            {\r\n            case 0: snprintf(buffer, countof(buffer), Msg_Get(MSG_About_Line_Meka_Date), MEKA_NAME_VERSION, MEKA_DATE); break;\r\n            case 1: snprintf(buffer, countof(buffer), Msg_Get(MSG_About_Line_Authors), MEKA_AUTHORS_SHORT); break;\r\n            case 2: snprintf(buffer, countof(buffer), Msg_Get(MSG_About_Line_Homepage), MEKA_HOMEPAGE); break;\r\n            case 3: snprintf(buffer, countof(buffer), \"Built %s, %s\", MEKA_BUILD_DATE, MEKA_BUILD_TIME); break;\r\n            }\r\n            const int x = (( (app->box->frame.size.x - dragon_h - 18 - 6) - Font_TextWidth(FONTID_CUR, buffer) ) / 2) + dragon_h + 8 + 6;\r\n            Font_Print(FONTID_CUR, buffer, x, y, COLOR_SKIN_WINDOW_TEXT);\r\n            y += Font_Height() + 3;\r\n        }\r\n    }\r\n}\r\n\r\nvoid            AboutBox_Init()\r\n{\r\n    t_app_about_box *app = &AboutBox;   // Global instance\r\n\r\n    t_frame frame;\r\n    frame.pos.x = 440;\r\n    frame.pos.y = 62;\r\n    frame.size.x = 346;\r\n    frame.size.y = 85;\r\n    app->box = gui_box_new(&frame, Msg_Get(MSG_About_BoxTitle));\r\n    Desktop_Register_Box(\"ABOUT\", app->box, 0, &AboutBox.active);\r\n\r\n    // Layout\r\n    AboutBox_Layout(TRUE);\r\n}\r\n\r\nvoid        AboutBox_Update()\r\n{\r\n    // Skip update if not active\r\n    if (!AboutBox.active)\r\n        return;\r\n\r\n    // If skin has changed, redraw everything\r\n    if (AboutBox.box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        AboutBox_Layout(FALSE);\r\n        AboutBox.box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/app_about.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - about.h\n// About Box - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_app_about_box\n{\n    // Interface\n    bool            active;\n    t_gui_box *     box;\n};\n\nextern t_app_about_box     AboutBox;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    AboutBox_Init(void);\nvoid    AboutBox_Switch(void);\nvoid    AboutBox_Update(void);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/app_cheatfinder.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_cheatfinder.c\r\n// Cheat Finder - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_cheatfinder.h\"\r\n#include \"app_memview.h\"\r\n#include \"debugger.h\"\r\n#include \"desktop.h\"\r\n#include \"g_widget.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_cheat_finder *    g_CheatFinder_MainInstance;\r\nt_list *            g_CheatFinders;\r\n\r\nstatic const char*  s_value_type_names[] =\r\n{\r\n    \"1\",\r\n    \"8\",\r\n    \"16\",\r\n    \"24\",\r\n    \"ANY\",\r\n};\r\nstatic int          s_value_type_bit_length[] =\r\n{\r\n    1,\r\n    8,\r\n    16,\r\n    24,\r\n    -1,\r\n};\r\nstatic const char*  s_comparer_names[] =\r\n{\r\n    \"==\",\r\n    \"!=\",\r\n    \"<\",\r\n    \">\",\r\n    \"<=\",\r\n    \">=\"\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void         CheatFinder_Layout(t_cheat_finder *app, bool setup);\r\nstatic void         CheatFinder_Update(t_cheat_finder* app);\r\n\r\nstatic void         CheatFinder_ResetMatches(t_cheat_finder* app);\r\nstatic void         CheatFinder_ReduceMatches(t_cheat_finder* app, t_cheat_finder_comparer comparer);\r\nstatic void         CheatFinder_UndoReduce(t_cheat_finder* app);\r\nstatic void         CheatFinder_SelectOneMatch(t_cheat_finder* app, int match_index);\r\n\r\nstatic u32          CheatFinder_IndexToAddr(t_cheat_finder* app, const t_cheat_finder_match* match);\r\nstatic u32          CheatFinder_ReadValue(t_cheat_finder* app, const t_memory_range* memrange, t_cheat_finder_match* match);\r\n\r\nstatic void         CheatFinder_CallbackMemtypeSelect(t_widget* w);\r\nstatic void         CheatFinder_CallbackValuetypeSelect(t_widget* w);\r\nstatic void         CheatFinder_CallbackComparer(t_widget* w);\r\nstatic void         CheatFinder_CallbackCompareToSelect(t_widget* w);\r\nstatic void         CheatFinder_CallbackReset(t_widget* w);\r\nstatic void         CheatFinder_CallbackReduce(t_widget* w);\r\nstatic void         CheatFinder_CallbackUndoReduce(t_widget* w);\r\nstatic void         CheatFinder_CallbackSelectOneMatch(t_widget* w);\r\nstatic void         CheatFinder_CallbackClose(t_widget* w);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nt_cheat_finder *    CheatFinder_New(bool register_desktop)\r\n{\r\n    t_cheat_finder* app = new t_cheat_finder();\r\n    list_add(&g_CheatFinders, app);\r\n\r\n    // Setup\r\n    app->active = FALSE;\r\n\r\n    // Create box\r\n    t_frame frame;\r\n    frame.pos.x     = 437;\r\n    frame.pos.y     = 102;\r\n    frame.size.x    = 330;\r\n    frame.size.y    = 208;\r\n    app->box = gui_box_new(&frame, \"Cheat Finder\"); // FIXME-LOCALIZATION\r\n    app->box->user_data = app;\r\n    app->box->destroy = (t_gui_box_destroy_handler)CheatFinder_Delete;\r\n\r\n    app->memtype            = MEMTYPE_RAM;\r\n    app->valuetype          = CHEAT_FINDER_VALUE_TYPE_8;\r\n    app->compare_to         = CHEAT_FINDER_COMPARE_TO_OLD_VALUE;\r\n    app->custom_value       = 0;\r\n    app->custom_value_valid = false;\r\n    app->reset_state        = true;\r\n\r\n    // Register to desktop (applet is disabled by default)\r\n    if (register_desktop)\r\n        Desktop_Register_Box(\"CHEAT_FINDER\", app->box, FALSE, &app->active);\r\n\r\n    // Set exclusive inputs flag to avoid messing with emulation\r\n    app->box->flags |= GUI_BOX_FLAGS_FOCUS_INPUTS_EXCLUSIVE;\r\n\r\n    // Set tab stop\r\n    app->box->flags |= GUI_BOX_FLAGS_TAB_STOP;\r\n\r\n    // Layout\r\n    CheatFinder_Layout(app, TRUE);\r\n    CheatFinder_ResetMatches(app);\r\n\r\n    // Return new instance\r\n    return (app);\r\n}\r\n\r\nvoid    CheatFinder_Delete(t_cheat_finder *app)\r\n{\r\n    list_remove(&g_CheatFinders, app);\r\n    free(app);\r\n}\r\n\r\nvoid    CheatFinder_Layout(t_cheat_finder *app, bool setup)\r\n{\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    // Add closebox widget\r\n    if (setup)\r\n        widget_closebox_add(app->box, CheatFinder_CallbackClose);\r\n\r\n    // Setup Memory sections\r\n    FontPrinter fp(FONTID_MEDIUM);\r\n    DrawCursor dc(v2i(5,0), FONTID_MEDIUM);\r\n    dc.y_spacing += 4;\r\n\r\n    fp.Printf(dc.pos+v2i(0,4), \"Memory region:\");\r\n    dc.pos.x += 90;\r\n\r\n    if (setup)\r\n    {\r\n        for (int i = 0; i != MEMTYPE_MAX_; i++)\r\n        {\r\n            t_memory_type memtype = (t_memory_type)i;\r\n            t_memory_range memrange;\r\n            MemoryRange_GetDetails(memtype, &memrange);\r\n\r\n            t_frame frame(dc.pos, v2i(30,Font_Height(FONTID_SMALL) + 3));\r\n            app->w_memtype_buttons[memtype] = widget_button_add(app->box, &frame, 1, CheatFinder_CallbackMemtypeSelect, FONTID_SMALL, (const char *)memrange.name, (void*)memtype);\r\n            dc.pos.x += frame.size.x + 2;\r\n        }\r\n    }\r\n    dc.NewLine();\r\n    dc.HorizontalSeparator();\r\n\r\n    fp.Printf(dc.pos+v2i(0,4), \"Variable size:\");\r\n    dc.pos.x += 90;\r\n    if (setup)\r\n    {\r\n        for (int i = 0; i != CHEAT_FINDER_VALUE_TYPE_MAX_; i++)\r\n        {\r\n            t_frame frame(dc.pos, v2i(30,Font_Height(FONTID_SMALL)+3));\r\n            app->w_valuetype_buttons[i] = widget_button_add(app->box, &frame, 1, CheatFinder_CallbackValuetypeSelect, FONTID_SMALL, (const char *)s_value_type_names[i], (void*)i);\r\n            dc.pos.x += frame.size.x + 2;\r\n        }\r\n    }\r\n    dc.NewLine();\r\n    dc.HorizontalSeparator();\r\n\r\n    if (setup)\r\n    {\r\n        t_frame frame(dc.pos, v2i(80,Font_Height(FONTID_SMALL)+3));\r\n        widget_button_add(app->box, &frame, 1, (t_widget_callback)CheatFinder_CallbackReset, FONTID_SMALL, \"RESET SEARCH\"); // FIXME-LOCALIZATION\r\n    }\r\n\r\n    app->matches_frame.SetPos(92,dc.pos.y);\r\n    app->matches_frame.SetSize(app->box->frame.size - app->matches_frame.pos);\r\n\r\n    DrawCursor dc2(v2i(92+5,dc.pos.y+3),FONTID_MEDIUM);\r\n    dc2.NewLine();\r\n    al_draw_line(91+0.5f,dc.pos.y-2,91+0.5f,app->box->frame.size.y+1, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n    if (setup)\r\n    {\r\n        int h = Font_Height(FONTID_SMALL)-2;\r\n        for (int i = 0; i != CHEAT_FINDER_MATCHES_MAX; i++)\r\n        {\r\n            t_frame frame(dc2.pos, v2i(h,h));\r\n            app->w_matches_memedit_buttons[i] = widget_button_add(app->box, &frame, 1, CheatFinder_CallbackSelectOneMatch, FONTID_SMALL, \"\", (void*)i);\r\n            dc2.NewLine();\r\n        }\r\n    }\r\n    dc.NewLine();\r\n    dc.HorizontalSeparator();   // NB: this draw too far but the rest is clearer later anyway, so its ok for now\r\n\r\n    fp.Printf(dc.pos+v2i(0,4), \"COMPARE REF:\");\r\n    dc.NewLine();\r\n    {\r\n        t_frame frame(dc.pos, v2i(50,Font_Height(FONTID_SMALL)+3));\r\n        if (setup)\r\n            app->w_compare_to_buttons[CHEAT_FINDER_COMPARE_TO_OLD_VALUE] = widget_button_add(app->box, &frame, 1, CheatFinder_CallbackCompareToSelect, FONTID_SMALL, \"Old Value\", (void*)0);\r\n        dc.NewLine();\r\n        frame.SetPos(dc.pos);\r\n        if (setup)\r\n            app->w_compare_to_buttons[CHEAT_FINDER_COMPARE_TO_CONSTANT] = widget_button_add(app->box, &frame, 1, CheatFinder_CallbackCompareToSelect, FONTID_SMALL, \"Constant\", (void*)1);\r\n        dc.NewLine();\r\n    }\r\n\r\n    //fp.Printf(dc.pos+v2i(0,4), \"Value:\");\r\n    dc.pos.x = 24;\r\n    dc.pos.y += 2;\r\n    if (setup)\r\n    {\r\n        t_frame frame(dc.pos, v2i(60,Font_Height(FONTID_SMALL)+3));\r\n        app->w_custom_value = widget_inputbox_add(app->box, &frame, 9, FONTID_MEDIUM, NULL);\r\n        widget_inputbox_set_content_type(app->w_custom_value, WIDGET_CONTENT_TYPE_DEC_HEX_BIN);\r\n    }\r\n    dc.pos.y += 1;\r\n\r\n    dc.NewLine();\r\n    dc.HorizontalSeparator();   // NB: this draw too far but the rest is clearer later anyway, so its ok for now\r\n\r\n    fp.Printf(dc.pos+v2i(0,4), \"REDUCE:\");\r\n    dc.NewLine();\r\n    //if (setup)\r\n    {\r\n        for (int i = 0; i != CHEAT_FINDER_COMPARER_MAX_; i++)\r\n        {\r\n            t_frame frame(dc.pos, v2i(30,Font_Height(FONTID_SMALL)+3));\r\n            if (setup)\r\n                app->w_comparer_buttons[i] = widget_button_add(app->box, &frame, 1, CheatFinder_CallbackComparer, FONTID_SMALL, (const char *)s_comparer_names[i], (void*)i);\r\n            if ((i & 1) == 0)\r\n                dc.pos.x += frame.size.x + 2;\r\n            else\r\n                dc.NewLine();\r\n            //dc.pos.y += frame.size.y + 2;\r\n        }\r\n    }\r\n    //dc.NewLine();\r\n\r\n    //dc.HorizontalSeparator(); // NB: this draw too far but the rest is clearer later anyway, so its ok for now\r\n\r\n    //dc.pos.y += 2;\r\n    /*if (setup)\r\n    {\r\n        t_frame frame(dc.pos, v2i(80,Font_Height(F_SMALL)+3));\r\n        app->w_reduce_search = widget_button_add(app->box, &frame, 1, (t_widget_callback)CheatFinder_CallbackReduce, FONTID_SMALL, \"START\");        // FIXME-LOCALIZATION\r\n    }\r\n    dc.NewLine();\r\n    dc.pos.y += 2;*/\r\n    if (setup)\r\n    {\r\n        t_frame frame(dc.pos, v2i(80,Font_Height(FONTID_SMALL)+3));\r\n        app->w_undo_reduce_search = widget_button_add(app->box, &frame, 1, (t_widget_callback)CheatFinder_CallbackUndoReduce, FONTID_SMALL, \"UNDO REDUCE\");     // FIXME-LOCALIZATION\r\n        //widget_button_set_grayed_out(app->w_undo_reduce_search, false);\r\n    }\r\n}\r\n\r\nvoid    CheatFinder_Update(t_cheat_finder* app)\r\n{\r\n    if (!app->active)\r\n        return;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n\r\n    // If skin has changed, redraw everything\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        CheatFinder_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    }\r\n\r\n    for (int i = 0; i != MEMTYPE_MAX_; i++)\r\n    {\r\n        widget_set_highlight(app->w_memtype_buttons[i], app->memtype == i);\r\n        widget_button_set_grayed_out(app->w_memtype_buttons[i], !app->reset_state);\r\n    }\r\n\r\n    for (int i = 0; i != CHEAT_FINDER_VALUE_TYPE_MAX_; i++)\r\n    {\r\n        widget_set_highlight(app->w_valuetype_buttons[i], app->valuetype == i);\r\n        widget_button_set_grayed_out(app->w_valuetype_buttons[i], !app->reset_state);\r\n    }\r\n\r\n    const char* custom_value_text = widget_inputbox_get_value(app->w_custom_value);\r\n    t_debugger_value v;\r\n    app->custom_value_valid = Debugger_Eval_ParseConstant(custom_value_text, &v, DEBUGGER_EVAL_VALUE_FORMAT_INT_DEC);\r\n    if (app->custom_value_valid)\r\n        app->custom_value = v.data;\r\n    //app->custom_value_valid = (sscanf(custom_value_text, \"%d\", &app->custom_value) == 1);\r\n\r\n    const bool cannot_reduce = (app->matches.empty() || (app->compare_to == CHEAT_FINDER_COMPARE_TO_CONSTANT && !app->custom_value_valid));\r\n    for (int i = 0; i != CHEAT_FINDER_COMPARER_MAX_; i++)\r\n        widget_button_set_grayed_out(app->w_comparer_buttons[i], cannot_reduce);\r\n\r\n    //widget_button_set_label(app->w_reduce_search, app->reset_state ? \"START\" : \"REDUCE\"); // FIXME-LOCALIZATION\r\n    //widget_button_set_grayed_out(app->w_reduce_search, !app->reset_state && (app->matches.empty() || (app->compare_to == CHEAT_FINDER_COMPARE_TO_CONSTANT && !app->custom_value_valid)));\r\n    widget_button_set_grayed_out(app->w_undo_reduce_search, app->matches_undo.empty());\r\n\r\n    al_draw_filled_rectangle(app->matches_frame.pos.x, app->matches_frame.pos.y, app->matches_frame.pos.x+app->matches_frame.size.x, app->matches_frame.pos.y+app->matches_frame.size.y, COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    FontPrinter fp(FONTID_MEDIUM);\r\n    DrawCursor dc(app->matches_frame.pos+v2i(5,4), FONTID_MEDIUM);\r\n\r\n    fp.Printf(dc.pos, (app->matches.size()>1) ? \"%d matches\" : \"%d match\", app->matches.size());\r\n    dc.NewLine();\r\n\r\n    bool displaying_matches = false;\r\n    if (app->matches.size() > 0)\r\n    {\r\n        t_memory_range memrange;\r\n        MemoryRange_GetDetails(app->memtype, &memrange);\r\n        if (app->matches.size() <= CHEAT_FINDER_MATCHES_MAX)\r\n        {\r\n            const t_cheat_finder_match* match = &app->matches[0];\r\n            for (size_t i = 0; i != app->matches.size(); i++, match++)\r\n            {\r\n                if (match->type == CHEAT_FINDER_VALUE_TYPE_1)\r\n                    fp.Printf(dc.pos+v2i(12,0), \"%s $%0*X bit %d (mask $%02X): %d\", memrange.name, memrange.addr_hex_length, memrange.addr_start+(match->value_index>>3), match->value_index&7, 1<<(match->value_index&7), match->last_value);\r\n                else\r\n                    fp.Printf(dc.pos+v2i(12,0), \"%s $%0*X: $%0*X (%d)\", memrange.name, memrange.addr_hex_length, memrange.addr_start+match->value_index, (s_value_type_bit_length[match->type]/8)*2, match->last_value, match->last_value);\r\n                dc.NewLine();\r\n            }\r\n            displaying_matches = true;\r\n        }\r\n        else\r\n        {\r\n            fp.Printf(dc.pos, \"Too many matches to display!\");\r\n        }\r\n    }\r\n    for (int i = 0; i != CHEAT_FINDER_MATCHES_MAX; i++)\r\n    {\r\n        widget_set_enabled(app->w_matches_memedit_buttons[i], displaying_matches && ((int)app->matches.size()>i));\r\n    }\r\n\r\n    widget_set_highlight(app->w_compare_to_buttons[0], app->compare_to == CHEAT_FINDER_COMPARE_TO_OLD_VALUE);\r\n    widget_set_highlight(app->w_compare_to_buttons[1], app->compare_to == CHEAT_FINDER_COMPARE_TO_CONSTANT);\r\n\r\n    // Request memory editor highlight?\r\n    if (displaying_matches)\r\n    {\r\n        app->addresses_to_highlight_in_memory_editor.reserve(app->matches.size());\r\n        app->addresses_to_highlight_in_memory_editor.resize(0);\r\n        for (size_t i = 0; i != app->matches.size(); i++)\r\n        {\r\n            const t_cheat_finder_match* match = &app->matches[i];\r\n            u32 addr_min = CheatFinder_IndexToAddr(app, match);\r\n            u32 addr_max = addr_min + (s_value_type_bit_length[match->type]+7)/8;\r\n            for (u32 addr = addr_min; addr < addr_max; addr++)\r\n                app->addresses_to_highlight_in_memory_editor.push_back(addr);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        app->addresses_to_highlight_in_memory_editor.clear();\r\n    }\r\n}\r\n\r\nstatic u32 CheatFinder_IndexToAddr(t_cheat_finder* app, const t_cheat_finder_match* match)\r\n{\r\n    u32 index = match->value_index;\r\n    u32 addr = (match->type == CHEAT_FINDER_VALUE_TYPE_1) ? (index >> 3) : index;\r\n    return addr;\r\n}\r\n\r\nstatic u32 CheatFinder_ReadValue(t_cheat_finder* app, const t_memory_range* memrange, t_cheat_finder_match* match)\r\n{\r\n    const u32 addr = CheatFinder_IndexToAddr(app, match);\r\n\r\n    u32 v;\r\n    switch (match->type)\r\n    {\r\n    case CHEAT_FINDER_VALUE_TYPE_1:\r\n        {\r\n            v = (u32)memrange->ReadByte(addr);\r\n            if (v & (1 << (match->value_index & 7)))\r\n                v = 1;\r\n            else\r\n                v = 0;\r\n            break;\r\n        }\r\n    case CHEAT_FINDER_VALUE_TYPE_8:\r\n        {\r\n            v = (u32)memrange->ReadByte(addr);\r\n            break;\r\n        }\r\n    case CHEAT_FINDER_VALUE_TYPE_16:\r\n        {\r\n            v = ((u32)memrange->ReadByte(addr) << 0) | ((u32)memrange->ReadByte(addr+1) << 8);\r\n            break;\r\n        }\r\n    case CHEAT_FINDER_VALUE_TYPE_24:\r\n        {\r\n            v = ((u32)memrange->ReadByte(addr) << 0) | ((u32)memrange->ReadByte(addr+1) << 8) | ((u32)memrange->ReadByte(addr+2) << 16);\r\n            break;\r\n        }\r\n    default:\r\n        assert(0);\r\n        v = 0;\r\n        break;\r\n    }\r\n\r\n    return v;\r\n}\r\n\r\nvoid CheatFinder_AddNewMatches(t_cheat_finder* app, const t_memory_range* memrange, t_cheat_finder_value_type value_type)\r\n{\r\n    int value_count = memrange->size * (value_type == CHEAT_FINDER_VALUE_TYPE_1 ? 8 : 1);\r\n    if (value_type == CHEAT_FINDER_VALUE_TYPE_16)\r\n        value_count -= 1;\r\n    if (value_type == CHEAT_FINDER_VALUE_TYPE_24)\r\n        value_count -= 2;\r\n\r\n    // Disabled memory region may be empty\r\n    if (value_count <= 0)\r\n        return;\r\n\r\n    int insert_pos = app->matches.size();\r\n    app->matches.resize(insert_pos + value_count);\r\n    for (int index = 0; index != value_count; index++)\r\n    {\r\n        t_cheat_finder_match* match = &app->matches[insert_pos + index];\r\n        match->type = value_type;\r\n        match->value_index = index;\r\n        match->last_value = CheatFinder_ReadValue(app, memrange, match);\r\n    }\r\n}\r\n\r\nvoid CheatFinder_ResetMatches(t_cheat_finder* app)\r\n{\r\n    app->reset_state = true;\r\n    app->matches.clear();\r\n    app->matches_undo.clear();\r\n\r\n    t_cheat_finder_value_type value_type = app->valuetype;\r\n\r\n    t_memory_range memrange;\r\n    MemoryRange_GetDetails(app->memtype, &memrange);\r\n\r\n    if (value_type == CHEAT_FINDER_VALUE_TYPE_ANY_SIZE)\r\n    {\r\n        CheatFinder_AddNewMatches(app, &memrange, CHEAT_FINDER_VALUE_TYPE_1);\r\n        CheatFinder_AddNewMatches(app, &memrange, CHEAT_FINDER_VALUE_TYPE_8);\r\n        CheatFinder_AddNewMatches(app, &memrange, CHEAT_FINDER_VALUE_TYPE_16);\r\n        CheatFinder_AddNewMatches(app, &memrange, CHEAT_FINDER_VALUE_TYPE_24);\r\n    }\r\n    else\r\n    {\r\n        CheatFinder_AddNewMatches(app, &memrange, value_type);\r\n    }\r\n}\r\n\r\nvoid CheatFinder_ReduceMatches(t_cheat_finder* app, t_cheat_finder_comparer comparer)\r\n{\r\n    t_memory_range memrange;\r\n    MemoryRange_GetDetails(app->memtype, &memrange);\r\n\r\n    if (app->reset_state)\r\n    {\r\n        CheatFinder_ResetMatches(app);\r\n        app->reset_state = false;\r\n        if (app->compare_to == CHEAT_FINDER_COMPARE_TO_OLD_VALUE)\r\n            return;\r\n    }\r\n\r\n    if (app->matches.empty())\r\n        return;\r\n\r\n    if (app->compare_to == CHEAT_FINDER_COMPARE_TO_CONSTANT && !app->custom_value_valid)\r\n        return;\r\n\r\n    // Reduce\r\n    t_cheat_finder_match* match = &app->matches[0];\r\n    int custom_value = app->custom_value;\r\n\r\n    std::vector<t_cheat_finder_match> matches_reduced;\r\n    matches_reduced.reserve(app->matches.size());\r\n    for (size_t i = 0; i != app->matches.size(); i++, match++)\r\n    {\r\n        const u32 v_old = match->last_value;\r\n        const u32 v_cur = CheatFinder_ReadValue(app, &memrange, match);\r\n        const u32 v_to_compare = (app->compare_to == CHEAT_FINDER_COMPARE_TO_OLD_VALUE) ? v_old : custom_value;\r\n\r\n        bool compare_success = false;\r\n        switch (comparer)\r\n        {\r\n        case CHEAT_FINDER_COMPARER_EQUAL:\r\n            compare_success = (v_cur == v_to_compare);\r\n            break;\r\n        case CHEAT_FINDER_COMPARER_NOT_EQUAL:\r\n            compare_success = (v_cur != v_to_compare);\r\n            break;\r\n        case CHEAT_FINDER_COMPARER_LESS:\r\n            compare_success = (v_cur < v_to_compare);\r\n            break;\r\n        case CHEAT_FINDER_COMPARER_GREATER:\r\n            compare_success = (v_cur > v_to_compare);\r\n            break;\r\n        case CHEAT_FINDER_COMPARER_LESS_OR_EQUAL:\r\n            compare_success = (v_cur <= v_to_compare);\r\n            break;\r\n        case CHEAT_FINDER_COMPARER_GREATER_OR_EQUAL:\r\n            compare_success = (v_cur >= v_to_compare);\r\n            break;\r\n        }\r\n\r\n        // Discard?\r\n        if (!compare_success)\r\n            continue;\r\n\r\n        // Keep and update value\r\n        match->last_value = v_cur;\r\n        matches_reduced.push_back(*match);\r\n    }\r\n    if (app->matches.size() != matches_reduced.size())\r\n    {\r\n        app->matches_undo.swap(app->matches);\r\n        app->matches.swap(matches_reduced);\r\n    }\r\n}\r\n\r\nstatic void CheatFinder_UndoReduce(t_cheat_finder* app)\r\n{\r\n    if (!app->matches_undo.empty())\r\n    {\r\n        app->matches.swap(app->matches_undo);\r\n        app->matches_undo.clear();\r\n    }\r\n}\r\n\r\nstatic void CheatFinder_SelectOneMatch(t_cheat_finder* app, int match_index)\r\n{\r\n    assert(match_index < (int)app->matches.size());\r\n\r\n    const t_cheat_finder_match* match = &app->matches[match_index];\r\n    u32 addr = CheatFinder_IndexToAddr(app, match);\r\n\r\n    MemoryViewer_GotoAddress(MemoryViewer_MainInstance, app->memtype, addr);\r\n}\r\n\r\nstatic void CheatFinder_CallbackMemtypeSelect(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    app->memtype = (t_memory_type)(intptr_t)w->user_data;\r\n    CheatFinder_ResetMatches(app);\r\n}\r\n\r\nstatic void CheatFinder_CallbackValuetypeSelect(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    app->valuetype = (t_cheat_finder_value_type)(intptr_t)w->user_data;\r\n    CheatFinder_ResetMatches(app);\r\n}\r\n\r\nstatic void CheatFinder_CallbackCompareToSelect(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    app->compare_to = (t_cheat_finder_compare_to)(intptr_t)w->user_data;\r\n}\r\n\r\nstatic void CheatFinder_CallbackReset(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    CheatFinder_ResetMatches(app);\r\n}\r\n\r\nstatic void CheatFinder_CallbackComparer(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    CheatFinder_ReduceMatches(app, (t_cheat_finder_comparer)(intptr_t)w->user_data);\r\n}\r\n\r\nstatic void CheatFinder_CallbackUndoReduce(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    CheatFinder_UndoReduce(app);\r\n}\r\n\r\nstatic void CheatFinder_CallbackSelectOneMatch(t_widget *w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data;\r\n    const int match_index = (int)(intptr_t)w->user_data;\r\n    CheatFinder_SelectOneMatch(app, match_index);\r\n}\r\n\r\nstatic void CheatFinder_CallbackClose(t_widget* w)\r\n{\r\n    t_cheat_finder* app = (t_cheat_finder*)w->box->user_data; // Get instance\r\n    if (app == g_CheatFinder_MainInstance)\r\n    {\r\n        CheatFinder_SwitchMainInstance();\r\n    }\r\n    else\r\n    {\r\n        app->active ^= 1;\r\n        gui_box_show(app->box, app->active, TRUE);\r\n        if (!app->active)\r\n        {\r\n            // Flag GUI box for deletion\r\n            app->box->flags |= GUI_BOX_FLAGS_DELETE;\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\nvoid    CheatFinder_SwitchMainInstance()\r\n{\r\n    t_cheat_finder *app = g_CheatFinder_MainInstance;\r\n    app->active ^= 1;\r\n    gui_box_show(app->box, app->active, TRUE);\r\n    gui_menu_toggle_check(menus_ID.tools, 5);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    CheatFinders_Update()\r\n{\r\n    for (t_list* apps = g_CheatFinders; apps != NULL; apps = apps->next)\r\n    {\r\n        t_cheat_finder *app = (t_cheat_finder *)apps->elem;\r\n        CheatFinder_Update(app);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_cheatfinder.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_cheatfinder.h\r\n// Cheat Finder - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"app_memview.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n#define CHEAT_FINDER_MATCHES_MAX    (16)\r\n\r\nenum t_cheat_finder_value_type\r\n{\r\n    CHEAT_FINDER_VALUE_TYPE_1,\r\n    CHEAT_FINDER_VALUE_TYPE_8,\r\n    CHEAT_FINDER_VALUE_TYPE_16,\r\n    CHEAT_FINDER_VALUE_TYPE_24,\r\n    CHEAT_FINDER_VALUE_TYPE_ANY_SIZE,\r\n    CHEAT_FINDER_VALUE_TYPE_MAX_,\r\n};\r\n\r\nenum t_cheat_finder_comparer\r\n{\r\n    CHEAT_FINDER_COMPARER_EQUAL,\r\n    CHEAT_FINDER_COMPARER_NOT_EQUAL,\r\n    CHEAT_FINDER_COMPARER_LESS,\r\n    CHEAT_FINDER_COMPARER_GREATER,\r\n    CHEAT_FINDER_COMPARER_LESS_OR_EQUAL,\r\n    CHEAT_FINDER_COMPARER_GREATER_OR_EQUAL,\r\n    CHEAT_FINDER_COMPARER_MAX_,\r\n};\r\n\r\nenum t_cheat_finder_compare_to\r\n{\r\n    CHEAT_FINDER_COMPARE_TO_OLD_VALUE,\r\n    CHEAT_FINDER_COMPARE_TO_CONSTANT,\r\n};\r\n\r\nstruct t_cheat_finder_match\r\n{\r\n    u8      type;               // t_cheat_finder_value_type\r\n    u16     value_index;        // index of value in memory range, typically address offset, but *8 in the case of matching 1-bit flags\r\n    u32     last_value;\r\n};\r\n\r\nstruct t_cheat_finder\r\n{\r\n    bool                        active;\r\n    t_gui_box*                  box;\r\n\r\n    t_memory_type               memtype;\r\n    t_cheat_finder_value_type   valuetype;\r\n    t_cheat_finder_compare_to   compare_to;\r\n    int                         custom_value;\r\n    bool                        custom_value_valid;\r\n\r\n    t_widget*                           w_memtype_buttons[MEMTYPE_MAX_];\r\n    t_widget*                           w_valuetype_buttons[CHEAT_FINDER_VALUE_TYPE_MAX_];\r\n    t_widget*                           w_comparer_buttons[CHEAT_FINDER_COMPARER_MAX_];\r\n    t_widget*                           w_compare_to_buttons[2];\r\n    t_widget*                           w_custom_value;\r\n    //t_widget*                         w_reduce_search;\r\n    t_widget*                           w_undo_reduce_search;\r\n    t_widget*                           w_matches_memedit_buttons[CHEAT_FINDER_MATCHES_MAX];\r\n\r\n    bool                                reset_state;\r\n    std::vector<t_cheat_finder_match>   matches;\r\n    std::vector<t_cheat_finder_match>   matches_undo;\r\n    std::vector<u32>                    addresses_to_highlight_in_memory_editor;\r\n\r\n    t_frame                             matches_frame;\r\n};\r\n\r\nextern t_cheat_finder *     g_CheatFinder_MainInstance;\r\nextern t_list *             g_CheatFinders;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nt_cheat_finder *            CheatFinder_New(bool register_desktop);\r\nvoid                        CheatFinder_Delete(t_cheat_finder* app);\r\nvoid                        CheatFinder_SwitchMainInstance();\r\n\r\nvoid                        CheatFinders_Update();\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_filebrowser.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_file.c\r\n// GUI File Browser - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"desktop.h\"\r\n#include \"g_tools.h\"\r\n#include \"g_widget.h\"\r\n#include \"db.h\"\r\n#include \"file.h\"\r\n#include \"inputs_t.h\"\r\n#include \"vlfn.h\"\r\n#include \"vmachine.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_filebrowser    FB;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions (private)\r\n//-----------------------------------------------------------------------------\r\n\r\n#define FB_BUTTON_X             (60)\r\n#define FB_BUTTON_Y             (27)\r\n#define FB_MINI_BUTTON_X        (9)\r\n#define FB_MINI_BUTTON_Y        (9)\r\n#define FB_PAD_X                (6)\r\n#define FB_PAD_Y                (6)\r\n#define FB_TEXT_PAD_X           (12)\r\n#define FB_TEXT_PAD_Y           (10)\r\n#define FB_SCROLL_X             (10)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     FB_Layout               (t_filebrowser *app, bool setup);\r\n\r\n//...\r\n\r\nstatic void     FB_Draw_List            ();\r\nstatic void     FB_Draw_Infos           ();\r\nstatic void     FB_Click_List           (t_widget *w);\r\nstatic void     FB_Sort_Files           (int start, int end);\r\nstatic void     FB_Check_and_Repos      ();\r\n\r\nstatic bool     FB_SelectEntryByFileName(const char* name);\r\nstatic void     FB_OpenSelectedEntry    ();\r\nstatic void     FB_OpenDirectory        (const char* name);\r\nstatic void     FB_OpenFile             (const char* name);\r\nstatic void     FB_LoadAllNames         ();\r\n\r\nstatic t_filebrowser_entry *   FB_Entry_New        (int type, char *file_name);\r\nstatic void                    FB_Entry_Delete     (t_filebrowser_entry *entry);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nt_filebrowser_entry *       FB_Entry_New(int type, char *file_name)\r\n{\r\n    t_filebrowser_entry* entry;\r\n    entry = (t_filebrowser_entry*)malloc(sizeof(t_filebrowser_entry));\r\n    entry->type             = type;\r\n    entry->file_name        = file_name;\r\n    entry->db_entry         = NULL;\r\n    entry->db_entry_name    = NULL;\r\n    return (entry);\r\n}\r\n\r\nvoid    FB_Entry_Delete(t_filebrowser_entry *entry)\r\n{\r\n    free (entry->file_name);\r\n    free (entry);\r\n}\r\n\r\n// Find VLFN data associated to given entry file name, and associate data\r\nvoid    FB_Entry_FindVLFN(t_filebrowser_entry *entry)\r\n{\r\n    t_vlfn_entry *  vlfn_entry = VLFN_FindByFileName(entry->file_name);\r\n    if (vlfn_entry)\r\n    {\r\n        entry->db_entry         = vlfn_entry->db_entry;\r\n        entry->db_entry_name    = DB_Entry_GetCurrentName (entry->db_entry);    // pre-get\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic int FB_Return_File_Area_Y()\r\n{\r\n    return ((FB.files_display_count * Font_Height(FB.font_id)) + 5);\r\n}\r\n\r\nvoid    FB_Switch()\r\n{\r\n    FB.active ^= 1;\r\n    gui_box_show(FB.box, FB.active, TRUE);\r\n    gui_menu_toggle_check(menus_ID.file, 0);\r\n}\r\n\r\nvoid    FB_Init()\r\n{\r\n    t_filebrowser* app = &FB;\r\n\r\n    t_frame frame;\r\n    frame.pos.x     = 454;\r\n    frame.pos.y     = 54;\r\n    frame.size.x    = 340;\r\n    frame.size.y    = 390;\r\n\r\n    app->files_display_count = 21;\r\n    app->box = gui_box_new(&frame, Msg_Get(MSG_FileBrowser_BoxTitle));\r\n    app->box->flags |= GUI_BOX_FLAGS_FOCUS_INPUTS_EXCLUSIVE;                // Set exclusive inputs flag to avoid messing with emulation\r\n    app->box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;\r\n    app->box->size_min.x = 250;\r\n    app->box->size_min.y = 120;\r\n\r\n    // Register to desktop\r\n    Desktop_Register_Box(\"FILEBROWSER\", app->box, 0, &FB.active);\r\n\r\n    // Add close box widget\r\n    widget_closebox_add(FB.box, (t_widget_callback)FB_Switch);\r\n\r\n    // Layout\r\n    FB_Layout(app, true);\r\n}\r\n\r\nvoid    FB_Init_2()\r\n{\r\n    chdir(FB.current_directory);\r\n    FB_Load_Directory();\r\n}\r\n\r\nvoid    FB_Layout(t_filebrowser *app, bool setup)\r\n{\r\n    app->font_id = (t_font_id)g_config.font_filebrowser;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    int contents_y = app->box->frame.size.y;\r\n    contents_y -= ((3*FB_PAD_Y) + FB_BUTTON_Y + 5);\r\n    app->files_display_count = contents_y / Font_Height(app->font_id);\r\n\r\n    app->bottom_y = contents_y + 2*FB_PAD_Y;\r\n\r\n    const t_frame bb = app->box->frame;\r\n    const int bb_w = app->box->frame.size.x;\r\n\r\n    // Setup widgets\r\n    t_frame frame;\r\n\r\n    // Add scrollbar\r\n    frame.pos.x = bb_w - FB_PAD_X - FB_SCROLL_X + 1;\r\n    frame.pos.y = FB_PAD_Y + 2;\r\n    frame.size.x = FB_SCROLL_X - 3;\r\n    frame.size.y = FB_Return_File_Area_Y() - 4;\r\n    if (setup)\r\n        app->widget_scrollbar = widget_scrollbar_add(FB.box, WIDGET_SCROLLBAR_TYPE_VERTICAL, &frame, &FB.files_max, &FB.file_display_first, FB.files_display_count, (t_widget_callback)FB_Draw_List);\r\n    else\r\n    {\r\n        app->widget_scrollbar->frame = frame;\r\n        widget_scrollbar_set_page_step(app->widget_scrollbar, FB.files_display_count);\r\n    }\r\n\r\n    // Add an invisible 'button' to catch click on the list\r\n    // (currently the GUI doesn't handle list/combo)\r\n    frame.pos.x = FB_PAD_X + 2;\r\n    frame.pos.y = FB_PAD_Y + 2;\r\n    frame.size.x = bb_w - (2 * FB_PAD_X) - FB_SCROLL_X - 4;\r\n    frame.size.y = FB_Return_File_Area_Y() - 6;\r\n    if (setup)\r\n        app->widget_click_list = widget_button_add(FB.box, &frame, 1, (t_widget_callback)FB_Click_List, FONTID_NONE, NULL);\r\n    else\r\n        app->widget_click_list->frame = frame;\r\n\r\n    // Outer frame\r\n    gui_rect(LOOK_ROUND, FB_PAD_X, FB_PAD_Y, bb_w - FB_PAD_X, FB_PAD_Y + FB_Return_File_Area_Y(), COLOR_SKIN_WIDGET_LISTBOX_BORDER);\r\n\r\n    // Add 'CLOSE' button\r\n    //frame.pos.x = FB_BUTTON_X + 10;\r\n    frame.pos.x = bb_w - FB_BUTTON_X - 10;\r\n    frame.pos.y = app->bottom_y;\r\n    frame.size.x = FB_BUTTON_X;\r\n    frame.size.y = FB_BUTTON_Y;\r\n    if (setup)\r\n        app->widget_close_button = widget_button_add(FB.box, &frame, 1, (t_widget_callback)FB_Switch, app->font_id, Msg_Get(MSG_FileBrowser_Close));\r\n    else\r\n        app->widget_close_button->frame = frame;\r\n\r\n    // Add 'LOAD' button\r\n    frame.pos.x -= FB_BUTTON_X + 10;\r\n    if (setup)\r\n        app->widget_load_button = widget_button_add(FB.box, &frame, 1, (t_widget_callback)FB_OpenSelectedEntry, app->font_id, Msg_Get(MSG_FileBrowser_Load));\r\n    else\r\n        app->widget_load_button->frame = frame;\r\n\r\n    // Add small 'LOAD NAMES' button\r\n    frame.pos.x = FB_PAD_X;\r\n    frame.pos.y = app->bottom_y + Font_Height(FONTID_MEDIUM) + 6;\r\n    frame.size.x = 80;\r\n    frame.size.y = (int)(Font_Height(FONTID_MEDIUM) * 2);\r\n    if (setup)\r\n        app->widget_load_names_button = widget_button_add(FB.box, &frame, 1, (t_widget_callback)FB_LoadAllNames, FONTID_MEDIUM, Msg_Get(MSG_FileBrowser_LoadNames));\r\n    else\r\n        app->widget_load_names_button->frame = frame;\r\n\r\n    // Add small 'RELOAD DIR' button\r\n    frame.pos.x += frame.size.x + 1;\r\n    if (setup)\r\n        app->widget_reload_dir_button = widget_button_add(FB.box, &frame, 1, (t_widget_callback)FB_Load_Directory, FONTID_MEDIUM, Msg_Get(MSG_FileBrowser_ReloadDir));\r\n    else\r\n        app->widget_reload_dir_button->frame = frame;\r\n}\r\n\r\nvoid    FB_Free_Memory()\r\n{\r\n    for (int i = 0; i < FB.files_max; i ++)\r\n        FB_Entry_Delete(FB.files[i]);\r\n    free(FB.files);\r\n}\r\n\r\nvoid    FB_Close()\r\n{\r\n    FB_Free_Memory();\r\n}\r\n\r\n#ifdef ARCH_WIN32\r\n\r\nvoid    FB_Add_DiskDrives()\r\n{\r\n    for (int i = 2; i < 26; i ++)   // C: to Z:\r\n    {\r\n        if (GetLogicalDrives() & (1 << i))\r\n        {\r\n            // Create a new file browser entry of disk type\r\n            t_filebrowser_entry *entry;\r\n            char buf[16];\r\n            sprintf(buf, \"%c:\", 'A' + i);\r\n            entry = FB_Entry_New(FB_ENTRY_TYPE_DRIVE, strdup(buf));\r\n\r\n            // Add to list (FIXME: arghh.)\r\n            FB.files[FB.files_max] = entry;\r\n            FB.files_max ++;\r\n            FB.files = (t_filebrowser_entry**)realloc(FB.files, (FB.files_max + 1) * sizeof(t_filebrowser_entry *));\r\n        }\r\n    }\r\n}\r\n\r\n#endif\r\n\r\nstatic INLINE int   FB_Sort_Files_GetEntryPriority (t_filebrowser_entry *entry)\r\n{\r\n    const t_db_entry *    db_entry = entry->db_entry;\r\n    if (!db_entry)\r\n        return (-1);\r\n\r\n    // Priority order :\r\n    // - no country flag\r\n    // - country flag\r\n    // - proto\r\n    // - BIOS\r\n    // - translation\r\n    // - hacks\r\n    // - bad\r\n    int p = DB_Entry_SelectDisplayFlag(db_entry);\r\n    if (db_entry->flags & DB_FLAG_BIOS)\r\n        p += 500;\r\n    if (db_entry->flags & DB_FLAG_PROTO)\r\n        p += 1000;\r\n    if (db_entry->flags & DB_FLAG_TRANS)\r\n        p += 2000 + db_entry->trans_country;\r\n    if (db_entry->flags & DB_FLAG_HACK)\r\n        p += 4000;\r\n    if (db_entry->flags & DB_FLAG_BAD)\r\n        p += 8000;\r\n    return (p);\r\n}\r\n\r\n// FIXME-OPT: slow\r\nvoid    FB_Sort_Files(int start, int end)\r\n{\r\n    for (; start < end - 1; start ++)\r\n    {\r\n        for (int i = end - 1; i > start; i --)\r\n        {\r\n            t_filebrowser_entry *e1 = FB.files[i];\r\n            t_filebrowser_entry *e2 = FB.files[i - 1];\r\n\r\n            // Compare\r\n            const char *e1_name = e1->db_entry_name ? e1->db_entry_name : e1->file_name;\r\n            const char *e2_name = e2->db_entry_name ? e2->db_entry_name : e2->file_name;\r\n            int d = stricmp (e1_name, e2_name);\r\n\r\n            // Only if names are equal, sorting order depends on DB data (flags/bad marker, etc...)\r\n            if (d == 0)\r\n            {\r\n                int e1_p = FB_Sort_Files_GetEntryPriority(e1);\r\n                int e2_p = FB_Sort_Files_GetEntryPriority(e2);\r\n                d = (e1_p - e2_p);\r\n            }\r\n\r\n            // Swap!\r\n            if (d < 0)\r\n            {\r\n                FB.files [i] = e2;\r\n                FB.files [i - 1] = e1;\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nint     FB_Ext_In_List(const t_list *ext_list, const char *ext)\r\n{\r\n    while (ext_list)\r\n    {\r\n        if (stricmp ((char*)ext_list->elem, ext) == 0)\r\n            return (1);\r\n        ext_list = ext_list->next;\r\n    }\r\n    return (0);\r\n}\r\n\r\nvoid    FB_Add_Entries(t_list *ext_list, int type)\r\n{\r\n#if defined(ARCH_UNIX) || defined(ARCH_MACOSX)\r\n    DIR *           dir;\r\n    struct dirent * dirent;\r\n    struct stat     dirent_stat;\r\n\r\n    // Open current directory\r\n    if ((dir = opendir(\".\")) == 0)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Error_Directory_Open));\r\n        return;\r\n    }\r\n\r\n    // Check all files\r\n    while ((dirent = readdir(dir)))\r\n    {\r\n        char *name = dirent->d_name;\r\n        if (stat (name, &dirent_stat) != 0)\r\n            continue;\r\n\r\n        if (type == FB_ENTRY_TYPE_DIRECTORY && (dirent_stat.st_mode & S_IFMT) == S_IFDIR)\r\n        {\r\n            // Skip '.'\r\n            if (name[0] == '.' && name[1] == '\\0') // if (!strcmp(name, \".\"))\r\n                continue;\r\n        }\r\n        else if (type == FB_ENTRY_TYPE_FILE && (dirent_stat.st_mode & S_IFMT) == S_IFREG)\r\n        {\r\n            const char *ext = strrchr (name, '.');\r\n            if (ext == NULL)\r\n                ext = \"\";\r\n            if (!FB_Ext_In_List (ext_list, ext + 1))\r\n                continue;\r\n        }\r\n        else\r\n        {\r\n            continue;\r\n        }\r\n\r\n        // Create a new file browser entry of given type\r\n        t_filebrowser_entry *entry = FB_Entry_New (type, strdup (name));\r\n        if (g_config.fb_uses_DB)\r\n            FB_Entry_FindVLFN (entry);\r\n\r\n        // Add to list (FIXME: argh)\r\n        FB.files[FB.files_max] = entry;\r\n        FB.files_max ++;\r\n        FB.files = (t_filebrowser_entry**)realloc (FB.files, (FB.files_max + 1) * sizeof (t_filebrowser_entry *));\r\n    }\r\n\r\n    closedir (dir);\r\n\r\n#else // ARCH_WIN32\r\n\r\n#ifndef FA_LABEL\r\n#define FA_LABEL        8\r\n#endif\r\n#ifndef FA_DIREC\r\n#define FA_DIREC        16\r\n#endif\r\n\r\n    struct _finddata_t info;\r\n    long   handle;\r\n    if ((handle = _findfirst (\"*.*\", &info)) < 0)\r\n        return;\r\n\r\n    do\r\n    {\r\n        int     attrib  = info.attrib;\r\n        char *  name    = info.name;\r\n\r\n        if (attrib & FA_LABEL /* 8 */)\r\n            continue;\r\n\r\n        if (type == FB_ENTRY_TYPE_DIRECTORY && (attrib & FA_DIREC) != 0)\r\n        {\r\n            // Skip '.'\r\n            if (name[0] == '.' && name[1] == '\\0') // if (!strcmp(name, \".\"))\r\n                continue;\r\n        }\r\n        else if (type == FB_ENTRY_TYPE_FILE && (attrib & FA_DIREC) == 0)\r\n        {\r\n            const char *ext = strrchr (name, '.');\r\n            if (ext == NULL)\r\n                ext = \"\";\r\n            if (!FB_Ext_In_List (ext_list, ext + 1))\r\n                continue;\r\n        }\r\n        else\r\n        {\r\n            continue;\r\n        }\r\n\r\n        // Create a new file browser entry of given type\r\n        t_filebrowser_entry *entry = FB_Entry_New (type, strdup (name));\r\n        if (g_config.fb_uses_DB)\r\n            FB_Entry_FindVLFN (entry);\r\n\r\n        // Add to list (FIXME: argh)\r\n        FB.files[FB.files_max] = entry;\r\n        FB.files_max ++;\r\n        FB.files = (t_filebrowser_entry**)realloc (FB.files, (FB.files_max + 1) * sizeof (t_filebrowser_entry *));\r\n    }\r\n    while (_findnext (handle, &info) == 0);\r\n\r\n    _findclose (handle);\r\n\r\n#endif\r\n}\r\n\r\nstatic void     FB_Load_Directory_Internal()\r\n{\r\n    static bool no_files_hack = false;\r\n\r\n    // Clear out\r\n    FB.files_max = 0;\r\n    FB.file_pos = 0;\r\n    FB.file_display_first = 0;\r\n    FB.last_click = -1;\r\n    FB.files = (t_filebrowser_entry**)malloc (sizeof (t_filebrowser_entry *));\r\n\r\n    // First add directories and sort them\r\n    FB_Add_Entries(NULL, FB_ENTRY_TYPE_DIRECTORY);\r\n    const int sort_dir_last = FB.files_max;\r\n    const int sort_dir_first = (sort_dir_last > 0 && (strcmp(FB.files [0]->file_name, \"..\") == 0)) ? 1 : 0;\r\n    FB_Sort_Files(sort_dir_first, sort_dir_last);\r\n\r\n    // Then add files\r\n    // FIXME: get the list from Drivers.[ch]\r\n    t_list* ext_list = NULL;\r\n    list_add(&ext_list, (void*)\"SMS\");\r\n    list_add(&ext_list, (void*)\"GG\");\r\n    list_add(&ext_list, (void*)\"SG\");\r\n    list_add(&ext_list, (void*)\"SC\");\r\n    list_add(&ext_list, (void*)\"SF7\");\r\n    list_add(&ext_list, (void*)\"DSK\");\r\n    list_add(&ext_list, (void*)\"OMV\");\r\n    list_add(&ext_list, (void*)\"COL\");\r\n    list_add(&ext_list, (void*)\"BIN\");\r\n    list_add(&ext_list, (void*)\"ROM\");\r\n    #ifdef MEKA_ZIP\r\n        list_add(&ext_list, (void*)\"ZIP\");\r\n    #endif\r\n    FB_Add_Entries(ext_list, FB_ENTRY_TYPE_FILE);\r\n\r\n    // If nothing was found, attempt to chdir to root and try again\r\n    // FIXME: using a static there...\r\n    if (FB.files_max == 0 && !no_files_hack)\r\n    {\r\n        chdir(\"\\\\\");\r\n        no_files_hack = true;\r\n        FB_Load_Directory_Internal();\r\n        return;\r\n    }\r\n    no_files_hack = false;\r\n\r\n    // Sort files\r\n    FB.file_first = sort_dir_last;\r\n    FB.file_last = FB.files_max;\r\n    FB_Sort_Files(FB.file_first, FB.file_last);\r\n\r\n    // Finally add disk drives\r\n    #ifdef ARCH_WIN32\r\n        FB_Add_DiskDrives();\r\n    #endif\r\n}\r\n\r\nvoid        FB_Draw_Infos()\r\n{\r\n    t_filebrowser* app = &FB;\r\n    ALLEGRO_BITMAP* box_gfx = app->box->gfx_buffer;\r\n\r\n    char buf[32];\r\n    sprintf(buf, \"%d/%d\", app->file_pos + 1, app->files_max);\r\n    Font_SetCurrent(app->font_id);\r\n    al_set_target_bitmap(box_gfx);\r\n    al_draw_filled_rectangle(FB_TEXT_PAD_X, app->bottom_y + 2, 88+1, app->bottom_y + 2 + Font_Height()+1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n    Font_Print(FONTID_CUR, buf, FB_TEXT_PAD_X, app->bottom_y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n}\r\n\r\n// Redraw file listing\r\nvoid    FB_Draw_List()\r\n{\r\n    t_filebrowser *app = &FB;\r\n\r\n    ALLEGRO_BITMAP* box_gfx = app->box->gfx_buffer;\r\n\r\n    int     x = FB_TEXT_PAD_X;\r\n    int     y = FB_TEXT_PAD_Y;\r\n\r\n    char    name_buffer [256];\r\n\r\n    const int lines_max = MIN(FB.file_display_first + FB.files_display_count, FB.files_max);\r\n\r\n    const t_frame bb = app->box->frame;\r\n    const int bb_w = app->box->frame.size.x;\r\n\r\n    // Ask scrollbar to refresh\r\n    al_set_target_bitmap(box_gfx);\r\n    al_draw_filled_rectangle(FB_PAD_X + 2, FB_PAD_Y + 2, bb_w - FB_PAD_X - FB_SCROLL_X, FB_PAD_Y + FB_Return_File_Area_Y() - 1, COLOR_SKIN_WIDGET_LISTBOX_BACKGROUND);\r\n    al_draw_line(bb_w - FB_PAD_X - FB_SCROLL_X + 1, FB_PAD_Y + 2, bb_w - FB_PAD_X - FB_SCROLL_X + 1, FB_PAD_Y + FB_Return_File_Area_Y() - 1, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n\r\n    Font_SetCurrent(app->font_id);\r\n    for (int n = FB.file_display_first; n < lines_max; n++)\r\n    {\r\n        t_filebrowser_entry *entry = FB.files[n];\r\n        int     x_max;\r\n        int     x_usage = 0;\r\n        int     entry_file_flag = -1;\r\n\r\n        // Highlight the current file\r\n        if (n == FB.file_pos)\r\n            al_draw_filled_rectangle(FB_PAD_X + 2, y, bb_w - FB_SCROLL_X - FB_PAD_X - 1, y + Font_Height() - 1, COLOR_SKIN_WIDGET_LISTBOX_SELECTION);\r\n\r\n        // Get the name to print and additional width usage (icons, etc...)\r\n        switch (entry->type)\r\n        {\r\n        case FB_ENTRY_TYPE_DIRECTORY:\r\n            {\r\n                // Name\r\n                strcpy(name_buffer, entry->file_name);\r\n                // Width usage for directory '>' marker\r\n                x_usage = 8;\r\n                break;\r\n            }\r\n        case FB_ENTRY_TYPE_DRIVE:\r\n            {\r\n                // Name\r\n                sprintf(name_buffer, Msg_Get(MSG_FileBrowser_Drive), entry->file_name[0]);\r\n                // Width usage for drive '>' marker\r\n                x_usage = 8;\r\n                break;\r\n            }\r\n        case FB_ENTRY_TYPE_FILE:\r\n            {\r\n                // Name\r\n                if (entry->db_entry_name)\r\n                    strcpy(name_buffer, entry->db_entry_name);\r\n                else\r\n                    strcpy(name_buffer, entry->file_name);\r\n\r\n                // Width usage for icons/flags\r\n                x_usage = 0;\r\n                if (entry->db_entry)\r\n                {\r\n                    // Translation icon = +18+18 (translation automatically add the country icon)\r\n                    if (entry->db_entry->flags & DB_FLAG_TRANS)\r\n                    {\r\n                        // Translation icon + Translation flag (+ overwrites)\r\n                        x_usage += 18 + 18;\r\n                        entry_file_flag = DB_Entry_GetTranslationFlag(entry->db_entry);\r\n                    }\r\n                    else\r\n                    {\r\n                        entry_file_flag = DB_Entry_SelectDisplayFlag(entry->db_entry);\r\n                        if (entry_file_flag != -1)\r\n                        {\r\n                            // Country flag\r\n                            x_usage += 18;\r\n                        }\r\n                    }\r\n                    if (entry->db_entry->flags & (DB_FLAG_BAD|DB_FLAG_BIOS|DB_FLAG_HACK|DB_FLAG_HOMEBREW|DB_FLAG_PROTO))\r\n                    {\r\n                        // Any of BAD|BIOS|HACK|HOMEBREW|PROTO = +18 as well\r\n                        x_usage += 18;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        // Compute x_max which is the maximum x position we can draw to\r\n        x_max = bb_w - FB_TEXT_PAD_X - FB_SCROLL_X + 4;\r\n        x_max -= x_usage;\r\n\r\n        // If name doesn't fit in x_max, we have to cut it\r\n        if (x + Font_TextWidth(FONTID_CUR, name_buffer) > x_max)\r\n        {\r\n            const int x_usage_ellipse = Font_TextWidth(FONTID_CUR, \"..\");\r\n            int name_buffer_len = strlen(name_buffer);\r\n            while (x + Font_TextWidth(FONTID_CUR, name_buffer) + x_usage_ellipse > x_max)\r\n            {\r\n                name_buffer_len--;\r\n                name_buffer [name_buffer_len] = EOSTR;\r\n            }\r\n            strcat (name_buffer, \"..\");\r\n        }\r\n\r\n        // Print name\r\n        Font_Print(FONTID_CUR, name_buffer, x, y, COLOR_SKIN_WIDGET_LISTBOX_TEXT);\r\n\r\n        // Print additional infos/icons\r\n        switch (entry->type)\r\n        {\r\n        case FB_ENTRY_TYPE_DIRECTORY:\r\n        case FB_ENTRY_TYPE_DRIVE:\r\n            {\r\n                // Directory/Drive '>' marker\r\n                Font_Print(FONTID_CUR, \">\", bb_w - FB_TEXT_PAD_X - FB_SCROLL_X - 4, y, COLOR_SKIN_WIDGET_LISTBOX_TEXT);\r\n                break;\r\n            }\r\n        case FB_ENTRY_TYPE_FILE:\r\n            {\r\n                if (entry->db_entry)\r\n                {\r\n                    // Start drawing at x_max\r\n                    int x = x_max;\r\n\r\n                    // Hack icon\r\n                    if (entry->db_entry->flags & DB_FLAG_HACK)\r\n                    {\r\n                        al_draw_bitmap(Graphics.Icons.Hack, x + 1, y + 1, 0);\r\n                        x += 18;\r\n                    }\r\n\r\n                    // BAD icon\r\n                    if (entry->db_entry->flags & DB_FLAG_BAD)\r\n                    {\r\n                        al_draw_bitmap(Graphics.Icons.BAD, x + 1+3, y + 1+1, 0);\r\n                        x += 18;\r\n                    }\r\n\r\n                    // Translation icon\r\n                    if (entry->db_entry->flags & DB_FLAG_TRANS)\r\n                    {\r\n                        if (entry_file_flag == FLAG_UK || entry_file_flag == FLAG_US)\r\n                            al_draw_bitmap(Graphics.Icons.Translation_JP, x + 1, y + 1, 0);\r\n                        else\r\n                            al_draw_bitmap(Graphics.Icons.Translation_JP_US, x + 1, y + 1, 0);\r\n                        x += 18;\r\n                        if (entry_file_flag == -1)\r\n                            entry_file_flag = FLAG_UNKNOWN;\r\n                        al_draw_bitmap(Graphics.Flags[entry_file_flag], x + 1, y + 1, 0);\r\n                    }\r\n                    else\r\n                    {\r\n                        // Icons\r\n                        if (entry->db_entry->flags & (DB_FLAG_HOMEBREW | DB_FLAG_PROTO | DB_FLAG_BIOS))\r\n                        {\r\n                            // HomeBrew icon\r\n                            if (entry->db_entry->flags & DB_FLAG_HOMEBREW)\r\n                                al_draw_bitmap(Graphics.Icons.HomeBrew, x + 1, y + 1, 0);\r\n                            // Proto icon\r\n                            else if (entry->db_entry->flags & DB_FLAG_PROTO)\r\n                                al_draw_bitmap(Graphics.Icons.Prototype, x + 1, y + 1, 0);\r\n                            // BIOS icon\r\n                            else if (entry->db_entry->flags & DB_FLAG_BIOS)\r\n                                al_draw_bitmap(Graphics.Icons.BIOS, x + 1, y + 1, 0);\r\n                        }\r\n\r\n                        // Country Flag\r\n                        if (entry_file_flag != -1)\r\n                        {\r\n                            if (entry->db_entry->flags & (DB_FLAG_HOMEBREW | DB_FLAG_PROTO | DB_FLAG_BIOS))\r\n                                x += 18;\r\n                            al_draw_bitmap(Graphics.Flags[entry_file_flag], x + 1, y + 1, 0);\r\n                        }\r\n                    }\r\n                }\r\n                break;\r\n            }\r\n        }\r\n\r\n        // Increment Y position\r\n        y += Font_Height();\r\n    }\r\n\r\n    FB_Draw_Infos();\r\n}\r\n\r\nvoid    FB_Check_and_Repos()\r\n{\r\n    if (FB.file_pos >= FB.files_max)\r\n        FB.file_pos = FB.files_max - 1;\r\n    if (FB.file_pos < 0)\r\n        FB.file_pos = 0;\r\n\r\n    if (FB.file_pos < (FB.files_display_count >> 1))\r\n        FB.file_display_first = 0;\r\n    else if (FB.file_pos >= FB.files_max - (FB.files_display_count / 2))\r\n        FB.file_display_first = FB.files_max - FB.files_display_count;\r\n    else\r\n        FB.file_display_first = FB.file_pos - (FB.files_display_count / 2);\r\n\r\n    if (FB.file_display_first < 0)\r\n        FB.file_display_first = 0;\r\n}\r\n\r\nvoid    FB_Update()\r\n{\r\n    // Skip update if not active\r\n    if (!FB.active)\r\n        return;\r\n\r\n    // If skin has changed, redraw everything\r\n    int dirty = FALSE;\r\n    if (FB.box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        FB_Layout(&FB, FALSE);\r\n        FB.box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n        dirty = TRUE;\r\n    }\r\n\r\n    // Update user inputs only if focused\r\n    if (gui_box_has_focus(FB.box))\r\n    {\r\n        // Update keyboard inputs\r\n        if (Inputs_KeyPressed(ALLEGRO_KEY_ENTER, TRUE) || Inputs_KeyPressed (ALLEGRO_KEY_PAD_ENTER, TRUE))\r\n        {\r\n            FB_OpenSelectedEntry();\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed(ALLEGRO_KEY_HOME, FALSE))\r\n        {\r\n            FB.file_pos = 0;\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed(ALLEGRO_KEY_END, FALSE))\r\n        {\r\n            FB.file_pos = FB.files_max - 1;\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_DOWN, FALSE, 15, 1))\r\n        {\r\n            FB.file_pos ++;\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_UP, FALSE, 15, 1))\r\n        {\r\n            FB.file_pos --;\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_PGDN, FALSE, 30, 4))\r\n        {\r\n            FB.file_pos += FB.files_display_count;\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_PGUP, FALSE, 30, 4))\r\n        {\r\n            FB.file_pos -= FB.files_display_count;\r\n            dirty = TRUE;\r\n        }\r\n        else if (Inputs_KeyPressed(ALLEGRO_KEY_BACKSPACE, false))\r\n        {\r\n            FB_OpenDirectory(\"..\");\r\n            dirty = true;\r\n        }\r\n        // Note: we check for no key modifiers to be pressed\r\n        // Eg: we don't want ALT-L to jump on 'L' games\r\n        else if ((g_keyboard_modifiers & (ALLEGRO_KEYMOD_CTRL | ALLEGRO_KEYMOD_ALT | ALLEGRO_KEYMOD_SHIFT)) == 0)\r\n        {\r\n            // FIXME: this function may need a rewrite. Also, avoid using strupr()!\r\n            // FIXME: could use allegro feature of keycode->ascii conversion\r\n            int i;\r\n            for (i = 0; i < 26; i ++)\r\n            {\r\n                const int keycode = ALLEGRO_KEY_A + i;\r\n                const char keychar = 'A' + i;\r\n                if (Inputs_KeyPressed_Repeat(keycode, FALSE, 20, 2))\r\n                {\r\n                    int j;\r\n                    for (j = FB.file_pos + 1; j < FB.files_max; j ++)\r\n                    {\r\n                        t_filebrowser_entry *entry = FB.files[j];\r\n                        if (entry->type == FB_ENTRY_TYPE_DRIVE)\r\n                            continue;\r\n                        const char c = entry->db_entry_name ? entry->db_entry_name[0] : entry->file_name[0];\r\n                        if (toupper(c) == keychar)\r\n                        {\r\n                            FB.file_pos = j;\r\n                            break;\r\n                        }\r\n                    }\r\n                    if (j == FB.files_max)\r\n                    {\r\n                        for (j = 0; j < FB.file_pos; j ++)\r\n                        {\r\n                            t_filebrowser_entry *entry = FB.files[j];\r\n                            if (entry->type == FB_ENTRY_TYPE_DRIVE)\r\n                                continue;\r\n                            const char c = entry->db_entry_name ? entry->db_entry_name[0] : entry->file_name[0];\r\n                            if (toupper (c) == keychar)\r\n                            {\r\n                                FB.file_pos = j;\r\n                                break;\r\n                            }\r\n                        }\r\n                    }\r\n                    break;\r\n                }\r\n            }\r\n            if (i != 26)\r\n                dirty = TRUE;\r\n        }\r\n\r\n        // Update mouse inputs (wheel)\r\n        if (gui.mouse.wheel_rel != 0)\r\n        {\r\n            const int wheel_speed = (g_keyboard_modifiers & ALLEGRO_KEYMOD_CTRL) ? 10 : 1;\r\n            if (gui.mouse.wheel_rel < 0)\r\n                FB.file_pos += wheel_speed;\r\n            if (gui.mouse.wheel_rel > 0)\r\n                FB.file_pos -= wheel_speed;\r\n            dirty = TRUE;\r\n        }\r\n    }\r\n\r\n    // Fix and redraw\r\n    if (dirty)\r\n    {\r\n        FB_Check_and_Repos();\r\n        FB_Draw_List();\r\n    }\r\n}\r\n\r\nvoid    FB_Load_Directory()\r\n{\r\n    // Msg(MSGT_DEBUG, \"FB_Load_Directory()\");\r\n\r\n    const int old_files_max = FB.files_max;\r\n    const int old_file_pos = FB.file_pos;\r\n    const int old_file_display_first = FB.file_display_first;\r\n    FB_Free_Memory();\r\n    FB_Load_Directory_Internal();\r\n    if (old_files_max == FB.files_max) // nothing has changed in directory // FIXME: argh\r\n    {\r\n        FB.file_pos = old_file_pos;\r\n        FB.file_display_first = old_file_display_first;\r\n    }\r\n    FB_Draw_List();\r\n}\r\n\r\nvoid    FB_LoadAllNames()\r\n{\r\n    // Save current battery backed memory if there's one\r\n    // Because Load_ROM with no verbosing doesn't save it\r\n    BMemory_Save();\r\n\r\n    // Msg(MSGT_DEBUG, \"FB_LoadAllNames()\");\r\n    for (int i = 0; i < FB.files_max; i++)\r\n    {\r\n        t_filebrowser_entry *entry = FB.files[i];\r\n        if (entry->type == FB_ENTRY_TYPE_FILE)\r\n        {\r\n            strncpy(g_env.Paths.MediaImageFile, entry->file_name, sizeof(g_env.Paths.MediaImageFile));\r\n            // Msg(MSGT_DEBUG, \"Loading %d/%d, %s\", i, FB.files_max, file.rom);\r\n            //FB.file_pos = i;\r\n            //FB_Check_and_Repos();\r\n            //FB_Draw_List();\r\n            Load_ROM(LOAD_MODE_GUI, false);\r\n            //gui_redraw_everything_now_once();\r\n        }\r\n    }\r\n\r\n    // Free last loaded ROM\r\n    Free_ROM();\r\n\r\n    // Reload directory and position us to first entry\r\n    FB.file_pos = 0;\r\n    FB.file_display_first = 0;\r\n    FB_Load_Directory();\r\n    FB_Draw_List();\r\n}\r\n\r\nvoid    FB_OpenSelectedEntry()\r\n{\r\n    t_filebrowser_entry *entry = FB.files [FB.file_pos];\r\n    switch (entry->type)\r\n    {\r\n    case FB_ENTRY_TYPE_DIRECTORY:\r\n    case FB_ENTRY_TYPE_DRIVE:\r\n        {\r\n            FB_OpenDirectory(entry->file_name);\r\n            break;\r\n        }\r\n    case FB_ENTRY_TYPE_FILE:\r\n        {\r\n            FB_OpenFile(entry->file_name);\r\n            break;\r\n        }\r\n    default:\r\n        {\r\n            Quit_Msg(\"Error #1452: FB_Open() - Please send a report.\");\r\n            break;\r\n        }\r\n    }\r\n}\r\n\r\nvoid    FB_OpenDirectory(const char* name)\r\n{\r\n    // Mute sound while processing loading or changing directory, which may take time\r\n    Sound_Playback_Mute();\r\n\r\n    // Change directory\r\n    chdir(name);\r\n\r\n    char previous_directory[FILENAME_LEN];\r\n    if (!strcmp(name, \"..\"))\r\n    {\r\n        // If going up the hierarchy we want to position cursor on the orevious directory\r\n        // Abusively use StrPath_RemoveDirectory() since we know current_directory doesn't end with /\r\n        StrPath_RemoveDirectory(previous_directory, FB.current_directory);\r\n    }\r\n    else\r\n    {\r\n        previous_directory[0] = EOSTR;\r\n    }\r\n\r\n    getcwd(FB.current_directory, FILENAME_LEN);\r\n    //printf(\"curdir %s¥n\", FB.current_directory);\r\n    FB_Free_Memory();\r\n    FB_Load_Directory_Internal();\r\n\r\n    if (previous_directory[0] != EOSTR)\r\n    {\r\n        FB_SelectEntryByFileName(previous_directory);\r\n    }\r\n\r\n    FB_Draw_List();\r\n\r\n    // Resume sound\r\n    Sound_Playback_Resume();\r\n}\r\n\r\nvoid    FB_OpenFile(const char* name)\r\n{\r\n    // Mute sound while processing loading or changing directory, which may take time\r\n    Sound_Playback_Mute();\r\n\r\n    strncpy(g_env.Paths.MediaImageFile, name, sizeof(g_env.Paths.MediaImageFile));\r\n    Load_ROM(LOAD_MODE_GUI, true);\r\n    FB_Reload_Names();\r\n    if (g_config.fb_close_after_load)\r\n    {\r\n        FB_Switch();\r\n    }\r\n    if (g_config.fullscreen_after_load)\r\n    {\r\n        Action_Switch_Mode();\r\n    }\r\n\r\n    // Resume sound\r\n    Sound_Playback_Resume();\r\n}\r\n\r\nbool    FB_SelectEntryByFileName(const char* file_name)\r\n{\r\n    for (int i = 0; i < FB.files_max; i++)\r\n    {\r\n        const t_filebrowser_entry *entry = FB.files[i];\r\n        if (strcmp(entry->file_name, file_name) == 0)\r\n        {\r\n            FB.file_pos = i;\r\n            FB_Check_and_Repos();\r\n            return true;\r\n        }\r\n    }\r\n    return false;\r\n}\r\n\r\nvoid    FB_Click_List (t_widget *w)\r\n{\r\n    t_filebrowser* app = &FB;\r\n\r\n    const int i = app->file_display_first + (w->mouse_y / Font_Height(app->font_id));\r\n    if ((i == app->last_click) && (gui.mouse.double_clicked & 1))\r\n    {\r\n        FB_OpenSelectedEntry();\r\n    }\r\n    else\r\n    {\r\n        app->file_pos = i;\r\n        app->last_click = i;\r\n        if (app->file_pos >= app->files_max)\r\n            app->file_pos = app->files_max - 1;\r\n        FB_Draw_List();\r\n    }\r\n}\r\n\r\n// Load all names from DB, based on current country\r\nvoid    FB_Reload_Names()\r\n{\r\n    if (!g_config.fb_uses_DB)\r\n        return;\r\n\r\n    // Get all names\r\n    for (int i = 0; i < FB.files_max; i++)\r\n    {\r\n        t_filebrowser_entry *entry = FB.files[i];\r\n        if (entry->type == FB_ENTRY_TYPE_FILE)\r\n        {\r\n            if (entry->db_entry)\r\n                entry->db_entry_name = DB_Entry_GetCurrentName (entry->db_entry);\r\n            else\r\n                FB_Entry_FindVLFN (entry);\r\n        }\r\n    }\r\n\r\n    // Resort files only\r\n    FB_Sort_Files (FB.file_first, FB.file_last);\r\n\r\n    // Display\r\n    FB_Draw_List();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_filebrowser.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - app_filebrowser.h\n// GUI File Browser - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define FB_ENTRY_TYPE_FILE      (0)\n#define FB_ENTRY_TYPE_DIRECTORY (1)\n#define FB_ENTRY_TYPE_DRIVE     (2)\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    FB_Switch               ();\nvoid    FB_Init                 ();\nvoid    FB_Init_2               ();\nvoid    FB_Close                ();\nvoid    FB_Update               ();\n\nvoid    FB_Load_Directory       ();\nvoid    FB_Reload_Names         ();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_db_entry;\n\nstruct t_filebrowser_entry\n{\n    s16                 type;\n    char *              file_name;\n    const t_db_entry *  db_entry;\n    const char *        db_entry_name;\n};\n\nstruct t_filebrowser\n{\n    t_gui_box *         box;\n    t_font_id           font_id;\n    bool                active;\n    t_filebrowser_entry **  files;\n    int                 files_max;\n    int                 file_pos;\n    int                 file_display_first;\n    int                 file_first, file_last; // Other are directories & drives\n    int                 last_click;\n    char                current_directory[FILENAME_LEN+1];\n    int                 files_display_count;\n\n    int                 bottom_y;\n    t_widget *          widget_scrollbar;\n    t_widget *          widget_click_list;\n    t_widget *          widget_close_button;\n    t_widget *          widget_load_button;\n    t_widget *          widget_load_names_button;\n    t_widget *          widget_reload_dir_button;\n};\n\nextern t_filebrowser    FB;\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/app_game.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - app_game.c\n// Game screen applet - Code\n//-----------------------------------------------------------------------------\n// FIXME: very old code.\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"app_game.h\"\n#include \"db.h\"\n#include \"vdp.h\"\n#include \"vmachine.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_gui_box *  gamebox_instance;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid        gamebox_draw(t_gui_box *box, ALLEGRO_BITMAP *game_buffer)\n{\n    const float scale = g_config.game_window_scale;\n\n    int     x_start = g_driver->x_start;\n    int     y_start = g_driver->y_show_start;\n    int     x_len   = g_driver->x_res;\n    int     y_len   = g_driver->y_res;\n    int     x_dst   = box->frame.pos.x;\n    int     y_dst   = box->frame.pos.y;\n\n    if ((g_driver->id == DRV_SMS) && (Mask_Left_8))\n    {\n        // Center screen when 8 left columns are masked\n        // This not logical but looks good\n        al_draw_filled_rectangle(x_dst, y_dst, x_dst + 4*scale, y_dst + y_len*scale, COLOR_BLACK);\n        al_draw_filled_rectangle(x_dst + (x_len - 4)*scale, y_dst, x_dst + x_len*scale, y_dst + y_len*scale, COLOR_BLACK);\n        x_len -= 8;\n        x_start += 8;\n        x_dst += 4*scale;\n    }\n\n    if (fabs(scale-1.0f) < 0.001f)\n        al_draw_bitmap_region(game_buffer, x_start, y_start, x_len, y_len, x_dst, y_dst, 0x0000);\n    else\n        al_draw_scaled_bitmap(game_buffer, x_start, y_start, x_len, y_len, x_dst, y_dst, x_len*scale, y_len*scale, 0x0000);\n}\n\nvoid        gamebox_compute_size(int *x, int *y)\n{\n    *x = (g_driver->x_res * g_config.game_window_scale) - 1;\n    *y = (g_driver->y_res * g_config.game_window_scale) - 1;\n}\n\nt_gui_box * gamebox_create(int x, int y)\n{\n    t_frame frame;\n    frame.pos.x = x;\n    frame.pos.y = y;\n    gamebox_compute_size(&frame.size.x, &frame.size.y);\n\n    t_gui_box *box = gui_box_new(&frame, \"--\");\n    if (box == NULL)\n        return (NULL);\n\n    box->type = GUI_BOX_TYPE_GAME;\n    box->flags |= GUI_BOX_FLAGS_TAB_STOP;\n    box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;\n    box->size_min.x = (g_driver->x_res/2)-1;\n    box->size_min.y = (g_driver->y_res/2)-1;\n    box->size_step.x = g_driver->x_res/4;\n    box->size_step.y = g_driver->y_res/4;\n    box->size_fixed_ratio = true;\n\n    gui_box_clip_position(box);\n    gamebox_rename_all();\n\n    return (box);\n}\n\nvoid    gamebox_resize_all()\n{\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\n    {\n        t_gui_box* box = (t_gui_box*)boxes->elem;\n        if (box->type == GUI_BOX_TYPE_GAME)\n        {\n            box->size_min.x = (g_driver->x_res/2)-1;\n            box->size_min.y = (g_driver->y_res/2)-1;\n            box->size_step.x = g_driver->x_res/4;\n            box->size_step.y = g_driver->y_res/4;\n            int sx, sy;\n            gamebox_compute_size(&sx, &sy);\n            gui_box_resize(box, sx, sy, false);\n        }\n    }\n    gui.info.must_redraw = TRUE;\n}\n\nvoid    gamebox_rename_all()\n{\n    const char *new_name;\n    \n    if (DB.current_entry)\n    {\n        new_name = DB_Entry_GetCurrentName(DB.current_entry);\n    }\n    else\n    {\n        if (g_machine_flags & MACHINE_CART_INSERTED)\n            new_name = Msg_Get(MSG_DB_Name_Default);\n        else\n            new_name = Msg_Get(MSG_DB_Name_NoCartridge);\n    }\n\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\n    {\n        t_gui_box* box = (t_gui_box*)boxes->elem;\n        if (box->type == GUI_BOX_TYPE_GAME)\n            gui_box_set_title(box, new_name);\n    }\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/app_game.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - app_game.h\n// Game screen applet - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nextern t_gui_box *  gamebox_instance;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nt_gui_box * gamebox_create(int x, int y);\n\nvoid        gamebox_draw(t_gui_box *box, ALLEGRO_BITMAP *game_buffer);\nvoid        gamebox_resize_all();\nvoid        gamebox_rename_all();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/app_mapview.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_mapview.c\r\n// TileMap Viewer - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_mapview.h\"\r\n#include \"desktop.h\"\r\n#include \"g_tools.h\"\r\n#include \"g_widget.h\"\r\n#include \"vdp.h\"\r\n#include \"video_c.h\"\r\n#include \"video_m2.h\"\r\n#include \"video_m5.h\"\r\n#include \"palette.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define TILEMAP_VIEWER_PADDING   (3)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_tilemap_viewer *  TilemapViewer_MainInstance;\r\nt_list *            TilemapViewers;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void         TilemapViewer_SetupLayoutSizes(t_tilemap_viewer *app);\r\nstatic void         TilemapViewer_Layout(t_tilemap_viewer *app, bool setup);\r\nstatic void         TilemapViewer_Update(t_tilemap_viewer *app);\r\nstatic void         TilemapViewer_UpdateAddresses(t_tilemap_viewer *app);\r\nstatic void         TilemapViewer_UpdateInfos(t_tilemap_viewer *app);\r\nstatic void         TilemapViewer_UpdateScroll(t_tilemap_viewer *app);\r\n\r\nstatic void         TilemapViewer_Switch(t_widget *w);\r\nstatic void         TilemapViewer_CallbackTilemapClick(t_widget *w);\r\nstatic void         TilemapViewer_CallbackTilemapAddressScroll(t_widget *w);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nt_tilemap_viewer *  TilemapViewer_New(bool register_desktop)\r\n{\r\n    t_tilemap_viewer* app = (t_tilemap_viewer*)malloc(sizeof(t_tilemap_viewer));\r\n\r\n    // Add to global list\r\n    list_add(&TilemapViewers, app);\r\n\r\n    // Setup members\r\n    app->active                     = FALSE;\r\n    app->config_bg                  = TRUE;\r\n    app->config_fg                  = TRUE;\r\n    app->config_hflip               = TRUE;\r\n    app->config_vflip               = TRUE;\r\n    app->config_scroll              = TRUE;\r\n    app->config_scroll_raster       = TRUE;\r\n    app->config_tilemap_addr        = 0x3800;\r\n    app->config_tilemap_addr_auto   = TRUE;\r\n    app->config_tilemap_addr_manual_base_addr   = 0x0000;\r\n    app->config_tilemap_addr_manual_step_size   = 0x0800;\r\n    app->config_tilemap_addr_manual_step_count  = 8;\r\n    app->tile_hovered               = -1;\r\n    app->tile_selected              = 0;\r\n\r\n    // Start with SMS/GG layout because it is the biggest and we can't resize a gui box above its initial size\r\n    app->layout = TILEMAP_VIEWER_LAYOUT_SMSGG;\r\n    TilemapViewer_SetupLayoutSizes(app);\r\n\r\n    // Create box\r\n    app->frame_box.pos.x        = 524;\r\n    app->frame_box.pos.y        = 52;\r\n    app->box = gui_box_new(&app->frame_box, \"Tilemap Viewer\");  // FIXME-LOCALIZATION\r\n    app->box->user_data = app;\r\n    app->box->destroy = (t_gui_box_destroy_handler)TilemapViewer_Delete;\r\n\r\n    // Register to desktop (applet is disabled by default)\r\n    if (register_desktop)\r\n        Desktop_Register_Box(\"TILEMAP_VIEWER\", app->box, FALSE, &app->active);\r\n\r\n    // Layout\r\n    TilemapViewer_Layout(app, TRUE);\r\n\r\n    // Return new instance\r\n    return (app);\r\n}\r\n\r\nvoid    TilemapViewer_Delete(t_tilemap_viewer *app)\r\n{\r\n    // Remove from global list\r\n    list_remove(&TilemapViewers, app);\r\n    free(app);\r\n}\r\n\r\nvoid    TilemapViewer_ChangeLayout(t_tilemap_viewer *app, t_tilemap_viewer_layout layout)\r\n{\r\n    app->layout = layout;\r\n    gui_box_destroy_widgets(app->box);\r\n    TilemapViewer_SetupLayoutSizes(app);\r\n    gui_box_resize(app->box, app->frame_box.size.x, app->frame_box.size.y, false);\r\n    TilemapViewer_Layout(app, true);\r\n}\r\n\r\nvoid    TilemapViewer_SetupLayoutSizes(t_tilemap_viewer *app)\r\n{\r\n    switch (app->layout)\r\n    {\r\n    case TILEMAP_VIEWER_LAYOUT_SMSGG:\r\n    case TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT:\r\n        {\r\n            app->frame_tilemap.pos.x        = TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap.pos.y        = TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap.size.x       = 256;\r\n            app->frame_tilemap.size.y       = (app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT) ? 256 : 224;\r\n\r\n            app->frame_infos.pos.x          = TILEMAP_VIEWER_PADDING;\r\n            app->frame_infos.pos.y          = app->frame_tilemap.pos.y + app->frame_tilemap.size.y + TILEMAP_VIEWER_PADDING;\r\n            app->frame_infos.size.x         = 180 - TILEMAP_VIEWER_PADDING / 2;\r\n            app->frame_infos.size.y         = 104;\r\n\r\n            app->frame_config.pos.x         = app->frame_infos.pos.x + app->frame_infos.size.x + (TILEMAP_VIEWER_PADDING * 2);\r\n            app->frame_config.pos.y         = app->frame_tilemap.pos.y + app->frame_tilemap.size.y + TILEMAP_VIEWER_PADDING;\r\n            app->frame_config.size.x        = 76;\r\n            app->frame_config.size.y        = 104;\r\n\r\n            app->frame_tilemap_addr.pos.x   = TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap_addr.pos.y   = app->frame_infos.pos.y + app->frame_infos.size.y + TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap_addr.size.x  = 256;\r\n            app->frame_tilemap_addr.size.y  = 16;\r\n\r\n            // Box size (note that we don't touch pos here)\r\n            app->frame_box.size.x           = app->frame_tilemap.size.x + (TILEMAP_VIEWER_PADDING * 2) - 1;\r\n            app->frame_box.size.y           = app->frame_tilemap.size.y + app->frame_infos.size.y + app->frame_tilemap_addr.size.y + (TILEMAP_VIEWER_PADDING * 3) - 1;\r\n            break;\r\n        }\r\n    case TILEMAP_VIEWER_LAYOUT_SGSC:\r\n        {\r\n            app->frame_tilemap.pos.x        = TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap.pos.y        = TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap.size.x       = 256;\r\n            app->frame_tilemap.size.y       = 192;\r\n\r\n            app->frame_infos.pos.x          = TILEMAP_VIEWER_PADDING;\r\n            app->frame_infos.pos.y          = app->frame_tilemap.pos.y + app->frame_tilemap.size.y + TILEMAP_VIEWER_PADDING;\r\n            app->frame_infos.size.x         = 180 + 76 - TILEMAP_VIEWER_PADDING / 2;\r\n            app->frame_infos.size.y         = 90;//26;\r\n\r\n            app->frame_config.pos.x         = app->frame_infos.pos.x + app->frame_infos.size.x + (TILEMAP_VIEWER_PADDING * 2);\r\n            app->frame_config.pos.y         = app->frame_tilemap.pos.y + app->frame_tilemap.size.y + TILEMAP_VIEWER_PADDING;\r\n            app->frame_config.size.x        = 0;//76;\r\n            app->frame_config.size.y        = 90;//26;\r\n\r\n            app->frame_tilemap_addr.pos.x   = TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap_addr.pos.y   = app->frame_infos.pos.y + app->frame_infos.size.y + TILEMAP_VIEWER_PADDING;\r\n            app->frame_tilemap_addr.size.x  = 256;\r\n            app->frame_tilemap_addr.size.y  = 16*1;\r\n\r\n            // Box size (note that we don't touch pos here)\r\n            app->frame_box.size.x           = app->frame_tilemap.size.x + (TILEMAP_VIEWER_PADDING * 2) - 1;\r\n            app->frame_box.size.y           = app->frame_tilemap.size.y + app->frame_infos.size.y + app->frame_tilemap_addr.size.y + (TILEMAP_VIEWER_PADDING * 3) - 1;\r\n            break;\r\n        }\r\n    default:\r\n        assert(0);\r\n    }\r\n}\r\n\r\nvoid         TilemapViewer_Layout(t_tilemap_viewer *app, bool setup)\r\n{\r\n    t_frame frame;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    // Add closebox widget\r\n    if (setup)\r\n        widget_closebox_add(app->box, TilemapViewer_Switch);\r\n\r\n    // Tilemap zone/button\r\n    if (setup)\r\n        app->frame_tilemap_zone = widget_button_add(app->box, &app->frame_tilemap, 1, TilemapViewer_CallbackTilemapClick, FONTID_NONE, NULL);\r\n\r\n    // Horizontal line\r\n    al_draw_line(0, app->frame_tilemap_addr.pos.y+0.5f, app->frame_config.pos.x + app->frame_config.size.x, app->frame_tilemap_addr.pos.y+0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n\r\n    if (app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG || app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT)\r\n    {\r\n        // Vertical line\r\n        al_draw_line(app->frame_config.pos.x - TILEMAP_VIEWER_PADDING*2+1, app->frame_config.pos.y, app->frame_config.pos.x - TILEMAP_VIEWER_PADDING*2+1, app->frame_config.pos.y + app->frame_config.size.y, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n\r\n        // Config/Options\r\n        frame.SetSize(10, 10);\r\n\r\n        frame.pos.x = app->frame_config.pos.x + 2;\r\n        frame.pos.y = app->frame_config.pos.y + 3;\r\n        Font_Print(FONTID_MEDIUM, \"Display\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        frame.pos.x  = app->frame_config.pos.x;\r\n        frame.pos.y += frame.size.y + 3;\r\n        if (setup)\r\n            widget_checkbox_add(app->box, &frame, &app->config_bg, NULL);\r\n        frame.pos.x += frame.size.x + 6;\r\n        Font_Print(FONTID_MEDIUM, \"BG\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        frame.pos.x  = app->frame_config.pos.x;\r\n        frame.pos.y += frame.size.y + 3;\r\n        if (setup)\r\n            widget_checkbox_add(app->box, &frame, &app->config_fg, NULL);\r\n        frame.pos.x += frame.size.x + 6;\r\n        Font_Print(FONTID_MEDIUM, \"FG\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        frame.pos.x  = app->frame_config.pos.x;\r\n        frame.pos.y += frame.size.y + 3;\r\n        if (setup)\r\n            widget_checkbox_add(app->box, &frame, &app->config_hflip, NULL);\r\n        frame.pos.x += frame.size.x + 6;\r\n        Font_Print(FONTID_MEDIUM, \"H Flip\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        frame.pos.x  = app->frame_config.pos.x;\r\n        frame.pos.y += frame.size.y + 3;\r\n        if (setup)\r\n            widget_checkbox_add(app->box, &frame, &app->config_vflip, NULL);\r\n        frame.pos.x += frame.size.x + 6;\r\n        Font_Print(FONTID_MEDIUM, \"V Flip\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        frame.pos.x  = app->frame_config.pos.x;\r\n        frame.pos.y += frame.size.y + 3;\r\n        if (setup)\r\n            widget_checkbox_add(app->box, &frame, &app->config_scroll, NULL);\r\n        frame.pos.x += frame.size.x + 6;\r\n        Font_Print(FONTID_MEDIUM, \"Scroll\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        frame.pos.x  = app->frame_config.pos.x;\r\n        frame.pos.y += frame.size.y + 3;\r\n        if (setup)\r\n            widget_checkbox_add(app->box, &frame, &app->config_scroll_raster, NULL);\r\n        frame.pos.x += frame.size.x + 6;\r\n        Font_Print(FONTID_MEDIUM, \"Raster\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n    }\r\n\r\n    // Tilemap Address - Scrollbar\r\n    frame.SetPos(app->frame_tilemap_addr.pos.x + 136, app->frame_tilemap_addr.pos.y + 3 + 1);\r\n    frame.SetSize(8 * 8, 8);\r\n    if (setup)\r\n    {\r\n        app->widget_tilemap_addr_scrollbar_slot_cur = 0;\r\n        app->widget_tilemap_addr_scrollbar = widget_scrollbar_add(app->box, WIDGET_SCROLLBAR_TYPE_HORIZONTAL, &frame, &app->config_tilemap_addr_manual_step_count, &app->widget_tilemap_addr_scrollbar_slot_cur, 1, TilemapViewer_CallbackTilemapAddressScroll);\r\n    }\r\n\r\n    // Tilemap Address - Auto Button\r\n    frame.pos.x += frame.size.x + 8;\r\n    frame.pos.y  = app->frame_tilemap_addr.pos.y + 3;\r\n    frame.SetSize(10, 10);\r\n    if (setup)\r\n        app->widget_tilemap_addr_auto_checkbox = widget_checkbox_add(app->box, &frame, &app->config_tilemap_addr_auto, NULL);\r\n    frame.pos.x += frame.size.x + 6;\r\n    Font_Print(FONTID_MEDIUM, \"Auto\", frame.pos.x, frame.pos.y + 2, COLOR_SKIN_WINDOW_TEXT);\r\n}\r\n\r\nvoid         TilemapViewer_CallbackTilemapClick(t_widget *w)\r\n{\r\n    t_tilemap_viewer *app = (t_tilemap_viewer *)w->box->user_data; // Get instance\r\n    const int mx = app->frame_tilemap_zone->mouse_x;\r\n    const int my = app->frame_tilemap_zone->mouse_y;\r\n    if (app->frame_tilemap_zone->mouse_action & WIDGET_MOUSE_ACTION_HOVER)\r\n        app->tile_selected = (mx / 8) + (my / 8) * 32;\r\n}\r\n\r\nvoid        TilemapViewer_CallbackTilemapAddressScroll(t_widget *w)\r\n{\r\n    t_tilemap_viewer *app = (t_tilemap_viewer *)w->box->user_data; // Get instance\r\n\r\n    const int new_addr = app->config_tilemap_addr_manual_base_addr + (app->widget_tilemap_addr_scrollbar_slot_cur * app->config_tilemap_addr_manual_step_size);\r\n    const int cur_addr = app->config_tilemap_addr;\r\n\r\n    if (new_addr != cur_addr)\r\n    {\r\n        app->config_tilemap_addr = new_addr;\r\n        app->config_tilemap_addr_auto = FALSE;\r\n    }\r\n}\r\n\r\nvoid         TilemapViewer_Switch(t_widget *w)\r\n{\r\n    t_tilemap_viewer *app = (t_tilemap_viewer *)w->box->user_data; // Get instance\r\n    if (app == TilemapViewer_MainInstance)\r\n    {\r\n        TilemapViewer_SwitchMainInstance();\r\n    }\r\n    else\r\n    {\r\n        app->active ^= 1;\r\n        gui_box_show(app->box, app->active, TRUE);\r\n        if (!app->active)\r\n        {\r\n            // Flag GUI box for deletion\r\n            app->box->flags |= GUI_BOX_FLAGS_DELETE;\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\nvoid         TilemapViewer_SwitchMainInstance()\r\n{\r\n    t_tilemap_viewer *app = TilemapViewer_MainInstance;\r\n    app->active ^= 1;\r\n    // FIXME-LOCAL\r\n    //if (app->active ^= 1)\r\n    //    Msg(MSGT_USER, Msg_Get(MSG_MemoryEditor_Enabled));\r\n    //else\r\n    //    Msg(MSGT_USER, Msg_Get(MSG_MemoryEditor_Disabled));\r\n    gui_box_show(app->box, app->active, TRUE);\r\n    gui_menu_toggle_check(menus_ID.tools, 3);\r\n}\r\n\r\nvoid         TilemapViewer_Update(t_tilemap_viewer *app)\r\n{\r\n    if (!app->active)\r\n        return;\r\n\r\n    // Full relayout when changing video mode\r\n    t_tilemap_viewer_layout required_layout;\r\n    if (tsms.VDP_VideoMode >= 4)\r\n        required_layout = (Wide_Screen_28) ? TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT : TILEMAP_VIEWER_LAYOUT_SMSGG;\r\n    else\r\n        required_layout = TILEMAP_VIEWER_LAYOUT_SGSC;\r\n    if (app->layout != required_layout)\r\n        TilemapViewer_ChangeLayout(app, required_layout);\r\n\r\n    // If skin has changed, redraw everything\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        TilemapViewer_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    }\r\n\r\n    TilemapViewer_UpdateAddresses(app);\r\n\r\n    // Update tilemap\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n\r\n    // FIXME: Video mode numbers\r\n    if (tsms.VDP_VideoMode == 2)\r\n    {\r\n        gui_frame_clear(app->box->gfx_buffer, &app->frame_tilemap, COLOR_SKIN_WINDOW_BACKGROUND);\r\n        ALLEGRO_LOCKED_REGION* locked_region = al_lock_bitmap(app->box->gfx_buffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);\r\n\r\n        // Draw tilemap\r\n        // TODO: pattern name addr slider, 0x0000 -> 0x3C00, 0x0400 increments\r\n        // TODO: vsection mask (use proper name)\r\n        // TODO: pattern data base addr\r\n        // TODO: color table base addr\r\n        // TODO: show info per tile: Index, X,Y, pattern_name\r\n        const u8* pattern_name_table = VRAM + app->config_tilemap_addr;\r\n        const int vsection_mask = sms.VDP[4] & 3;\r\n        int y = 0;\r\n        for (int vsection_idx = 0; vsection_idx < 3; vsection_idx++) // screen in 3 parts\r\n        {\r\n            const u8* tile_base = g_machine.VDP.sg_pattern_gen_address + ((vsection_idx & vsection_mask) * 0x800);  // Pattern data base\r\n            const u8* col_base = g_machine.VDP.sg_color_table_address + ((vsection_idx & vsection_mask) * 0x800);   // Color table base\r\n            for (int ty = 0; ty < 8; ty++)\r\n            {\r\n                int x = 0;\r\n                for (int tx = 0; tx < 32; tx++)\r\n                {\r\n                    const u32 pattern_name = (*pattern_name_table++) * 8;\r\n                    const u8* p1 = tile_base + pattern_name;        // Pattern data\r\n                    const u8* p2 = col_base  + pattern_name;        // Color table\r\n\r\n                    // Draw one tile\r\n                    const int dst_x = app->frame_tilemap.pos.x + x;\r\n                    const int dst_y = app->frame_tilemap.pos.y + y;\r\n                    VDP_Mode0123_DrawTile(app->box->gfx_buffer, locked_region, dst_x, dst_y, p1, p2);\r\n                    p1 += 8;\r\n                    p2 += 8;\r\n                    x += 8;\r\n                }\r\n                y += 8;\r\n            }\r\n        }\r\n\r\n        al_unlock_bitmap(app->box->gfx_buffer);\r\n    }\r\n    else if (tsms.VDP_VideoMode >= 4)\r\n    {\r\n        ALLEGRO_LOCKED_REGION* locked_region = al_lock_bitmap(app->box->gfx_buffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);\r\n\r\n        // Draw tilemap\r\n        const u16 *map = (u16 *)(VRAM + app->config_tilemap_addr);\r\n        for (int j = 0; j != app->frame_tilemap.size.y/8; j++)\r\n        {\r\n            const int dst_y = app->frame_tilemap.pos.y + (j << 3);\r\n            for (int i = 0; i != app->frame_tilemap.size.x/8; i++)\r\n            {\r\n                const int   dst_x           = app->frame_tilemap.pos.x + (i << 3);\r\n                const u16   map_item        = *map++;\r\n                const int   tile_index      = (map_item & 0x01FF);\r\n                const u32 * tile_palette    = (map_item & 0x0800) ? &Palette_EmulationToHostGui[16] : &Palette_EmulationToHostGui[0];\r\n                const u8 *  tile_pixels     = (u8 *)&tgfx.Tile_Decoded[tile_index];\r\n                int         tile_flip       = (map_item & 0x0600);\r\n\r\n                if (!app->config_hflip)\r\n                    tile_flip &= ~0x0200;\r\n                if (!app->config_vflip)\r\n                    tile_flip &= ~0x0400;\r\n\r\n                if ((!app->config_bg && !(map_item & 0x1000)) || (!app->config_fg && (map_item & 0x1000)))\r\n                {\r\n                    alx_locked_draw_filled_rectangle(locked_region, dst_x, dst_y, dst_x + 8, dst_y + 8, COLOR_DEBUG_BACKDROP);\r\n                }\r\n                else\r\n                {\r\n                    // Decode tile if necessary\r\n                    if (tgfx.Tile_Dirty[tile_index] & TILE_DIRTY_DECODE)\r\n                    {\r\n                        Decode_Tile(tile_index);\r\n                        tgfx.Tile_Dirty[tile_index] = TILE_DIRTY_REDRAW;\r\n                    }\r\n\r\n                    // Draw\r\n                    VDP_Mode4_DrawTile(app->box->gfx_buffer, locked_region, tile_pixels, tile_palette, dst_x, dst_y, tile_flip);\r\n                }\r\n            }\r\n        }\r\n        al_unlock_bitmap(app->box->gfx_buffer);\r\n    }\r\n    else\r\n    {\r\n        gui_frame_clear(app->box->gfx_buffer, &app->frame_tilemap, COLOR_SKIN_WINDOW_BACKGROUND);\r\n        char text[64];\r\n        sprintf(text, \"Unsupported video mode: %d\", tsms.VDP_VideoMode);\r\n        Font_Print(FONTID_MEDIUM, text, app->frame_tilemap.pos.x + TILEMAP_VIEWER_PADDING, app->frame_tilemap.pos.y + TILEMAP_VIEWER_PADDING, COLOR_SKIN_WINDOW_TEXT);\r\n    }\r\n\r\n    // Tilemap rectangle\r\n    al_draw_rectangle(\r\n        app->frame_tilemap.pos.x - 0.5f, app->frame_tilemap.pos.y - 0.5f,\r\n        app->frame_tilemap.pos.x + app->frame_tilemap.size.x + 0.5f, app->frame_tilemap.pos.y + app->frame_tilemap.size.y + 0.5f,\r\n        COLOR_SKIN_WIDGET_GENERIC_BORDER, 1.0f);\r\n\r\n    // Update hovered index\r\n    {\r\n        const int mx = app->frame_tilemap_zone->mouse_x;\r\n        const int my = app->frame_tilemap_zone->mouse_y;\r\n        if (app->frame_tilemap_zone->mouse_action & WIDGET_MOUSE_ACTION_HOVER)\r\n            app->tile_hovered = (mx / 8) + (my / 8) * 32;\r\n        else\r\n            app->tile_hovered = -1;\r\n    }\r\n\r\n    // Update hovered/selected tile information\r\n    if (app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG || app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT)\r\n    {\r\n        if (app->config_scroll)\r\n            TilemapViewer_UpdateScroll(app);\r\n    }\r\n    TilemapViewer_UpdateInfos(app);\r\n}\r\n\r\nstatic void     TilemapViewer_UpdateAddresses(t_tilemap_viewer *app)\r\n{\r\n    // Update tilemap address slot\r\n    const int old_tilemap_addr_step_count = app->config_tilemap_addr_manual_step_count;\r\n    if (tsms.VDP_VideoMode >= 4)\r\n    {\r\n        if (Wide_Screen_28)\r\n        {\r\n            app->config_tilemap_addr_manual_base_addr = 0x0700;\r\n            app->config_tilemap_addr_manual_step_size = 0x1000;\r\n            app->config_tilemap_addr_manual_step_count = 4;\r\n            if (app->config_tilemap_addr_auto)\r\n                app->widget_tilemap_addr_scrollbar_slot_cur = (sms.VDP[2] & 0x0C) >> 2;\r\n        }\r\n        else\r\n        {\r\n            app->config_tilemap_addr_manual_base_addr = 0x0000;\r\n            app->config_tilemap_addr_manual_step_size = 0x0800;\r\n            app->config_tilemap_addr_manual_step_count = 8;\r\n            if (app->config_tilemap_addr_auto)\r\n                app->widget_tilemap_addr_scrollbar_slot_cur = (sms.VDP[2] & 0x0E) >> 1;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        app->config_tilemap_addr_manual_base_addr = 0x0000;\r\n        app->config_tilemap_addr_manual_step_size = 0x400;\r\n        app->config_tilemap_addr_manual_step_count = 16;\r\n        if (app->config_tilemap_addr_auto)\r\n            app->widget_tilemap_addr_scrollbar_slot_cur = (sms.VDP[2] & 0x0F);\r\n    }\r\n\r\n    if (old_tilemap_addr_step_count != app->config_tilemap_addr_manual_step_count)\r\n    {\r\n        // Approximately remap selector\r\n        app->widget_tilemap_addr_scrollbar_slot_cur = LinearRemapClamp(app->widget_tilemap_addr_scrollbar_slot_cur, 0, old_tilemap_addr_step_count-1, 0, app->config_tilemap_addr_manual_step_count-1);\r\n    }\r\n\r\n    // Update tilemap address\r\n    app->config_tilemap_addr = app->config_tilemap_addr_manual_base_addr + (app->widget_tilemap_addr_scrollbar_slot_cur * app->config_tilemap_addr_manual_step_size);\r\n}\r\n\r\nstatic void     TilemapViewer_UpdateInfos(t_tilemap_viewer *app)\r\n{\r\n    const int tile_count = (app->frame_tilemap.size.x / 8) * (app->frame_tilemap.size.y / 8);\r\n    if (app->tile_selected >= tile_count)\r\n        app->tile_selected = 0;\r\n\r\n    const int  tile_current = (app->tile_hovered == -1) ? app->tile_selected : app->tile_hovered;\r\n    const int  tile_current_x = tile_current & 31;\r\n    const int  tile_current_y = tile_current >> 5;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    gui_frame_clear(app->box->gfx_buffer, &app->frame_infos, COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    FontPrinter fp(FONTID_MEDIUM);\r\n    if (app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG || app->layout == TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT)\r\n    {\r\n        const u16* tile_map = (u16 *)(VRAM + app->config_tilemap_addr);\r\n        const u16  tile_map_item = tile_map[tile_current];\r\n        char       tile_map_items_bits[2][9];\r\n        StrWriteBitfield((tile_map_item & 0xFF), 8, tile_map_items_bits[0]);\r\n        StrWriteBitfield(((tile_map_item >> 8) & 0xFF), 8, tile_map_items_bits[1]);\r\n\r\n        v2i pos = app->frame_infos.pos;\r\n        pos.x += TILEMAP_VIEWER_PADDING;\r\n        pos.y += TILEMAP_VIEWER_PADDING;\r\n        const v2i vh = v2i(0, Font_Height(FONTID_MEDIUM)+2);\r\n\r\n        fp.Printf(pos, \"Index:     $%03X @ VRAM $%04X\", tile_current, app->config_tilemap_addr + (tile_current * 2)); pos += vh;\r\n        fp.Printf(pos, \"X:         %d\", tile_current_x); pos += vh;\r\n        fp.Printf(pos, \"Y:         %d\", tile_current_y); pos += vh;\r\n\r\n        fp.Printf(pos, \"Name Data: $%04X\", tile_map_item); pos += vh;\r\n        fp.Printf(pos, \"           %%%s.%s\", tile_map_items_bits[1], tile_map_items_bits[0]); pos += vh;\r\n\r\n        //fp.Printf(&pos, \"            ___pcvhn.nnnnnnnn\"); pos += vh;\r\n\r\n        fp.Printf(pos, \"Tile No:   $%03X\", tile_map_item & 0x1FF); pos += vh;\r\n\r\n        fp.Printf(pos, \"H Flip:    %d\", (tile_map_item & 0x200) ? 1 : 0); pos += vh;\r\n        fp.Printf(pos, \"V Flip:    %d\", (tile_map_item & 0x400) ? 1 : 0); pos += vh;\r\n\r\n        fp.Printf(pos, \"Palette:   %d\", (tile_map_item & 0x800) ? 1 : 0); pos += vh;\r\n        fp.Printf(pos, \"Priority:  %s\", (tile_map_item & 0x1000) ? \"FG\" : \"BG\"); pos += vh;\r\n    }\r\n\r\n    if (app->layout == TILEMAP_VIEWER_LAYOUT_SGSC)\r\n    {\r\n        v2i pos = app->frame_infos.pos;\r\n        pos.x += TILEMAP_VIEWER_PADDING;\r\n        pos.y += TILEMAP_VIEWER_PADDING;\r\n        const v2i vh = v2i(0, Font_Height(FONTID_MEDIUM)+2);\r\n\r\n        fp.Printf(pos, \"Index:   $%03X\", tile_current); pos += vh;\r\n        fp.Printf(pos, \"X:       %d\", tile_current_x); pos += vh;\r\n        fp.Printf(pos, \"Y:       %d\", tile_current_y); pos += vh;\r\n\r\n        const int vsection_mask = sms.VDP[4] & 3;\r\n        const int vsection_idx = tile_current_y / 8;\r\n        const u8 char_name = VRAM[(app->config_tilemap_addr + tile_current) & 0x3FFF];\r\n        const u32 char_name_addr = char_name * 8;\r\n        const u8* tile_base = g_machine.VDP.sg_pattern_gen_address + ((vsection_idx & vsection_mask) * 0x800);  // Pattern data base\r\n        const u8* col_base = g_machine.VDP.sg_color_table_address + ((vsection_idx & vsection_mask) * 0x800);   // Color table base\r\n        const u8* char_pattern_data = tile_base + char_name_addr;\r\n        const u8* char_color_data = col_base  + char_name_addr;\r\n\r\n        fp.Printf(pos, \"Name:    1 byte @ VRAM $%04X\", (app->config_tilemap_addr + tile_current) & 0x3FFF); pos += vh;\r\n        fp.Printf(pos, \"         $%02X\", char_name); pos += vh;\r\n\r\n        fp.Printf(pos, \"Pattern: 8 bytes @ VRAM $%04X\", char_pattern_data - VRAM); pos += vh;\r\n        fp.Printf(pos, \"         $%02X $%02X $%02X $%02X $%02X $%02X $%02X $%02X\", char_pattern_data[0], char_pattern_data[1], char_pattern_data[2], char_pattern_data[3], char_pattern_data[4], char_pattern_data[5], char_pattern_data[6], char_pattern_data[7]); pos += vh;\r\n\r\n        fp.Printf(pos, \"Color:   8 bytes @ VRAM $%04X\", char_color_data - VRAM); pos += vh;\r\n        fp.Printf(pos, \"         $%02X $%02X $%02X $%02X $%02X $%02X $%02X $%02X\", char_color_data[0], char_color_data[1], char_color_data[2], char_color_data[3], char_color_data[4], char_color_data[5], char_color_data[6], char_color_data[7]); pos += vh;\r\n    }\r\n\r\n    al_draw_rectangle(\r\n        app->frame_tilemap.pos.x+tile_current_x*8-0.5f, app->frame_tilemap.pos.y+tile_current_y*8-0.5f,\r\n        app->frame_tilemap.pos.x+tile_current_x*8+8.5f, app->frame_tilemap.pos.y+tile_current_y*8+8.5f, COLOR_WHITE, 1.0f);\r\n\r\n    // Tilemap Address\r\n    al_draw_filled_rectangle(\r\n        app->frame_tilemap_addr.pos.x + 1, app->frame_tilemap_addr.pos.y + 1,\r\n        app->frame_tilemap_addr.pos.x + 128 + 1, app->frame_tilemap_addr.pos.y + app->frame_tilemap_addr.size.x + 1,\r\n        COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    v2i pos = app->frame_tilemap_addr.pos + v2i(2,3+2);\r\n    fp.Printf(pos, \"Tilemap @ VRAM $%04X\", app->config_tilemap_addr);\r\n}\r\n\r\nstatic void     TilemapViewer_UpdateScrollDrawLineWrap(t_tilemap_viewer *app, int y, int x1, int x2, ALLEGRO_COLOR color)\r\n{\r\n    x1 &= 255;\r\n    x2 &= 255;\r\n    if (Wide_Screen_28)\r\n    {\r\n        y &= 255;\r\n    }\r\n    else\r\n    {\r\n        if (y >= 224)\r\n            y -= 224;\r\n        else if (y < 0)\r\n            y += 224;\r\n    }\r\n    if (x1 < x2)\r\n    {\r\n        al_draw_hline(\r\n            app->frame_tilemap.pos.x + x1,\r\n            app->frame_tilemap.pos.y + y,\r\n            app->frame_tilemap.pos.x + x2,\r\n            color);\r\n    }\r\n    else if (x1 > x2)\r\n    {\r\n        al_draw_hline(\r\n            app->frame_tilemap.pos.x + x1,\r\n            app->frame_tilemap.pos.y + y,\r\n            app->frame_tilemap.pos.x + 255,\r\n            color);\r\n        al_draw_hline(\r\n            app->frame_tilemap.pos.x + 0,\r\n            app->frame_tilemap.pos.y + y,\r\n            app->frame_tilemap.pos.x + x2,\r\n            color);\r\n    }\r\n    else\r\n    {\r\n        // draw pixel is actually pixel than putpixel on a video memory buffer (no need to lock in/out)\r\n        al_draw_pixel(app->frame_tilemap.pos.x + x1 + 0.5f, app->frame_tilemap.pos.y + y + 0.5f, color);\r\n    }\r\n}\r\n\r\nstatic void     TilemapViewer_UpdateScroll(t_tilemap_viewer *app)\r\n{\r\n    const ALLEGRO_COLOR color_1 = COLOR_BLACK;//makecol(0x20, 0xFF, 0x40);\r\n    const ALLEGRO_COLOR color_2 = COLOR_WHITE;//makecol(0x00, 0xC0, 0x00);\r\n    const int drv_x1  = g_driver->x_start + ((g_driver->id == DRV_SMS && Mask_Left_8) ? 8 : 0);\r\n    const int drv_x2  = g_driver->x_end;\r\n    const int drv_y1  = g_driver->y_show_start;\r\n    const int drv_y2  = g_driver->y_show_end;\r\n    const int y_start = g_machine.VDP.scroll_y_latched;// + (Wide_Screen_28 ? -32 : 0);\r\n    int i;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    if (app->config_scroll_raster)\r\n    {\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y1,     -g_machine.VDP.scroll_x_latched_table[drv_y1] + drv_x1, -g_machine.VDP.scroll_x_latched_table[drv_y1] + drv_x2, color_1);\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y1 + 1, -g_machine.VDP.scroll_x_latched_table[drv_y1] + drv_x1, -g_machine.VDP.scroll_x_latched_table[drv_y1] + drv_x2, color_2);\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y2 - 1, -g_machine.VDP.scroll_x_latched_table[drv_y2] + drv_x1, -g_machine.VDP.scroll_x_latched_table[drv_y2] + drv_x2, color_2);\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y2,     -g_machine.VDP.scroll_x_latched_table[drv_y2] + drv_x1, -g_machine.VDP.scroll_x_latched_table[drv_y2] + drv_x2, color_1);\r\n        for (i = drv_y1+1; i < drv_y2; i++)\r\n        {\r\n            /*\r\n            const int x1a = -g_machine.VDP.scroll_x_latched_table[i-1] + drv_x1;\r\n            const int x1b = -g_machine.VDP.scroll_x_latched_table[i]   + drv_x1;\r\n            const int x2a = -g_machine.VDP.scroll_x_latched_table[i-1] + drv_x2;\r\n            const int x2b = -g_machine.VDP.scroll_x_latched_table[i]   + drv_x2;\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, MAX(x1a,x1b),   MAX(x1a,x1b),   color_1);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, MAX(x1a,x1b)+1, MAX(x1a,x1b)+1, color_2);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, MIN(x2a,x2b)-1, MIN(x2a,x2b)-1, color_2);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, MIN(x2a,x2b),   MIN(x2a,x2b),   color_1);\r\n            */\r\n            const int x1 = -g_machine.VDP.scroll_x_latched_table[i] + drv_x1;\r\n            const int x2 = -g_machine.VDP.scroll_x_latched_table[i] + drv_x2;\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x1,   x1,   color_1);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x1+1, x1+1, color_2);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x2-1, x2-1, color_2);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x2,   x2,   color_1);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y1,     ((Top_No_Scroll && drv_y1 < 16) ? 0 : -g_machine.VDP.scroll_x_latched) + drv_x1, ((Top_No_Scroll && drv_y1 < 16) ? 0 : -g_machine.VDP.scroll_x_latched) + drv_x2, color_1);\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y1 + 1, ((Top_No_Scroll && drv_y1 < 16) ? 0 : -g_machine.VDP.scroll_x_latched) + drv_x1, ((Top_No_Scroll && drv_y1 < 16) ? 0 : -g_machine.VDP.scroll_x_latched) + drv_x2, color_2);\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y2 - 1, -g_machine.VDP.scroll_x_latched + drv_x1, -g_machine.VDP.scroll_x_latched + drv_x2, color_2);\r\n        TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + drv_y2,     -g_machine.VDP.scroll_x_latched + drv_x1, -g_machine.VDP.scroll_x_latched + drv_x2, color_1);\r\n        for (i = drv_y1+1; i < drv_y2; i++)\r\n        {\r\n            const int x1 = ((Top_No_Scroll && i < 16) ? 0 : -g_machine.VDP.scroll_x_latched) + drv_x1;\r\n            const int x2 = ((Top_No_Scroll && i < 16) ? 0 : -g_machine.VDP.scroll_x_latched) + drv_x2;\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x1,   x1,   color_1);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x1+1, x1+1, color_2);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x2-1, x2-1, color_2);\r\n            TilemapViewer_UpdateScrollDrawLineWrap(app, y_start + i, x2,   x2,   color_1);\r\n        }\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    TilemapViewers_Update()\r\n{\r\n    t_list *apps;\r\n    for (apps = TilemapViewers; apps != NULL; apps = apps->next)\r\n    {\r\n        t_tilemap_viewer *app = (t_tilemap_viewer *)apps->elem;\r\n        TilemapViewer_Update(app);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_mapview.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_mapview.h\r\n// TileMap Viewer - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nenum t_tilemap_viewer_layout\r\n{\r\n    TILEMAP_VIEWER_LAYOUT_SMSGG,\r\n    TILEMAP_VIEWER_LAYOUT_SMSGG_EXTRAHEIGHT,\r\n    TILEMAP_VIEWER_LAYOUT_SGSC,\r\n};\r\n\r\nstruct t_tilemap_viewer\r\n{\r\n    bool                    active;\r\n    t_gui_box *             box;\r\n    t_tilemap_viewer_layout layout;\r\n    t_frame                 frame_box;\r\n    t_frame                 frame_tilemap;\r\n    t_frame                 frame_infos;\r\n    t_frame                 frame_config;\r\n    t_frame                 frame_tilemap_addr;\r\n    t_widget *              frame_tilemap_zone;\r\n\r\n    t_widget *              widget_tilemap_addr_scrollbar;\r\n    int                     widget_tilemap_addr_scrollbar_slot_cur;\r\n    t_widget *              widget_tilemap_addr_auto_checkbox;\r\n\r\n    bool                    config_bg;\r\n    bool                    config_fg;\r\n    bool                    config_hflip;\r\n    bool                    config_vflip;\r\n    bool                    config_scroll;\r\n    bool                    config_scroll_raster;\r\n    int                     config_tilemap_addr;\r\n    bool                    config_tilemap_addr_auto;\r\n    int                     config_tilemap_addr_manual_base_addr;       // SMS: $0000  Wide: $0700  SG/SC: $0000\r\n    int                     config_tilemap_addr_manual_step_size;       // SMS: $0800  Wide: $1000  SG/SC: $0400\r\n    int                     config_tilemap_addr_manual_step_count;      // SMS: 8      Wide: 4      SG/SC: 16\r\n    int                     tile_hovered;\r\n    int                     tile_selected;\r\n};\r\n\r\nextern t_tilemap_viewer *   TilemapViewer_MainInstance;\r\nextern t_list *             TilemapViewers;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nt_tilemap_viewer *          TilemapViewer_New(bool register_desktop);\r\nvoid                        TilemapViewer_Delete(t_tilemap_viewer* app);\r\nvoid                        TilemapViewer_SwitchMainInstance();\r\n\r\nvoid                        TilemapViewers_Update();\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_memview.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_memview.c\r\n// Memory Viewer - Code\r\n//-----------------------------------------------------------------------------\r\n// Note: currently referred as \"Memory Viewer\" in the code, but always as \"Memory Editor\" to the user.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_memview.h\"\r\n#include \"app_cheatfinder.h\"\r\n#include \"bmemory.h\"\r\n#include \"coleco.h\"\r\n#include \"desktop.h\"\r\n#include \"g_widget.h\"\r\n#include \"mappers.h\"\r\n#include \"inputs_t.h\"\r\n#include \"vdp.h\"\r\n#include \"vmachine.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define MEMVIEW_COLUMNS_8_PADDING   (5)     // Horizontal padding between each 8 columns\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_memory_viewer *   MemoryViewer_MainInstance;\r\nt_list *            MemoryViewers;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     MemoryViewer_Layout(t_memory_viewer *mv, bool setup);\r\nstatic void     MemoryViewer_Update(t_memory_viewer *mv);\r\nstatic void     MemoryViewer_UpdateInputs(t_memory_viewer *mv);\r\nstatic void     MemoryViewer_MediaReload(t_memory_viewer *mv);\r\nstatic void     MemoryViewer_UpdateAllMemoryRanges(t_memory_viewer *mv);\r\n\r\nstatic void     MemoryViewer_Switch(t_widget *w);\r\n\r\nstatic void     MemoryViewer_ViewPane(t_memory_viewer *mv, t_memory_type memtype);\r\nstatic void     MemoryViewer_ViewPaneCallback(t_widget *w);\r\n\r\nstatic void     MemoryViewer_InputBoxAddress_EnterCallback(t_widget *w);\r\nstatic void     MemoryViewer_InputBoxValue_EditCallback(t_widget *w);\r\nstatic void     MemoryViewer_InputBoxValue_EnterCallback(t_widget *w);\r\nstatic void     MemoryViewer_ClickBottom(t_widget *w);\r\nstatic void     MemoryViewer_ClickMemoryHex(t_widget *w);\r\nstatic void     MemoryViewer_ClickMemoryAscii(t_widget *w);\r\nstatic void     MemoryViewer_SetupEditValueBox(t_memory_viewer *mv);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    MemoryRange_GetDetails(t_memory_type memtype, t_memory_range* mr)\r\n{\r\n    mr->memtype = memtype;\r\n    switch (memtype)\r\n    {\r\n    case MEMTYPE_Z80:\r\n        {\r\n            mr->name            = \"Z80\";\r\n            mr->size            = 0x10000;\r\n            mr->addr_start      = 0x0000;\r\n            mr->addr_hex_length = 4;\r\n            mr->data            = NULL;\r\n            break;\r\n        }\r\n    case MEMTYPE_ROM:\r\n        {\r\n            mr->name            = \"ROM\";\r\n            mr->size            = tsms.Size_ROM;\r\n            mr->addr_start      = 0x00000;\r\n            mr->addr_hex_length = 5;\r\n            mr->data            = ROM;\r\n            break;\r\n        }\r\n    case MEMTYPE_RAM:\r\n        {\r\n            int ram_len, ram_start_addr;\r\n            Mapper_Get_RAM_Infos(&ram_len, &ram_start_addr);\r\n            mr->name            = \"RAM\";\r\n            mr->size            = ram_len;\r\n            mr->addr_start      = ram_start_addr;\r\n            mr->addr_hex_length = 4;\r\n            mr->data            = RAM;\r\n            break;\r\n        }\r\n    case MEMTYPE_VRAM:\r\n        {\r\n            mr->name            = \"VRAM\";\r\n            mr->size            = 0x4000;\r\n            mr->addr_start      = 0x0000;\r\n            mr->addr_hex_length = 4;\r\n            mr->data            = VRAM;\r\n            break;\r\n        }\r\n    case MEMTYPE_PRAM:\r\n        {\r\n            int pram_size = 0;\r\n            switch (g_machine.driver_id)\r\n            {\r\n            case DRV_SMS:   pram_size = 32;  break;\r\n            case DRV_GG:    pram_size = 64;  break;\r\n            }\r\n            mr->name            = \"PAL\";    // FIXME: \"PRAM\" ?\r\n            mr->size            = pram_size;\r\n            mr->addr_start      = 0x00;\r\n            mr->addr_hex_length = 2;\r\n            mr->data            = PRAM;\r\n            break;\r\n        }\r\n    case MEMTYPE_SRAM:\r\n        {\r\n            void* sram_data;\r\n            int sram_size;\r\n            BMemory_Get_Infos((void **)&sram_data, &sram_size);\r\n            mr->name            = \"Save\";   // FIXME: \"SRAM\"?\r\n            mr->size            = sram_size;\r\n            mr->addr_start      = 0x0000;\r\n            mr->addr_hex_length = 4;\r\n            mr->data            = (u8*)sram_data;\r\n            break;\r\n        }\r\n    case MEMTYPE_VREG:\r\n        {\r\n            mr->name            = \"VREG\";\r\n            mr->size            = 11;\r\n            mr->addr_start      = 0x0000;\r\n            mr->addr_hex_length = 1;\r\n            mr->data            = &sms.VDP[0];\r\n            break;\r\n        }\r\n    default:\r\n        assert(0);\r\n    }\r\n}\r\n\r\nu8      t_memory_range::ReadByte(int addr) const\r\n{\r\n    assert(addr >= 0 && addr < this->size);\r\n    switch (this->memtype)\r\n        {\r\n        case MEMTYPE_Z80:\r\n            if (!(g_machine_flags & MACHINE_POWER_ON))\r\n                return 0x00;\r\n            return RdZ80_NoHook(addr);\r\n        case MEMTYPE_ROM:\r\n        case MEMTYPE_RAM:\r\n        case MEMTYPE_VRAM:\r\n        case MEMTYPE_PRAM:\r\n        case MEMTYPE_SRAM:\r\n        case MEMTYPE_VREG:\r\n            if (addr >= 0 && addr < this->size)\r\n                return this->data[addr];\r\n            return 0xFF;\r\n    }\r\n    assert(0);\r\n    return 0x00;\r\n}\r\n\r\nbool    t_memory_range::WriteByte(int addr, u8 v)\r\n{\r\n    assert(addr >= 0 && addr < this->size);\r\n    switch (this->memtype)\r\n    {\r\n    case MEMTYPE_Z80:\r\n        {\r\n            if (!(g_machine_flags & MACHINE_POWER_ON))\r\n                return false;\r\n            WrZ80_NoHook(addr, v);\r\n            return true;\r\n        }\r\n    case MEMTYPE_ROM:\r\n        {\r\n            this->data[addr] = v;\r\n            // We have a special handling there, because SMS/GG mapper emulation is using a\r\n            // different memory area for addresses between 0x0000 and 0x0400\r\n            if (addr < 0x4000)\r\n                if (Mem_Pages[0] == Game_ROM_Computed_Page_0)\r\n                    Game_ROM_Computed_Page_0[addr] = v;\r\n            return true;\r\n        }\r\n    case MEMTYPE_RAM:\r\n        {\r\n            if (g_driver->id == DRV_COLECO)\r\n                Write_Mapper_Coleco(0x6000 + addr, v);  // special case for ColecoVision crazy mirroring\r\n            else\r\n                this->data[addr] = v;\r\n            return true;\r\n        }\r\n    case MEMTYPE_VRAM:\r\n        {\r\n            // Mark corresponding tile as dirty\r\n            this->data[addr] = v;\r\n            tgfx.Tile_Dirty[addr >> 5] |= TILE_DIRTY_DECODE;\r\n            return true;\r\n        }\r\n    case MEMTYPE_PRAM:\r\n        {\r\n            Tms_VDP_Palette_Write(addr, v);\r\n            return true;\r\n        }\r\n    case MEMTYPE_SRAM:\r\n        {\r\n            this->data[addr] = v;\r\n            return true;\r\n        }\r\n    case MEMTYPE_VREG:\r\n        {\r\n            Tms_VDP_Out(addr, v);\r\n            return true;\r\n        }\r\n    }\r\n    assert(0);\r\n    return false;\r\n}\r\n\r\n\r\n// Create and initialize Memory Editor applet\r\nt_memory_viewer *   MemoryViewer_New(bool register_desktop, int size_columns, int size_lines)\r\n{\r\n    t_memory_viewer* app = (t_memory_viewer*)malloc(sizeof(t_memory_viewer));\r\n\r\n    // Check parameters\r\n    assert(size_columns >= -1);\r\n    assert(size_lines >= -1);\r\n\r\n    // Add to global list\r\n    list_add(&MemoryViewers, app);\r\n\r\n    // Setup members\r\n    app->active = TRUE;\r\n    app->size_columns    = (size_columns != -1) ? size_columns : g_config.memory_editor_columns;\r\n    app->size_lines      = (size_lines != -1)   ? size_lines   : g_config.memory_editor_lines;\r\n\r\n    app->frame_hex.size.x = (app->size_columns * (Font_Height(FONTID_MEDIUM) * (2) - 1)) + ((app->size_columns - 1) / 8) * MEMVIEW_COLUMNS_8_PADDING;\r\n    app->frame_hex.size.y = app->size_lines * Font_Height(FONTID_MEDIUM);\r\n    app->frame_ascii.size.x = (app->size_columns * (Font_Height(FONTID_MEDIUM) - 2));\r\n    app->frame_ascii.size.y = app->size_lines * Font_Height(FONTID_MEDIUM);\r\n\r\n    // Default size\r\n    t_frame frame;\r\n    frame.pos.x = 10;\r\n    frame.pos.y = 395;\r\n\r\n    frame.size.x = 4;\r\n    frame.size.x += (Font_Height(FONTID_MEDIUM) * 6) - 7;   // Address\r\n    frame.size.x += app->frame_hex.size.x;                  // Hexadecimal\r\n    frame.size.x += MEMVIEW_COLUMNS_8_PADDING;              // Padding\r\n    frame.size.x += app->frame_ascii.size.x;                // ASCII\r\n    frame.size.x += 4 + 7;                                  // Padding, Scrollbar\r\n\r\n    frame.size.y = 4 + app->frame_hex.size.y + 3;\r\n    frame.size.y += 1 + 1 + Font_Height(FONTID_SMALL) + 2;  // Bottom bar\r\n\r\n    // Create box\r\n    app->box = gui_box_new(&frame, Msg_Get(MSG_MemoryEditor_BoxTitle));\r\n    app->box->user_data = app;\r\n    app->box->destroy = (t_gui_box_destroy_handler)MemoryViewer_Delete;\r\n    // app->box->focus_inputs_exclusive = TRUE; // Set exclusive inputs flag to avoid messing with emulation\r\n    app->box->flags |= GUI_BOX_FLAGS_TAB_STOP;\r\n    app->box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;\r\n    app->box->size_min.x = app->box->frame.size.x;\r\n    app->box->size_min.y = 32;\r\n    app->box->size_max.x = app->box->frame.size.x;\r\n    app->box->size_max.y = 9999;\r\n\r\n    // Register to desktop (applet is disabled by default)\r\n    if (register_desktop)\r\n    {\r\n        Desktop_Register_Box(\"MEMORY\", app->box, FALSE, &app->active);\r\n    }\r\n\r\n    // Layout\r\n    MemoryViewer_Layout(app, true);\r\n\r\n    // Setup other members\r\n    app->memblock_first = 0;\r\n    app->memblocks_max = 0;\r\n    app->values_edit_active = false;\r\n    app->values_edit_position = 0;\r\n    app->pane_current = &app->panes[MEMTYPE_ROM];   // anything but RAM (see below)\r\n\r\n    // Start by viewing RAM\r\n    MemoryViewer_ViewPane(app, MEMTYPE_RAM);\r\n\r\n    // Simulate a ROM load, so that default mapping setting are applied\r\n    // (this is for when checking the Memory Editor on startup before loading a ROM)\r\n    MemoryViewer_MediaReload(app);\r\n\r\n    // Return new instance\r\n    return (app);\r\n}\r\n\r\nvoid    MemoryViewer_Delete(t_memory_viewer* app)\r\n{\r\n    list_remove(&MemoryViewers, app);\r\n    free(app);\r\n}\r\n\r\nstatic void MemoryViewer_Layout(t_memory_viewer* app, bool setup)\r\n{\r\n    {\r\n        const float fh = Font_Height(FONTID_MEDIUM);\r\n\r\n        int contents_y = app->box->frame.size.y;\r\n        contents_y -= (4 + 3);\r\n        contents_y -= (1 + 1) + Font_Height(FONTID_SMALL) + 2;  // Bottom box\r\n        app->size_lines = contents_y / fh;\r\n\r\n        app->frame_hex.pos.x  = 4 + (fh * 6) - 7;\r\n        app->frame_hex.pos.y  = 4;\r\n        app->frame_hex.size.x = (app->size_columns * (fh * 2 - 1)) + ((app->size_columns - 1) / 8) * MEMVIEW_COLUMNS_8_PADDING;\r\n        app->frame_hex.size.y = app->size_lines * fh;\r\n\r\n        app->frame_ascii.pos.x  = app->frame_hex.pos.x + app->frame_hex.size.x + MEMVIEW_COLUMNS_8_PADDING;\r\n        app->frame_ascii.pos.y  = 4;\r\n        app->frame_ascii.size.x = (app->size_columns * (fh - 2));\r\n        app->frame_ascii.size.y = app->size_lines * fh;\r\n\r\n        // A column is made with 2 figures plus a space (except the last one)\r\n        app->frame_view.pos.x = 0;\r\n        app->frame_view.pos.y = 0;\r\n        app->frame_view.size.x = 4;\r\n        // Start of the line: \"XXXXX:\" (6 characters)\r\n        app->frame_view.size.x += (fh * 6) - 7;                 // Address\r\n        app->frame_view.size.x += app->frame_hex.size.x;        // Hexadecimal\r\n        app->frame_view.size.x += MEMVIEW_COLUMNS_8_PADDING;    // Padding\r\n        app->frame_view.size.x += app->frame_ascii.size.x;      // ASCII\r\n        app->frame_view.size.x += 4;                            // Padding\r\n        app->frame_view.size.y = contents_y + 4 + 3;//4 + app->frame_hex.size.y + 3;\r\n    }\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    // Add closebox widget\r\n    if (setup)\r\n        widget_closebox_add(app->box, MemoryViewer_Switch);\r\n\r\n    // Horizontal line to separate buttons from memory\r\n    al_draw_hline(0, app->frame_view.size.y, app->box->frame.size.x, COLOR_SKIN_WINDOW_SEPARATORS);\r\n\r\n    // Setup Memory sections\r\n    {\r\n        t_frame frame;\r\n        frame.pos.x = 174;\r\n        frame.pos.y = app->frame_view.size.y + 1;\r\n        frame.size.x = 30;\r\n        frame.size.y = Font_Height(FONTID_SMALL) + 3;\r\n\r\n        for (int i = 0; i != MEMTYPE_MAX_; i++)\r\n        {\r\n            t_memory_pane* pane = &app->panes[i];\r\n            t_memory_type memtype = (t_memory_type)i;\r\n            MemoryRange_GetDetails(memtype, &pane->memrange);\r\n            pane->memblock_first = 0;\r\n\r\n            if (setup)\r\n                pane->button = widget_button_add(app->box, &frame, 1, MemoryViewer_ViewPaneCallback, FONTID_SMALL, (char *)pane->memrange.name, (void*)memtype);\r\n            else\r\n                pane->button->frame = frame;\r\n\r\n            frame.pos.x += frame.size.x + 2;\r\n        }\r\n    }\r\n\r\n    // Invisible Button to catch click on bottom (to cancel editing)\r\n    t_frame frame;\r\n    frame.SetPos(0, app->frame_view.size.y);\r\n    frame.size.x = app->box->frame.size.x - 16;\r\n    frame.size.y = app->box->frame.size.y - app->frame_view.size.y;\r\n    if (setup)\r\n        app->bottom_box = widget_button_add(app->box, &frame, 1, MemoryViewer_ClickBottom, FONTID_NONE, NULL);\r\n    else\r\n        app->bottom_box->frame = frame;\r\n\r\n    // Address text\r\n    frame.pos.y = app->frame_view.size.y + 1;\r\n    frame.size.y = Font_Height(FONTID_SMALL) + 3;\r\n    Font_Print(FONTID_MEDIUM, \"Address:\", 5, frame.pos.y + 4, COLOR_SKIN_WINDOW_TEXT);\r\n    al_draw_vline(92, frame.pos.y, frame.pos.y + frame.size.y, COLOR_SKIN_WINDOW_SEPARATORS);\r\n\r\n    // Goto Address input box\r\n    Font_Print(FONTID_MEDIUM, \"Goto\", 100, frame.pos.y + 4, COLOR_SKIN_WINDOW_TEXT);\r\n    frame.pos.x = 128;\r\n    frame.size.x = 40;\r\n    if (setup)\r\n    {\r\n        app->address_edit_inputbox = widget_inputbox_add(app->box, &frame, 5, FONTID_MEDIUM, MemoryViewer_InputBoxAddress_EnterCallback);\r\n        widget_inputbox_set_content_type(app->address_edit_inputbox, WIDGET_CONTENT_TYPE_HEXADECIMAL);\r\n    }\r\n    else\r\n    {\r\n        app->address_edit_inputbox->frame = frame;\r\n    }\r\n\r\n    // Invisible buttons to catch click on memory for value editing\r\n    if (setup)\r\n    {\r\n        app->values_hex_box = widget_button_add(app->box, &app->frame_hex, 1, MemoryViewer_ClickMemoryHex, FONTID_NONE, NULL);\r\n        app->values_ascii_box = widget_button_add(app->box, &app->frame_ascii, 1, MemoryViewer_ClickMemoryAscii, FONTID_NONE, NULL);\r\n    }\r\n    else\r\n    {\r\n        app->values_hex_box->frame = app->frame_hex;\r\n        app->values_ascii_box->frame = app->frame_ascii;\r\n    }\r\n\r\n    // Scrollbar\r\n    frame.pos.x = app->frame_view.size.x;\r\n    frame.pos.y = 0;\r\n    frame.size.x = 7;\r\n    frame.size.y = app->frame_view.size.y - 1;\r\n    if (setup)\r\n    {\r\n        app->widget_scrollbar = widget_scrollbar_add(app->box, WIDGET_SCROLLBAR_TYPE_VERTICAL, &frame, &app->memblocks_max, &app->memblock_first, app->size_lines, NULL);\r\n    }\r\n    else\r\n    {\r\n        app->widget_scrollbar->frame = frame;\r\n        widget_scrollbar_set_page_step(app->widget_scrollbar, app->size_lines);\r\n    }\r\n\r\n    // Input box for memory values\r\n    frame.pos.x = 0;\r\n    frame.pos.y = 0;\r\n    frame.size.x = Font_Height(FONTID_MEDIUM) * 2 + 3;\r\n    frame.size.y = Font_Height(FONTID_MEDIUM);\r\n    if (setup)\r\n    {\r\n        app->values_edit_inputbox = widget_inputbox_add(app->box, &frame, 2, FONTID_MEDIUM, MemoryViewer_InputBoxValue_EnterCallback);\r\n        widget_inputbox_set_callback_edit(app->values_edit_inputbox, MemoryViewer_InputBoxValue_EditCallback);\r\n        widget_inputbox_set_flags(app->values_edit_inputbox, WIDGET_INPUTBOX_FLAGS_NO_CURSOR | WIDGET_INPUTBOX_FLAGS_NO_MOVE_CURSOR | WIDGET_INPUTBOX_FLAGS_NO_DELETE | WIDGET_INPUTBOX_FLAGS_NO_SELECTION | WIDGET_INPUTBOX_FLAGS_HIGHLIGHT_CURRENT_CHAR, TRUE);\r\n        widget_inputbox_set_content_type(app->values_edit_inputbox, WIDGET_CONTENT_TYPE_HEXADECIMAL);\r\n        widget_inputbox_set_overwrite_mode(app->values_edit_inputbox, TRUE);\r\n        app->values_edit_inputbox->update_func = NULL;\r\n        widget_set_enabled(app->values_edit_inputbox, false);\r\n    }\r\n    else\r\n    {\r\n        //app->values_edit_inputbox->frame = frame;\r\n        MemoryViewer_SetupEditValueBox(app);\r\n    }\r\n}\r\n\r\nstatic const std::vector<u32>* MemoryViewer_GetHighlightList(t_memory_viewer* app)\r\n{\r\n    const t_cheat_finder* cheat_finder = g_CheatFinder_MainInstance;\r\n    if (cheat_finder && cheat_finder->active && !cheat_finder->addresses_to_highlight_in_memory_editor.empty() && cheat_finder->memtype == app->pane_current->memrange.memtype)\r\n        return &cheat_finder->addresses_to_highlight_in_memory_editor;\r\n    return NULL;\r\n}\r\n\r\nstatic bool MemoryViewer_IsAddressHighlighted(const std::vector<u32>* highlight_list, u32 addr)\r\n{\r\n    if (!highlight_list)\r\n        return false;\r\n    return std::find(highlight_list->begin(), highlight_list->end(), addr) != highlight_list->end();\r\n}\r\n\r\nstatic void        MemoryViewer_Update(t_memory_viewer* app)\r\n{\r\n    t_memory_pane *pane = app->pane_current;\r\n\r\n    char            buf[9];\r\n    const t_font_id font_id = FONTID_MEDIUM;\r\n    const int       font_height = Font_Height(font_id);\r\n    const int       addr_length = pane->memrange.addr_hex_length;\r\n    const int       addr_start  = pane->memrange.addr_start;\r\n\r\n    // Skip update if not active\r\n    if (!app->active)\r\n        return;\r\n\r\n    MemoryViewer_UpdateAllMemoryRanges(app);\r\n\r\n    // If skin has changed, redraw everything\r\n    ALLEGRO_BITMAP* box_gfx = app->box->gfx_buffer;\r\n    al_set_target_bitmap(box_gfx);\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        MemoryViewer_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    }\r\n    else\r\n    {\r\n        // Clear anyway\r\n        al_draw_filled_rectangle(0, 0, app->frame_view.size.x - 1, app->frame_view.size.y, COLOR_SKIN_WINDOW_BACKGROUND);\r\n    }\r\n\r\n    // Update inputs\r\n    MemoryViewer_UpdateInputs(app);\r\n\r\n    int y = 4;\r\n    int addr = app->memblock_first * app->size_columns;\r\n\r\n    //const u8* memory = mv->pane_current->memrange.data;\r\n\r\n    // Lines to separate address/hex/ascii\r\n    // FIXME-SIZE\r\n    {\r\n        int x;\r\n        x = 4 + font_height * 6 - 7 - 7;\r\n        al_draw_vline(x, 0, app->frame_view.size.y - 1, COLOR_SKIN_WINDOW_SEPARATORS);\r\n        //x = 4 + font_height * 6 - 7 + (mv->size_columns * (font_height * 2 - 1) + font_height - 3) + font_height - 3 - 4;\r\n        x = app->frame_ascii.pos.x - 4;//MEMVIEW_COLUMNS_8_PADDING/2;\r\n        al_draw_vline(x, 0, app->frame_view.size.y - 1, COLOR_SKIN_WINDOW_SEPARATORS);\r\n    }\r\n\r\n    // Print current address\r\n    // FIXME: Could create a label widget for this purpose.\r\n    const int addr_offset = (app->memblock_first * app->size_columns) + app->values_edit_position;\r\n    const int addr_abs = addr_start + addr_offset;\r\n    sprintf(buf, \"%0*X\", addr_length, addr_abs);\r\n    al_draw_filled_rectangle(56, app->frame_view.size.y + 1 + 4, 91+1, app->frame_view.size.y + 1 + 4 + Font_Height(font_id) + 1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n    Font_Print(font_id, buf, 56, app->frame_view.size.y + 1 + 4, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n    y = 4;\r\n    if (app->pane_current->memrange.size == 0)\r\n    {\r\n        const char *text = \"None\";\r\n        if (app->pane_current->memrange.memtype == MEMTYPE_Z80 && g_driver->cpu != CPU_Z80)\r\n            text = \"You wish!\";\r\n        int x = 4 + font_height * 6 - 7;\r\n        Font_Print(font_id, text, x, y, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        app->values_edit_active = false;\r\n        MemoryViewer_SetupEditValueBox(app);\r\n    }\r\n    else\r\n    {\r\n        // Highlight request\r\n        const std::vector<u32>* highlight_list = MemoryViewer_GetHighlightList(app);\r\n        widget_set_highlight(app->values_edit_inputbox, MemoryViewer_IsAddressHighlighted(highlight_list, addr_offset));\r\n\r\n        const int y_size = font_height;\r\n        const int x_hex_size = font_height * (2) - 1;\r\n        const int x_asc_size = font_height - 2;\r\n\r\n        // Display all memory content lines\r\n        for (int row = 0; row != app->size_lines; row++, y += y_size)\r\n        {\r\n            if (app->memblock_first + row >= app->memblocks_max)\r\n                continue;\r\n\r\n            // Print address on every new line\r\n            sprintf(buf, \"%0*X\", addr_length, addr + addr_start);\r\n            Font_Print(font_id, buf, 4 + (5 - addr_length) * (font_height - 2), y, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n            // Print 16-bytes in both hexadecimal and ASCII\r\n            int x_hex = app->frame_hex.pos.x;\r\n            int x_asc = app->frame_ascii.pos.x;\r\n\r\n            for (int col = 0; col != app->size_columns; col++, x_hex += x_hex_size, x_asc += x_asc_size)\r\n            {\r\n                // Space each 8 columns (for readability)\r\n                if (col != 0 && ((col & 7) == 0))\r\n                    x_hex += MEMVIEW_COLUMNS_8_PADDING;\r\n\r\n                // Highlight?\r\n                if (MemoryViewer_IsAddressHighlighted(highlight_list, addr))\r\n                    al_draw_filled_rectangle(x_hex-2,y-1,x_hex+x_hex_size-2,y+y_size, COLOR_SKIN_WIDGET_GENERIC_SELECTION);\r\n\r\n                // Get value\r\n                const u8 v = pane->memrange.ReadByte(addr);\r\n\r\n                // Print hexadecimal\r\n                ALLEGRO_COLOR color = COLOR_SKIN_WINDOW_TEXT;\r\n                sprintf(buf, \"%02X\", v);\r\n                Font_Print(font_id, buf, x_hex, y, color);\r\n\r\n                // Print ASCII\r\n                if (app->values_edit_active && (app->values_edit_position == col + (row * app->size_columns)))\r\n                    color = COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT;\r\n                buf[0] = isprint(v) ? v : '.';\r\n                buf[1] = 0;\r\n                Font_Print(font_id, buf, x_asc, y, color);\r\n\r\n                addr++;\r\n                if (addr >= (int)pane->memrange.size)\r\n                    break;\r\n            }\r\n        }\r\n    }\r\n\r\n    // Refresh current value if edition cursor is at the beginning (no editing done yet)\r\n    if (app->values_edit_active)\r\n    {\r\n        if (widget_inputbox_get_cursor_pos(app->values_edit_inputbox) == 0)\r\n        {\r\n            const int addr = (app->memblock_first * app->size_columns) + app->values_edit_position;\r\n            const u8 v = pane->memrange.ReadByte(addr);\r\n            sprintf(buf, \"%02X\", v);\r\n            widget_inputbox_set_value(app->values_edit_inputbox, buf);\r\n            widget_inputbox_set_cursor_pos(app->values_edit_inputbox, 0);\r\n        }\r\n    }\r\n}\r\n\r\nstatic void MemoryViewer_Switch(t_memory_viewer* mv)\r\n{\r\n    if (mv == MemoryViewer_MainInstance)\r\n    {\r\n        MemoryViewer_SwitchMainInstance();\r\n    }\r\n    else\r\n    {\r\n        mv->active ^= 1;\r\n        gui_box_show(mv->box, mv->active, TRUE);\r\n        if (!mv->active)\r\n        {\r\n            // Flag GUI box for deletion\r\n            mv->box->flags |= GUI_BOX_FLAGS_DELETE;\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\nstatic void MemoryViewer_Switch(t_widget* w)\r\n{\r\n    t_memory_viewer* app = (t_memory_viewer *)w->box->user_data; // Get instance\r\n    MemoryViewer_Switch(app);\r\n}\r\n\r\nvoid    MemoryViewer_SwitchMainInstance()\r\n{\r\n    t_memory_viewer* app = MemoryViewer_MainInstance;\r\n    if (app->active ^= 1)\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_MemoryEditor_Enabled));\r\n    else\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_MemoryEditor_Disabled));\r\n    gui_box_show(app->box, app->active, TRUE);\r\n    gui_menu_toggle_check(menus_ID.tools, 4);\r\n}\r\n\r\nstatic void MemoryViewer_ViewPane(t_memory_viewer* app, t_memory_type memtype)\r\n{\r\n    t_memory_pane* pane = &app->panes[memtype];\r\n    if (app->pane_current == pane)\r\n        return;\r\n\r\n    // Save bookmark\r\n    app->pane_current->memblock_first = app->memblock_first;\r\n\r\n    // Update interface button\r\n    widget_set_highlight(app->pane_current->button, FALSE);\r\n    widget_set_highlight(pane->button, TRUE);\r\n\r\n    // Switch section\r\n    app->pane_current    = pane;\r\n    app->memblock_first = pane->memblock_first;\r\n    app->memblocks_max   = (pane->memrange.size + app->size_columns - 1) / app->size_columns;\r\n    assert(pane->memrange.size >= 0);\r\n    //if (mv->memblocks_max < mv->size_lines)\r\n    //    mv->memblocks_max = mv->size_lines;\r\n    MemoryViewer_SetupEditValueBox(app);\r\n}\r\n\r\nstatic void MemoryViewer_ViewPaneCallback(t_widget* w)\r\n{\r\n    t_memory_viewer* app = (t_memory_viewer *)w->box->user_data;\r\n    t_memory_type memtype = (t_memory_type)(intptr_t)w->user_data;\r\n    MemoryViewer_ViewPane(app, memtype);\r\n}\r\n\r\nstatic void MemoryViewer_UpdateAllMemoryRanges(t_memory_viewer* app)\r\n{\r\n    for (int i = 0; i != MEMTYPE_MAX_; i++)\r\n    {\r\n        t_memory_pane* pane = &app->panes[i];\r\n        MemoryRange_GetDetails((t_memory_type)i, &pane->memrange);\r\n\r\n        const int memblocks_max = (pane->memrange.size + app->size_columns - 1) / app->size_columns;\r\n        if (pane->memblock_first + app->size_lines > memblocks_max)\r\n            pane->memblock_first = MAX(memblocks_max - app->size_lines, 0);\r\n\r\n        if (app->pane_current == pane)\r\n            app->memblocks_max = memblocks_max;\r\n    }\r\n}\r\n\r\nstatic void MemoryViewer_MediaReload(t_memory_viewer* app)\r\n{\r\n    MemoryViewer_UpdateAllMemoryRanges(app);\r\n    MemoryViewer_SetupEditValueBox(app);\r\n}\r\n\r\nvoid    MemoryViewer_GotoAddress(t_memory_viewer* app, t_memory_type memtype, u32 offset)\r\n{\r\n    if (!app->active)\r\n        MemoryViewer_Switch(app);\r\n\r\n    // Switch pane if requested\r\n    if (memtype != MEMTYPE_UNKNOWN)\r\n        MemoryViewer_ViewPane(app, memtype);\r\n\r\n    // Check boundaries\r\n    t_memory_pane* pane = app->pane_current;\r\n    const t_memory_range* memrange = &pane->memrange;\r\n    if (offset < 0 || offset >= (u32)memrange->size)\r\n    {\r\n        char buf[16];\r\n        sprintf(buf, \"%0*X\", memrange->addr_hex_length, memrange->addr_start+offset);\r\n        Msg(MSGT_USER, Msg_Get(MSG_MemoryEditor_Address_Out_of_Bound), buf, memrange->name);\r\n        return;\r\n    }\r\n\r\n    // Jump to given address\r\n    app->memblock_first = (offset / app->size_columns) - (app->size_lines/2);\r\n    if (app->memblock_first < 0)\r\n        app->memblock_first = 0;\r\n    if (app->memblock_first + app->size_lines > app->memblocks_max)\r\n        app->memblock_first = MAX(app->memblocks_max - app->size_lines, 0);\r\n    app->values_edit_active = TRUE;\r\n    app->values_edit_position = offset - (app->memblock_first * app->size_columns);\r\n    MemoryViewer_SetupEditValueBox(app);\r\n\r\n    // Clear address box\r\n    widget_inputbox_set_value(app->address_edit_inputbox, \"\");\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Enter callback handler on 'address' input box.\r\n// Set current cursor position to given address (if valid)\r\n//-----------------------------------------------------------------------------\r\nvoid      MemoryViewer_InputBoxAddress_EnterCallback(t_widget* w)\r\n{\r\n    t_memory_viewer* app = (t_memory_viewer *)w->box->user_data; // Get instance\r\n\r\n    // Read address\r\n    const char* text = widget_inputbox_get_value(app->address_edit_inputbox);\r\n    int addr = 0;\r\n    sscanf(text, \"%X\", &addr);\r\n\r\n    const int offset = addr - app->pane_current->memrange.addr_start;\r\n    MemoryViewer_GotoAddress(app, app->pane_current->memrange.memtype, offset);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// MemoryViewer_InputBoxValue_EditCallback(t_widget *w)\r\n// Edit callback handler of moving 'value' input box.\r\n// When second digit is inputed, automatically call 'enter' callback,\r\n// then move cursor to following location.\r\n//-----------------------------------------------------------------------------\r\nstatic void      MemoryViewer_InputBoxValue_EditCallback(t_widget *w)\r\n{\r\n    t_memory_viewer *mv = (t_memory_viewer *)w->box->user_data; // Get instance\r\n\r\n    // When cursor reach 2, switch to next byte\r\n    const int cursor = widget_inputbox_get_cursor_pos(mv->values_edit_inputbox);\r\n    // Msg(MSGT_DEBUG, \"Edit, cursor at %d\", cursor);\r\n    if (cursor == 2)\r\n    {\r\n        // Simulate validation, then re-enable edit box\r\n        MemoryViewer_InputBoxValue_EnterCallback(w);\r\n        mv->values_edit_active = TRUE;\r\n\r\n        // Go to next\r\n        // (this is a copy of the handler code for KEY_RIGHT)\r\n        if (mv->values_edit_position < (mv->size_lines-1) * mv->size_columns - 1)\r\n        {\r\n            mv->values_edit_position++;\r\n            if (mv->memblock_first * mv->size_columns + mv->values_edit_position >= mv->pane_current->memrange.size)\r\n                mv->values_edit_position --;\r\n        }\r\n        else if (((mv->values_edit_position % mv->size_columns) == (mv->size_columns - 1)) && mv->memblock_first + mv->size_lines < mv->memblocks_max)\r\n        {\r\n            mv->memblock_first++;\r\n            mv->values_edit_position -= mv->size_columns - 1;\r\n        }\r\n        else if (mv->values_edit_position < mv->size_lines * mv->size_columns - 1)\r\n        {\r\n            mv->values_edit_position++;\r\n            if (mv->memblock_first * mv->size_columns + mv->values_edit_position >= mv->pane_current->memrange.size)\r\n                mv->values_edit_position --;\r\n        }\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    // FIXME: when cursor reach 2, write and move to next memory location\r\n}\r\n\r\n// Enter callback handler of moving 'value' input box.\r\n// Write input value at current memory location.\r\nstatic void      MemoryViewer_InputBoxValue_EnterCallback(t_widget *w)\r\n{\r\n    t_memory_viewer *mv = (t_memory_viewer *)w->box->user_data; // Get instance\r\n\r\n    const char* text = widget_inputbox_get_value(mv->values_edit_inputbox);\r\n    const int addr = (mv->memblock_first * mv->size_columns) + mv->values_edit_position;\r\n    int value;\r\n    sscanf(text, \"%X\", &value);\r\n    const bool ok = mv->pane_current->memrange.WriteByte(addr, (u8)value);\r\n    if (!ok)\r\n    {\r\n        assert(mv->pane_current->memrange.memtype == MEMTYPE_Z80);\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_MemoryEditor_WriteZ80_Unable));\r\n    }\r\n    mv->values_edit_active = FALSE;\r\n    MemoryViewer_SetupEditValueBox(mv);\r\n}\r\n\r\nstatic void     MemoryViewer_ClickBottom(t_widget* w)\r\n{\r\n    t_memory_viewer* app = (t_memory_viewer *)w->box->user_data; // Get instance\r\n\r\n    app->values_edit_active = FALSE;\r\n    MemoryViewer_SetupEditValueBox(app);\r\n}\r\n\r\nstatic void     MemoryViewer_ClickMemoryHex(t_widget* w)\r\n{\r\n    t_memory_viewer* app = (t_memory_viewer *)w->box->user_data; // Get instance\r\n\r\n    // Msg(MSGT_DEBUG, \"click w->mx = %d, w->my = %d (frame %d x %d)\\n\", w->mx, w->my, w->frame.size.x, w->frame.size.y);\r\n\r\n    // Clicking in empty columns disable edition\r\n    for (int i = 0; i < (app->size_columns - 1) / 8; i++)\r\n    {\r\n        const int max_x = (i + 1) * (8 * (Font_Height(FONTID_MEDIUM) * (2) - 1) + MEMVIEW_COLUMNS_8_PADDING);\r\n        const int min_x = max_x - MEMVIEW_COLUMNS_8_PADDING;\r\n        if (w->mouse_x >= min_x && w->mouse_x < max_x)\r\n        {\r\n            // Hide edit value input box\r\n            app->values_edit_active = FALSE;\r\n            MemoryViewer_SetupEditValueBox(app);\r\n            return;\r\n        }\r\n    }\r\n\r\n    // Inside\r\n    // FIXME-SIZE\r\n    int x, y;\r\n    x = w->mouse_x / (Font_Height(FONTID_MEDIUM) * (2) - 1);\r\n    x = (w->mouse_x - (x / 8) * MEMVIEW_COLUMNS_8_PADDING) / (Font_Height(FONTID_MEDIUM) * (2) - 1);\r\n    y = (w->mouse_y / Font_Height(FONTID_MEDIUM));\r\n\r\n    app->values_edit_position = x + y * app->size_columns;\r\n    app->values_edit_active = TRUE;\r\n    MemoryViewer_SetupEditValueBox(app);\r\n}\r\n\r\nstatic void        MemoryViewer_ClickMemoryAscii(t_widget *w)\r\n{\r\n    t_memory_viewer *mv = (t_memory_viewer *)w->box->user_data; // Get instance\r\n\r\n    int x = w->mouse_x / (Font_Height(FONTID_MEDIUM) - 2);\r\n    int y = w->mouse_y / Font_Height(FONTID_MEDIUM);\r\n    // Msg(MSGT_DEBUG, \"click w->mx = %d, w->my = %d (frame %d x %d)\\n\", w->mx, w->my, w->frame.size.x, w->frame.size.y);\r\n    // Msg(MSGT_DEBUG, \"x = %d, y = %d\\n\", x, y);\r\n\r\n    mv->values_edit_position = x + y * mv->size_columns;\r\n    mv->values_edit_active = TRUE;\r\n    MemoryViewer_SetupEditValueBox(mv);\r\n}\r\n\r\nstatic void    MemoryViewer_SetupEditValueBox(t_memory_viewer* app)\r\n{\r\n    // Disable if out of boundaries\r\n    const int addr = app->memblock_first * app->size_columns + app->values_edit_position;\r\n    if (addr < 0 || addr >= app->pane_current->memrange.size)\r\n    {\r\n        app->values_edit_active = FALSE;\r\n        app->values_edit_position = 0;\r\n    }\r\n\r\n    if (app->values_edit_active)\r\n    {\r\n        // Position input box\r\n        {\r\n            t_frame *frame = &app->values_edit_inputbox->frame;\r\n            const int pos = app->values_edit_position;\r\n            frame->pos.x = (pos % app->size_columns) * (Font_Height(FONTID_MEDIUM) * 2 - 1);\r\n            // Spacing every 8 bytes\r\n            frame->pos.x += MEMVIEW_COLUMNS_8_PADDING * ((pos % app->size_columns) / 8);\r\n            frame->pos.y = (pos / app->size_columns) * Font_Height(FONTID_MEDIUM);\r\n            frame->pos.x += app->values_hex_box->frame.pos.x - 5; // Coordinates are parent relative\r\n            frame->pos.y += app->values_hex_box->frame.pos.y - 1;\r\n        }\r\n\r\n        // Show input box if not already active\r\n        if (app->values_edit_inputbox->update_func == NULL)\r\n        {\r\n            app->values_edit_inputbox->update_func = widget_inputbox_update;\r\n            widget_set_enabled(app->values_edit_inputbox, true);\r\n            app->address_edit_inputbox->update_func = NULL;\r\n        }\r\n\r\n        // Setup input box default content\r\n        u8 value = app->pane_current->memrange.ReadByte(addr);\r\n        char buf[3];\r\n        sprintf(buf, \"%02X\", value);\r\n        widget_inputbox_set_value(app->values_edit_inputbox, buf);\r\n        widget_inputbox_set_cursor_pos(app->values_edit_inputbox, 0);\r\n    }\r\n    else\r\n    {\r\n        // Hide input box if active\r\n        if (app->values_edit_inputbox->update_func != NULL)\r\n        {\r\n            app->address_edit_inputbox->update_func = widget_inputbox_update;\r\n            app->values_edit_inputbox->update_func = NULL;\r\n            widget_set_enabled(app->values_edit_inputbox, false);\r\n        }\r\n    }\r\n}\r\n\r\n// Poll and update user inputs.\r\n// FIXME: This function is probably unnecessary big.\r\nstatic void     MemoryViewer_UpdateInputs(t_memory_viewer *mv)\r\n{\r\n    // Check for focus\r\n    if (!gui_box_has_focus(mv->box))\r\n        return;\r\n\r\n    if (Inputs_KeyPressed(ALLEGRO_KEY_HOME, FALSE))\r\n    {\r\n        mv->memblock_first = 0;\r\n        mv->values_edit_position = 0;\r\n        mv->values_edit_active = TRUE;\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (Inputs_KeyPressed(ALLEGRO_KEY_END, FALSE))\r\n    {\r\n        mv->memblock_first = MAX(mv->memblocks_max - mv->size_lines, 0);\r\n        mv->values_edit_position = MIN(mv->size_lines * mv->size_columns, mv->pane_current->memrange.size - mv->memblock_first * mv->size_columns);\r\n        if (mv->values_edit_position > 0)\r\n            mv->values_edit_position--;\r\n        mv->values_edit_active = TRUE;\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_PGUP, FALSE, 30, 3) || gui.mouse.wheel_rel > 0)\r\n    {\r\n        mv->memblock_first -= mv->size_lines;\r\n        if (mv->memblock_first < 0)\r\n        {\r\n            mv->memblock_first = 0;\r\n            // if (!(gui_mouse.z_rel > 0))\r\n            //    mv->values_edit_position = mv->values_edit_position & 15;\r\n        }\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_PGDN, FALSE, 30, 3) || gui.mouse.wheel_rel < 0)\r\n    {\r\n        mv->memblock_first += mv->size_lines;\r\n        if (mv->memblock_first + mv->size_lines > mv->memblocks_max)\r\n        {\r\n            mv->memblock_first = MAX(mv->memblocks_max - mv->size_lines, 0);\r\n            // if (!(gui_mouse.z_rel < 0))\r\n            //    mv->values_edit_position = (15 * 16) + (mv->values_edit_position & 15);\r\n        }\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_UP, FALSE, 30, 3))\r\n    {\r\n        if (mv->size_lines > 1 && mv->values_edit_position >= (mv->size_lines/2) * mv->size_columns)\r\n            mv->values_edit_position -= mv->size_columns;\r\n        else\r\n        {\r\n            mv->memblock_first--;\r\n            if (mv->memblock_first < 0)\r\n            {\r\n                mv->memblock_first = 0;\r\n                if (mv->values_edit_position >= mv->size_columns)\r\n                    mv->values_edit_position -= mv->size_columns;\r\n            }\r\n        }\r\n        mv->values_edit_active = TRUE;\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_DOWN, FALSE, 30, 3))\r\n    {\r\n        if (mv->values_edit_position < (mv->size_lines/2-1) * mv->size_columns)\r\n        {\r\n            mv->values_edit_position += mv->size_columns;\r\n            if (mv->memblock_first * mv->size_columns + mv->values_edit_position >= mv->pane_current->memrange.size)\r\n                mv->values_edit_position -= mv->size_columns;\r\n        }\r\n        else\r\n        {\r\n            mv->memblock_first++;\r\n            if (mv->memblock_first + mv->size_lines > mv->memblocks_max)\r\n            {\r\n                mv->memblock_first = MAX(mv->memblocks_max - mv->size_lines, 0);\r\n                if (mv->values_edit_position < (mv->size_lines-1) * mv->size_columns)\r\n                    mv->values_edit_position += mv->size_columns;\r\n            }\r\n        }\r\n        mv->values_edit_active = TRUE;\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (mv->values_edit_active && Inputs_KeyPressed_Repeat(ALLEGRO_KEY_LEFT, FALSE, 30, 3))\r\n    {\r\n        if (mv->values_edit_position > 1 * mv->size_columns)\r\n            mv->values_edit_position--;\r\n        else if (mv->memblock_first > 0 && (mv->size_lines > 1 || mv->values_edit_position == 0))\r\n        {\r\n            mv->memblock_first--;\r\n            mv->values_edit_position += mv->size_columns - 1;\r\n        }\r\n        else if (mv->values_edit_position > 0)\r\n            mv->values_edit_position--;\r\n        // mv->values_edit_active = TRUE;\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n    else if (mv->values_edit_active && Inputs_KeyPressed_Repeat(ALLEGRO_KEY_RIGHT, FALSE, 30, 3))\r\n    {\r\n        if (mv->values_edit_position < (mv->size_lines-1) * mv->size_columns - 1)\r\n        {\r\n            mv->values_edit_position++;\r\n            if (mv->memblock_first * mv->size_columns + mv->values_edit_position >= mv->pane_current->memrange.size)\r\n                mv->values_edit_position --;\r\n        }\r\n        else if (((mv->values_edit_position % mv->size_columns) == (mv->size_columns - 1)) && mv->memblock_first + mv->size_lines < mv->memblocks_max)\r\n        {\r\n            mv->memblock_first++;\r\n            mv->values_edit_position -= mv->size_columns - 1;\r\n        }\r\n        else if (mv->values_edit_position < (mv->size_lines * mv->size_columns) - 1)\r\n        {\r\n            mv->values_edit_position++;\r\n            if (mv->memblock_first * mv->size_columns + mv->values_edit_position >= mv->pane_current->memrange.size)\r\n                mv->values_edit_position --;\r\n        }\r\n        // mv->values_edit_active = TRUE;\r\n        MemoryViewer_SetupEditValueBox(mv);\r\n    }\r\n\r\n    // Limits\r\n    if (mv->memblock_first + mv->size_lines > mv->memblocks_max)\r\n        mv->memblock_first = MAX(mv->memblocks_max - mv->size_lines, 0);\r\n    else if (mv->memblock_first < 0)\r\n        mv->memblock_first = 0;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid      MemoryViewers_Update()\r\n{\r\n    for (t_list* mvs = MemoryViewers; mvs != NULL; mvs = mvs->next)\r\n    {\r\n        t_memory_viewer *mv = (t_memory_viewer *)mvs->elem;\r\n        MemoryViewer_Update(mv);\r\n    }\r\n}\r\n\r\nvoid      MemoryViewers_MediaReload()\r\n{\r\n    for (t_list* mvs = MemoryViewers; mvs != NULL; mvs = mvs->next)\r\n    {\r\n        t_memory_viewer *mv = (t_memory_viewer *)mvs->elem;\r\n        MemoryViewer_MediaReload(mv);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_memview.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - app_memview.h\n// Memory Viewer - Headers\n//-----------------------------------------------------------------------------\n\n#pragma once\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\nenum t_memory_type\n{\n    MEMTYPE_UNKNOWN = -1,\n    MEMTYPE_Z80     = 0,\n    MEMTYPE_ROM     = 1,\n    MEMTYPE_RAM     = 2,\n    MEMTYPE_VRAM    = 3,\n    MEMTYPE_PRAM    = 4,\n    MEMTYPE_SRAM    = 5,\n    MEMTYPE_VREG    = 6,\n    MEMTYPE_MAX_    = 7,\n};\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_memory_range\n{\n    t_memory_type       memtype;\n    const char *        name;\n    int                 size;\n    int                 addr_start;\n    int                 addr_hex_length;\n    u8 *                data;\n\n    u8                  ReadByte(int addr) const;\n    bool                WriteByte(int addr, u8 v);\n};\n\nstruct t_memory_pane\n{\n    t_memory_range      memrange;\n    int                 memblock_first;\n    t_widget *          button;\n};\n\nstruct t_memory_viewer\n{\n    // Logic\n    int                 size_columns;\n    int                 size_lines;\n    int                 memblocks_max;\n    int                 memblock_first;\n    t_memory_pane       panes[MEMTYPE_MAX_];\n    t_memory_pane *     pane_current;\n\n    // Interface\n    bool                active;\n    t_gui_box *         box;\n    t_widget *          widget_scrollbar;\n\n    // Interface - Top (values)\n    t_frame             frame_view;\n    t_frame             frame_hex;\n    t_frame             frame_ascii;\n    t_widget *          values_hex_box;\n    t_widget *          values_ascii_box;\n    bool                values_edit_active;\n    int                 values_edit_position;\n    t_widget *          values_edit_inputbox;\n\n    // Interface - Bottom (control)\n    t_widget *          bottom_box;\n    t_widget *          address_edit_inputbox;\n};\n\nextern t_memory_viewer *MemoryViewer_MainInstance;\nextern t_list *         MemoryViewers;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nt_memory_viewer *       MemoryViewer_New(bool register_desktop, int size_columns, int size_lines);\nvoid                    MemoryViewer_Delete(t_memory_viewer* app);\nvoid                    MemoryViewer_GotoAddress(t_memory_viewer* app, t_memory_type memtype, u32 offset);\nvoid                    MemoryViewer_SwitchMainInstance();\n\nvoid                    MemoryViewers_Update();\nvoid                    MemoryViewers_MediaReload();\n\nvoid                    MemoryRange_GetDetails(t_memory_type memtype, t_memory_range* out);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/app_options.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - options.c\r\n// Options Box - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"desktop.h\"\r\n#include \"app_options.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"g_widget.h\"\r\n#include \"palette.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_app_options Options;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define OPTIONS_PAD_X           (6)\r\n#define OPTIONS_PAD_Y           (6)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     Options_Layout(t_app_options *app, bool setup);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void    Option_Switch_Uses_VLFN()\r\n{\r\n    FB_Load_Directory();\r\n}\r\n\r\nstatic void    Option_Switch_NES_Crap()\r\n{\r\n    g_config.enable_NES = FALSE;\r\n    Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_NES_Deny_Facts));\r\n}\r\n\r\nvoid    Options_Init_Applet()\r\n{\r\n    // Create box\r\n    t_frame frame;\r\n    frame.pos.x     = 437;\r\n    frame.pos.y     = 102;\r\n    frame.size.x    = 400;\r\n    frame.size.y    = 220;\r\n    Options.box = gui_box_new(&frame, Msg_Get(MSG_Options_BoxTitle));\r\n    Desktop_Register_Box(\"OPTIONS\", Options.box, 0, &Options.active);\r\n\r\n    // Layout\r\n    Options_Layout(&Options, TRUE);\r\n\r\n    // Setup other members\r\n    Options.active = FALSE;\r\n}\r\n\r\nstatic void     Options_Layout_AddLine(t_app_options* app, bool setup, t_frame *frame, const char *text, bool *v, void (*func)())\r\n{\r\n    frame->pos.x = OPTIONS_PAD_X;\r\n    if (setup)\r\n        widget_checkbox_add(Options.box, frame, v, (t_widget_callback)func); // FIXME: Cast\r\n    frame->pos.x += frame->size.x + Font_TextWidth(app->font_id, \" \");\r\n    Font_Print(app->font_id, text, frame->pos.x, frame->pos.y+2, COLOR_SKIN_WINDOW_TEXT);\r\n    frame->pos.y += (int)(Font_Height(app->font_id) * 1.3f);\r\n}\r\n\r\nstatic void     Options_Layout(t_app_options* app, bool setup)\r\n{\r\n    app->font_id = (t_font_id)g_config.font_options;\r\n\r\n    t_frame frame;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (setup)\r\n    {\r\n        // Add closebox widget\r\n        widget_closebox_add(Options.box, (t_widget_callback)Options_Switch);\r\n\r\n        // Add close button\r\n        frame.size.x = Font_TextWidth(app->font_id, Msg_Get(MSG_Options_Close))+15;\r\n        frame.size.y = Font_Height(app->font_id)*2;\r\n        frame.pos.x = Options.box->frame.size.x - frame.size.x - OPTIONS_PAD_X;\r\n        frame.pos.y = Options.box->frame.size.y - frame.size.y - OPTIONS_PAD_Y;\r\n        widget_button_add(Options.box, &frame, 1, (t_widget_callback)Options_Switch, app->font_id, Msg_Get(MSG_Options_Close));\r\n    }\r\n\r\n    // Draw option lines\r\n    frame.pos.x = Font_Height(app->font_id)-2;\r\n    frame.pos.y = OPTIONS_PAD_Y;\r\n    frame.size.x = Font_Height(app->font_id);\r\n    frame.size.y = Font_Height(app->font_id);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_BIOS_Enable),                &g_config.enable_BIOS,                   NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_DB_Display),                 &g_config.fb_uses_DB,                    Option_Switch_Uses_VLFN);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_Product_Number),             &g_config.show_product_number,           NULL);\r\n    //Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_Bright_Palette),           &g_config.palette_type,                  Palette_Emu_Reload);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_Allow_Opposite_Directions),  &g_config.allow_opposite_directions,     NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_Load_Close),                 &g_config.fb_close_after_load,           NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_Load_FullScreen),            &g_config.fullscreen_after_load,         NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_FullScreen_Messages),        &g_config.show_fullscreen_messages,      NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_GUI_VSync),                  &g_config.video_mode_gui_vsync,          NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_Capture_Crop_Align),         &g_config.capture_crop_align_8x8,        NULL);\r\n    Options_Layout_AddLine(app, setup, &frame, Msg_Get(MSG_Options_NES_Enable),                 &g_config.enable_NES,                    Option_Switch_NES_Crap);\r\n}\r\n\r\nvoid    Options_Update(void)\r\n{\r\n    t_app_options *app = &Options;  // Global instance\r\n\r\n    // Skip update if not active\r\n    if (!app->active)\r\n        return;\r\n\r\n    // If skin has changed, redraw everything\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        Options_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    }\r\n}\r\n\r\nvoid    Options_Switch()\r\n{\r\n    Options.active ^= 1;\r\n    gui_box_show(Options.box, Options.active, TRUE);\r\n    gui_menu_toggle_check(menus_ID.file, 8);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/app_options.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - options.h\n// Options Box - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_app_options\n{\n    t_gui_box * box;\n    t_font_id   font_id;\n    bool        active;\n};\n\nextern t_app_options Options;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Options_Init_Applet     (void);\nvoid    Options_Update          (void);\nvoid    Options_Switch          (void);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/app_palview.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_palview.c\r\n// Palette Viewer - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_palview.h\"\r\n#include \"desktop.h\"\r\n#include \"g_tools.h\"\r\n#include \"g_widget.h\"\r\n#include \"palette.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_app_palette_viewer    PaletteViewer;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void    PaletteViewer_Layout(t_app_palette_viewer *app, bool setup);\r\nstatic void    PaletteViewer_CallbackSelectColor(t_widget *w);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    PaletteViewer_Init()\r\n{\r\n    t_app_palette_viewer *pv = &PaletteViewer;\r\n\r\n    // Setup\r\n    pv->active          = TRUE;\r\n    pv->dirty           = TRUE;\r\n    pv->palette_size    = 32; // Note: PaletteViewer_SetPaletteSize() is called after setting up the window\r\n    pv->color_displayed = -1;\r\n    pv->color_hovered   = -1;\r\n    pv->color_selected  = -1;\r\n\r\n    // Create box\r\n    t_frame frame;\r\n    frame.pos.x     = 163;\r\n    frame.pos.y     = 53;\r\n    frame.size.x    = 192-1;\r\n    frame.size.y    = 49+13;\r\n    pv->box = gui_box_new(&frame, Msg_Get(MSG_Palette_BoxTitle));\r\n    pv->box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;\r\n    pv->box->size_min.x = 32*2-1;//frame.size.x;\r\n    pv->box->size_min.y = 24;\r\n    pv->box->size_max.x = 32*16-1;//frame.size.x;\r\n    pv->box->size_max.y = 88;\r\n    pv->box->size_step.x = 32;\r\n    pv->box->size_step.y = 2;\r\n\r\n    // Register to desktop (applet is enabled by default)\r\n    Desktop_Register_Box (\"PALETTE\", pv->box, TRUE, &pv->active);\r\n\r\n    // Layout\r\n    PaletteViewer_Layout(pv, TRUE);\r\n\r\n    // Configuration\r\n    PaletteViewer_SetPaletteSize(pv, g_driver->colors);\r\n}\r\n\r\nvoid    PaletteViewer_Layout(t_app_palette_viewer* app, bool setup)\r\n{\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (setup)\r\n        widget_closebox_add(app->box, (t_widget_callback)PaletteViewer_Switch);\r\n\r\n    // Setup frames\r\n    app->frame_palette.pos.x     = 0;\r\n    app->frame_palette.pos.y     = 0;\r\n    app->frame_palette.size.x    = app->box->frame.size.x;\r\n    app->frame_palette.size.y    = app->box->frame.size.y - 13;\r\n    app->frame_info.pos.x        = 0;\r\n    app->frame_info.pos.y        = app->frame_palette.size.y;\r\n    app->frame_info.size.x       = app->box->frame.size.x;\r\n    app->frame_info.size.y       = 13;\r\n\r\n    if (setup)\r\n        app->frame_palette_zone      = widget_button_add(app->box, &app->frame_palette, 1, PaletteViewer_CallbackSelectColor, FONTID_NONE, NULL);\r\n    else\r\n        app->frame_palette_zone->frame = app->frame_palette;\r\n\r\n    // Draw separator\r\n    al_draw_line(app->frame_info.pos.x, app->frame_info.pos.y+0.5f, app->frame_info.pos.x + app->frame_info.size.x+1, app->frame_info.pos.y+0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n\r\n    // Draw current color square\r\n    gui_rect(LOOK_THIN, 2, app->frame_info.pos.y + 1, 2 + 11, app->frame_info.pos.y + 1 + 11, COLOR_SKIN_WIDGET_GENERIC_BORDER);\r\n}\r\n\r\nvoid    PaletteViewer_Switch()\r\n{\r\n    t_app_palette_viewer *pv = &PaletteViewer;  // Global instance\r\n\r\n    if (pv->active ^= 1)\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Palette_Enabled));\r\n    else\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Palette_Disabled));\r\n    gui_box_show (pv->box, pv->active, TRUE);\r\n    gui_menu_toggle_check (menus_ID.tools, 1);\r\n}\r\n\r\n// Note: has to be executed after tileviewer::update\r\nvoid    PaletteViewer_Update()\r\n{\r\n    t_app_palette_viewer *pv = &PaletteViewer;  // Global instance\r\n    ALLEGRO_BITMAP* box_gfx = pv->box->gfx_buffer;\r\n\r\n    // Skip update if not active\r\n    if (!pv->active)\r\n        return;\r\n\r\n    int         i;\r\n    bool        dirty = FALSE;\r\n    const int   color_box_size = al_get_bitmap_width(box_gfx) / pv->palette_size;\r\n    int         color_current;\r\n    bool        color_current_refresh;\r\n\r\n    // If skin has changed, redraw everything\r\n    if (pv->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        PaletteViewer_Layout(pv, FALSE);\r\n        pv->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n        pv->dirty = TRUE;\r\n    }\r\n\r\n    // Update hovered color index\r\n    {\r\n        const int mx = pv->frame_palette_zone->mouse_x;\r\n        //const int my = pv->frame_palette_zone->mouse_y;\r\n        if (pv->frame_palette_zone->mouse_action & WIDGET_MOUSE_ACTION_HOVER)\r\n            pv->color_hovered = (mx / color_box_size);\r\n        else\r\n            pv->color_hovered = -1;\r\n    }\r\n\r\n    color_current = (pv->color_hovered != -1) ? pv->color_hovered : pv->color_selected;\r\n    color_current_refresh = /*(color_current == -1) ? TRUE :*/ ((color_current != pv->color_displayed) ? TRUE : FALSE);\r\n\r\n    // Draw palette\r\n    al_set_target_bitmap(box_gfx);\r\n    for (i = 0; i != pv->palette_size; i++)\r\n    {\r\n        if (pv->dirty || Palette_EmulationFlags[i] & PALETTE_EMULATION_FLAGS_DIRTY)\r\n        {\r\n            al_draw_filled_rectangle(\r\n                (i * color_box_size), 0,\r\n                (i * color_box_size) + color_box_size, pv->frame_palette.size.y,\r\n                Palette_Emulation[i]);\r\n            Palette_EmulationFlags[i] &= ~PALETTE_EMULATION_FLAGS_DIRTY;\r\n            dirty = TRUE;\r\n            if (i == color_current)\r\n                color_current_refresh = TRUE;\r\n        }\r\n    }\r\n\r\n    if (pv->dirty || color_current_refresh)\r\n    {\r\n        al_draw_filled_rectangle(16, pv->frame_info.pos.y + 1, pv->frame_info.pos.x + pv->frame_info.size.x + 1, pv->frame_info.pos.y + pv->frame_info.size.y + 1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n        dirty = TRUE;\r\n\r\n        if (color_current != -1)\r\n        {\r\n            char buf[64];\r\n            char color_bits[20];\r\n\r\n            // Color square\r\n            al_draw_filled_rectangle(4, pv->frame_info.pos.y + 3, 4 + 8, pv->frame_info.pos.y + 3 + 8, Palette_Emulation[color_current]);\r\n\r\n            // Description\r\n            sprintf(buf, \"Color %d ($%02X)\", color_current, color_current);\r\n            switch (g_driver->id)\r\n            {\r\n                case DRV_SMS:\r\n                    color_bits[0] = '%';\r\n                    StrWriteBitfield(PRAM[color_current], 8, color_bits + 1);\r\n                    sprintf(buf+strlen(buf), \" - %s\", color_bits);\r\n                    break;\r\n                case DRV_GG:\r\n                    color_bits[0] = '%';\r\n                    StrWriteBitfield(PRAM[color_current * 2 + 1], 8, color_bits + 1);\r\n                    color_bits[9] = '.';\r\n                    StrWriteBitfield(PRAM[color_current * 2 + 0], 8, color_bits + 10);\r\n                    sprintf(buf+strlen(buf), \" - %s\", color_bits);\r\n                    break;\r\n                default:\r\n                    color_bits[0] = 0;\r\n                    break;\r\n            }\r\n            Font_Print(FONTID_SMALL, buf, 16, pv->frame_info.pos.y + 1, COLOR_SKIN_WINDOW_TEXT);\r\n            dirty = TRUE;\r\n            pv->color_displayed = color_current;\r\n        }\r\n        else\r\n        {\r\n            // Fill with black\r\n            al_draw_filled_rectangle(4, pv->frame_info.pos.y + 3, 4 + 8, pv->frame_info.pos.y + 3 + 8, COLOR_BLACK);\r\n        }\r\n    }\r\n\r\n    if (pv->dirty || dirty)\r\n        pv->dirty = FALSE;\r\n}\r\n\r\nvoid    PaletteViewer_SetPaletteSize(t_app_palette_viewer *pv, int palette_size)\r\n{\r\n    pv->palette_size = palette_size;\r\n}\r\n\r\nvoid    PaletteViewer_CallbackSelectColor(t_widget *w)\r\n{\r\n    t_app_palette_viewer *pv = &PaletteViewer;  // Global instance\r\n    const int color_box_size = al_get_bitmap_width(pv->box->gfx_buffer) / pv->palette_size;\r\n\r\n    if (w->mouse_action & WIDGET_MOUSE_ACTION_HOVER)\r\n        pv->color_selected = (w->mouse_x / color_box_size);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_palview.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - app_palview.h\r\n// Palette Viewer - Interface\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_app_palette_viewer\r\n{\r\n    // Interface\r\n    bool                active;\r\n    bool                dirty;\r\n    t_gui_box *         box;\r\n    t_frame             frame_palette;\r\n    t_frame             frame_info;\r\n    t_widget *          frame_palette_zone;\r\n\r\n    // Logic\r\n    int                 palette_size;\r\n    int                 color_displayed; // -1 if none, else 0 to palette_size-1\r\n    int                 color_hovered;   // -1 if none, else 0 to palette_size-1\r\n    int                 color_selected;  // -1 if none, else 0 to palette_size-1\r\n\r\n};\r\n\r\nextern t_app_palette_viewer    PaletteViewer;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    PaletteViewer_Init              (void);\r\nvoid    PaletteViewer_Switch            (void);\r\nvoid    PaletteViewer_Update            (void);\r\nvoid    PaletteViewer_SetPaletteSize    (t_app_palette_viewer *pv, int palette_size);\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_techinfo.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - techinfo.c\r\n// Technical Information Applet - Code\r\n//-----------------------------------------------------------------------------\r\n// TO DO:\r\n//  - re do.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_techinfo.h\"\r\n#include \"desktop.h\"\r\n#include \"debugger.h\"\r\n#include \"g_widget.h\"\r\n#include \"sound/psg.h\"\r\n#include \"vdp.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_app_tech_info TechInfo;\r\n\r\nextern u8 *          FM_Regs;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void TechInfo_Layout(t_app_tech_info *app, bool setup)\r\n{\r\n    // Clear\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (setup)\r\n    {\r\n        // Add closebox widget\r\n        widget_closebox_add(app->box, (t_widget_callback)TechInfo_Switch);\r\n    }\r\n}\r\n\r\nvoid        TechInfo_Init()\r\n{\r\n    t_font_id font_id = (t_font_id)g_config.font_techinfo;\r\n\r\n    t_frame frame;\r\n    frame.pos.x = 306;\r\n    frame.pos.y = 482;\r\n    frame.size.x = TECHINFO_COLUMNS * Font_TextWidth(font_id, \" \");\r\n    frame.size.y = TECHINFO_LINES * Font_Height(font_id);\r\n\r\n    TechInfo.active = FALSE;\r\n    TechInfo.box = gui_box_new(&frame, Msg_Get(MSG_TechInfo_BoxTitle));\r\n    Desktop_Register_Box(\"TECHINFO\", TechInfo.box, 0, &TechInfo.active);\r\n    TechInfo.box->update = TechInfo_Update;\r\n\r\n    // Layout\r\n    TechInfo_Layout(&TechInfo, true);\r\n\r\n    // Clear lines\r\n    for (int i = 0; i != TECHINFO_LINES; i++)\r\n    {\r\n        strcpy(TechInfo.lines[i], \"\");\r\n        TechInfo.lines_dirty[i] = true;\r\n    }\r\n}\r\n\r\nstatic void TechInfo_Redraw(t_app_tech_info* app)\r\n{\r\n    t_font_id font_id = (t_font_id)g_config.font_techinfo;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    for (int i = 0; i != TECHINFO_LINES; i++)\r\n    {\r\n        if (app->lines_dirty[i])\r\n        {\r\n            const int h = Font_Height(font_id);\r\n            const int y = (h * i);\r\n\r\n            al_set_target_bitmap(app->box->gfx_buffer);\r\n            al_draw_filled_rectangle(0, y, app->box->frame.size.x+1, y + h, COLOR_SKIN_WINDOW_BACKGROUND);\r\n            Font_Print(font_id, app->lines[i], 4, y, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n            app->lines_dirty[i] = FALSE;\r\n        }\r\n    }\r\n}\r\n\r\nstatic void TechInfo_SetLine(t_app_tech_info *app, const char *line, int line_idx)\r\n{\r\n    // If line hasn't changed, ignore the update\r\n    if (strcmp(TechInfo.lines[line_idx], line) == 0)\r\n        return;\r\n\r\n    // Copy new line, set dirty flag\r\n    strncpy(TechInfo.lines[line_idx], line, sizeof(TechInfo.lines[line_idx])/sizeof(*TechInfo.lines[line_idx]));\r\n    TechInfo.lines_dirty[line_idx] = TRUE;\r\n}\r\n\r\nvoid        TechInfo_Update(void)\r\n{\r\n    t_app_tech_info *app = &TechInfo;   // Global instance\r\n\r\n    char    line[512];\r\n    int     line_idx = 0;\r\n\r\n    // Skip update if not active\r\n    if (!app->active)\r\n        return;\r\n\r\n    // If skin has changed, redraw everything\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        int i;\r\n        TechInfo_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n        for (i = 0; i != TECHINFO_LINES; i++)\r\n            TechInfo.lines_dirty[i] = TRUE;\r\n    }\r\n\r\n    sprintf(line, \"   [MODE] %s (%s)\", g_driver->full_name, g_driver->short_name);\r\n    TechInfo_SetLine(app, line, line_idx++);\r\n\r\n    // Sega 8-bit\r\n\r\n    // - VDP\r\n    {\r\n        char model_str[9];\r\n        switch (g_machine.VDP.model)\r\n        {\r\n        case VDP_MODEL_315_5124: sprintf(model_str, \"315-5124\"); break;\r\n        case VDP_MODEL_315_5246: sprintf(model_str, \"315-5246\"); break;\r\n        case VDP_MODEL_315_5378: sprintf(model_str, \"315-5378\"); break;\r\n        case VDP_MODEL_315_5313: sprintf(model_str, \"315-5313\"); break;\r\n        default: assert(0); break;\r\n        }\r\n        sprintf(line, \"    [VDP] Model:%s - Display Mode:%d\",\r\n            model_str, tsms.VDP_VideoMode);\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n        sprintf(line, \"    [VDP] Status:$%02X - Address:$%04X - Latch:$%02X - IE0:%d - IE1:%d - DIS:%d\",\r\n            sms.VDP_Status, sms.VDP_Address, sms.VDP_Access_First,\r\n            (VBlank_ON?1:0), (HBlank_ON?1:0), (Display_ON?1:0));\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // - Scroll\r\n    {\r\n        sprintf(line, \" [SCROLL] X:$%02X - Y:$%02X - LeftColumnBlank:%d - HSI:%d - VSI:%d\",\r\n            sms.VDP[8], sms.VDP[9], (Mask_Left_8?1:0), (Top_No_Scroll?1:0), (Right_No_Scroll?1:0));\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // - Sprites\r\n    {\r\n        sprintf(line, \"[SPRITES] Size:%s - Double:%d - EarlyClock:%d - SAT:$%04X - SPG:$%04X\",\r\n            (Sprites_8x16?\"8x16\":\"8x8\"), (Sprites_Double?1:0), (Sprites_Left_8?1:0), (int)(g_machine.VDP.sprite_attribute_table - VRAM), (int)(g_machine.VDP.sprite_pattern_gen_address - VRAM));\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // - Inputs\r\n    {\r\n        sprintf(line, \" [INPUTS] PortDE:$%02X - Port3F:$%02X - Joy:$%04X - GG:$%02X - Paddle:$%02X,$%02X\",\r\n            (sms.Input_Mode), (tsms.Port3F), tsms.Control[7], (tsms.Control_GG), (Inputs.Paddle[0].x), (Inputs.Paddle[1].x));\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // - Various\r\n    {\r\n#ifdef MEKA_Z80_DEBUGGER\r\n        if (Debugger.enabled && Debugger.active)\r\n            sprintf(line, \"[VARIOUS] Country:%s - Border:%d - IPeriod:%d/%d - Lines:%d/%d\",\r\n            (sms.Country==COUNTRY_EXPORT)?\"Export\":\"Japan\", (sms.VDP[7] & 15), CPU_GetICount(), CPU_GetIPeriod(), tsms.VDP_Line, g_machine.TV_lines);\r\n        else\r\n#endif\r\n            sprintf(line, \"[VARIOUS] Country:%s - Border:%d - IPeriod:%d - Lines:%d\",\r\n            (sms.Country==COUNTRY_EXPORT)?\"Export\":\"Japan\", (sms.VDP[7] & 15), CPU_GetIPeriod(), g_machine.TV_lines);\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // - TMS9918\r\n    {\r\n        sprintf(line, \"[TMS9918] Name:$%04X - Color:$%04X - Pattern:$%04X - SPG:$%04X\",\r\n            (int)(g_machine.VDP.name_table_address - VRAM), (int)(g_machine.VDP.sg_color_table_address - VRAM), (int)(g_machine.VDP.sg_pattern_gen_address - VRAM), (int)(g_machine.VDP.sprite_pattern_gen_address - VRAM));\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // - PSG\r\n    {\r\n        t_psg *psg = &PSG;\r\n        sprintf(line, \"    [PSG] Tone 0: %03X,%01X  Tone 1: %03X,%01X  Tone 2: %03X,%01X  Noise:%02X,%01X (%s)  Stereo:%02X\",\r\n            psg->Registers[0], psg->Registers[1], psg->Registers[2], psg->Registers[3],\r\n            psg->Registers[4], psg->Registers[5], psg->Registers[6], psg->Registers[7],\r\n            ((psg->Registers[6] & 0x04) ? \"White\" : \"Periodic\"),\r\n            psg->Stereo);\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    {\r\n        if (FM_Regs != NULL)\r\n        {\r\n            sprintf(line, \" [YM2413] Custom inst: %02X/%02X/%02X/%02X/%02X/%02X/%02X/%02X  Rhythm: %02X\",\r\n                FM_Regs[0], FM_Regs[1], FM_Regs[2], FM_Regs[3], FM_Regs[4], FM_Regs[5], FM_Regs[6], FM_Regs[7],\r\n                FM_Regs[0xe]);\r\n            TechInfo_SetLine(app, line, line_idx++);\r\n            char* p = line;\r\n            p += sprintf(p, \" [YM2413]\");\r\n            for (int i = 0; i < 9; ++i)\r\n            {\r\n                p += sprintf(p, \" Tone %d: %01X,%03X,%c,%c,%01X,%01X\",\r\n                    i,\r\n                    (FM_Regs[i + 0x20] & 0x6) >> 1, // Block\r\n                    FM_Regs[i + 0x10] | ((FM_Regs[i + 0x20] & 1) << 8), // F-num\r\n                    (FM_Regs[i + 0x20] & 0x20) != 0 ? 'S' : '-', // Sustain\r\n                    (FM_Regs[i + 0x20] & 0x10) != 0 ? 'K' : '-', // Key\r\n                    FM_Regs[i + 0x30] & 0x0f, // Volume\r\n                    FM_Regs[i + 0x30] >> 4 // Instrument\r\n                    );\r\n                if (i % 3 == 2)\r\n                {\r\n                    TechInfo_SetLine(app, line, line_idx++);\r\n                    p = line;\r\n                    p += sprintf(p, \" [YM2413]\");\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    // - Memory\r\n    {\r\n        char mapper_regs[256];\r\n        mapper_regs[0] = '\\0';\r\n        for (int i = 0; i != g_machine.mapper_regs_count; i++)\r\n        {\r\n            char s[16];\r\n            if (i == 0)\r\n                sprintf(s, \"$%02X\", g_machine.mapper_regs[i]);\r\n            else\r\n                sprintf(s, \",$%02X\", g_machine.mapper_regs[i]);\r\n            strcat(mapper_regs, s);\r\n        }\r\n\r\n        sprintf(line, \" [MAPPER] Type:%d - Ctrl:$%02X - Regs:%s - Pages:[%d/%d][%d/%d]\",\r\n            g_machine.mapper, sms.SRAM_Mapping_Register, mapper_regs, tsms.Pages_Count_8k, tsms.Pages_Mask_8k, tsms.Pages_Count_16k, tsms.Pages_Mask_16k);\r\n        TechInfo_SetLine(app, line, line_idx++);\r\n    }\r\n\r\n    // Blank left lines\r\n    while (line_idx < TECHINFO_LINES)\r\n        TechInfo_SetLine(app, \"\", line_idx++);\r\n\r\n    // Redraw\r\n    TechInfo_Redraw(app);\r\n}\r\n\r\nvoid    TechInfo_Switch (void)\r\n{\r\n    if (TechInfo.active ^= 1)\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_TechInfo_Enabled));\r\n    else\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_TechInfo_Disabled));\r\n    gui_box_show(TechInfo.box, TechInfo.active, TRUE);\r\n    gui_menu_toggle_check(menus_ID.tools, 6);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/app_techinfo.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - techinfo.h\n// Technical Information Applet - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define TECHINFO_LINES          (14)\n#define TECHINFO_COLUMNS        (90)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_app_tech_info\n{\n    bool        active;\n    t_gui_box * box;\n    char        lines[TECHINFO_LINES][512 /* TECHINFO_COLUMNS */];\n    bool        lines_dirty[TECHINFO_LINES];\n\n};\n\nextern t_app_tech_info TechInfo;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TechInfo_Init(void);\nvoid    TechInfo_Update(void);\nvoid    TechInfo_Switch(void);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/app_textview.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - textview.c\n// Text Viewer Applet - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"app_textview.h\"\n#include \"desktop.h\"\n#include \"g_widget.h\"\n#include \"inputs_t.h\"\n#include \"libparse.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_app_textviewer   TextViewer;\n\n//-----------------------------------------------------------------------------\n// Forward Declaration\n//-----------------------------------------------------------------------------\n\nstatic void     TextViewer_Layout(t_app_textviewer* app, bool setup);\nstatic void     TextViewer_ScrollbarCallback();\nstatic void     TextViewer_Update_Inputs(t_app_textviewer* app);\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TextViewer_Init(t_app_textviewer* app)\n{\n    assert(app == &TextViewer); // WIP multiple instances not supported\n\n    // Setup members\n    app->active      = FALSE;\n    app->dirty       = TRUE;\n    app->current_file= -1;\n    app->font        = (t_font_id)g_config.font_documentation;\n    app->font_height = Font_Height(app->font);\n\n    // Create box\n    t_frame frame;\n    frame.pos.x     = 290;\n    frame.pos.y     = 65;\n    frame.size.x    = 550;\n    frame.size.y    = 620;\n    app->box = gui_box_new(&frame, \"Text Viewer\");\n    app->box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;\n\n    // Register to desktop\n    Desktop_Register_Box(\"DOCUMENTATION\", app->box, FALSE, &app->active);\n\n    // Layout\n    TextViewer_Layout(app, true);\n\n    // Setup other members\n    app->text_lines              = NULL;\n    app->text_lines_count        = 0;\n    app->text_size_y             = 0;\n    app->scroll_position_y       = 0;\n    app->scroll_position_y_max   = 0;\n    app->scroll_velocity_y       = 0;\n}\n\nvoid    TextViewer_Close(t_app_textviewer* app)\n{\n    gui_box_delete(app->box);\n    app->box = NULL;\n    for (int i = 0; i != app->text_lines_count; i++)\n        free(app->text_lines[i]);\n    free(app->text_lines);\n    app->text_lines = NULL;\n    app->text_lines_count = 0;\n}\n\nvoid    TextViewer_Layout(t_app_textviewer* app, bool setup)\n{\n    app->text_frame.pos.x        = TEXTVIEWER_PADDING;\n    app->text_frame.pos.y        = TEXTVIEWER_PADDING;\n    app->text_frame.size.x       = app->box->frame.size.x - (2 * TEXTVIEWER_PADDING) - TEXTVIEWER_SCROLLBAR_SIZE_X;\n    app->text_frame.size.y       = app->box->frame.size.y - (2 * TEXTVIEWER_PADDING);\n    app->text_size_per_page      = app->box->frame.size.y;\n\n    t_frame frame;\n\n    al_set_target_bitmap(app->box->gfx_buffer);\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\n\n    // Add closebox widget\n    if (setup)\n        widget_closebox_add(app->box, (t_widget_callback)TextViewer_Switch_Close);\n\n    // Add scrollbar\n    frame.pos.x = app->box->frame.size.x - TEXTVIEWER_SCROLLBAR_SIZE_X;\n    frame.pos.y = 0;\n    frame.size.x = TEXTVIEWER_SCROLLBAR_SIZE_X;\n    frame.size.y = app->box->frame.size.y - 16;\n    if (setup)\n    {\n        app->widget_scrollbar = widget_scrollbar_add(app->box, WIDGET_SCROLLBAR_TYPE_VERTICAL, &frame, &app->text_size_y, &app->scroll_position_y, app->text_size_per_page, (t_widget_callback)TextViewer_ScrollbarCallback);\n    }\n    else\n    {\n        app->widget_scrollbar->frame = frame;\n        widget_scrollbar_set_page_step(app->widget_scrollbar, app->text_size_per_page);\n    }\n}\n\nint     TextViewer_Open(t_app_textviewer* app, const char* title, const char* filename)\n{\n    // Open and read file\n    t_tfile *   tf;\n    if ((tf = tfile_read(filename)) == NULL)\n        return (MEKA_ERR_FILE_OPEN);\n\n    // Free existing lines\n    if (app->text_lines != NULL)\n    {\n        for (int i = 0; i != app->text_lines_count; i++)\n            free(app->text_lines[i]);\n        free(app->text_lines);\n        app->text_lines = NULL;\n        app->text_lines_count = 0;\n    }\n\n    // Allocate and copy new lines\n    app->text_lines = (char**)malloc(sizeof(char *) * tf->data_lines_count);\n    app->text_lines_count = tf->data_lines_count;\n    int i = 0;\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\n    {\n        const char *line = (const char *)lines->elem;\n        app->text_lines[i] = strdup(line);\n        i++;\n    }\n\n    // Free text file data\n    tfile_free(tf);\n\n    // Update members\n    app->dirty                   = TRUE;\n    app->text_size_y             = app->text_lines_count * app->font_height;\n    app->scroll_position_y       = 0;\n    app->scroll_position_y_max   = app->text_size_y - app->text_size_per_page;\n\n    // Set new title\n    gui_box_set_title(app->box, title);\n\n    return (MEKA_ERR_OK);\n}\n\n#define DOC_MAIN        (0)\n#define DOC_COMPAT      (1)\n#define DOC_MULTI       (2)\n#define DOC_CHANGES     (3)\n#define DOC_DEBUGGER    (4)\n#define DOC_MAX         (5)\n\nvoid            TextViewer_Switch_Doc_Main()\n{\n    TextViewer_Switch(&TextViewer, Msg_Get(MSG_Doc_BoxTitle), g_env.Paths.DocumentationMain, DOC_MAIN);\n}\n\nvoid            TextViewer_Switch_Doc_Compat()\n{\n    TextViewer_Switch(&TextViewer, Msg_Get(MSG_Doc_BoxTitle), g_env.Paths.DocumentationCompat, DOC_COMPAT);\n}\n\nvoid            TextViewer_Switch_Doc_Multiplayer_Games()\n{\n    TextViewer_Switch(&TextViewer, Msg_Get(MSG_Doc_BoxTitle), g_env.Paths.DocumentationMulti, DOC_MULTI);\n}\n\nvoid            TextViewer_Switch_Doc_Changes()\n{\n    TextViewer_Switch(&TextViewer, Msg_Get(MSG_Doc_BoxTitle), g_env.Paths.DocumentationChanges, DOC_CHANGES);\n}\n\nvoid            TextViewer_Switch_Doc_Debugger()\n{\n    TextViewer_Switch(&TextViewer, Msg_Get(MSG_Doc_BoxTitle), g_env.Paths.DocumentationDebugger, DOC_DEBUGGER);\n}\n\nvoid    TextViewer_Switch(t_app_textviewer* tv, const char* title, const char* filename, int current_file)\n{\n    if (tv->current_file != current_file)\n    {\n        if (TextViewer_Open(tv, title, filename) != MEKA_ERR_OK)\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Doc_File_Error));\n        tv->active = TRUE;\n        tv->current_file = current_file;\n    }\n    else\n    {\n        if (tv->active ^= 1)\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Doc_Enabled));\n        else\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Doc_Disabled));\n    }\n\n    gui_box_show(tv->box, tv->active, TRUE);\n    gui_menu_uncheck_range(menus_ID.help, 0, DOC_MAX - 1);\n    if (tv->active)\n        gui_menu_check(menus_ID.help, current_file);\n}\n\nvoid    TextViewer_Switch_Close()\n{\n    t_app_textviewer *tv = &TextViewer; // Global instance\n    tv->active = FALSE;\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Doc_Disabled));\n    gui_box_show(tv->box, tv->active, TRUE);\n    gui_menu_uncheck_range(menus_ID.help, 0, DOC_MAX - 1);\n}\n\nstatic void     TextViewer_ScrollbarCallback()\n{\n    t_app_textviewer *tv = &TextViewer; // Global instance\n    tv->dirty = TRUE;\n}\n\nvoid    TextViewer_Update(t_app_textviewer *tv)\n{\n    // Skip update if not active\n    if (!tv->active)\n        return;\n\n    // If skin has changed, redraw everything\n    if (tv->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\n    {\n        TextViewer_Layout(tv, FALSE);\n        tv->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\n        tv->dirty = TRUE;\n    }\n\n    // Update inputs\n    TextViewer_Update_Inputs(tv);\n\n    // Update velocity\n    tv->scroll_velocity_y = Clamp(tv->scroll_velocity_y, -TEXTVIEWER_SCROLL_VELOCITY_MAX, +TEXTVIEWER_SCROLL_VELOCITY_MAX);\n    if (fabsf(tv->scroll_velocity_y) > 0.01f)\n    {\n        tv->dirty = TRUE;\n        tv->scroll_position_y += tv->scroll_velocity_y;\n\n        // Clamp position & bounce\n        if (tv->scroll_position_y < 0)\n        {\n            tv->scroll_position_y = 0;\n            tv->scroll_velocity_y = -(tv->scroll_velocity_y / 1.5f);\n        }\n        if (tv->scroll_position_y > tv->scroll_position_y_max)\n        {\n            tv->scroll_position_y = tv->scroll_position_y_max;\n            tv->scroll_velocity_y = -(tv->scroll_velocity_y / 1.5f);\n        }\n\n        // Fade off velocity\n        tv->scroll_velocity_y *= 0.93f;\n    }\n\n    // Skip redraw if not dirty\n    if (!tv->dirty)\n        return;\n\n    // Redraw\n    tv->dirty = FALSE;\n    {\n        // Uses Allegro clipping functionality as a helper\n        al_set_target_bitmap(tv->box->gfx_buffer);\n        //al_set_clipping_rectangle(tv->text_frame.pos.x, tv->text_frame.pos.y, tv->text_frame.pos.x + tv->text_frame.size.x, tv->text_frame.pos.y + tv->text_frame.size.y);\n\n        // Clear all since Allegro 5 doesn't seem to do clipping on font\n        al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\n\n        // Draw separator between text and scrollbar\n        t_frame frame = tv->widget_scrollbar->frame;\n        al_draw_line(frame.pos.x, frame.pos.y, frame.pos.x, frame.pos.y + frame.size.y + 1, COLOR_SKIN_WINDOW_SEPARATORS, 0);\n        /*al_draw_filled_rectangle(\n            tv->text_frame.pos.x, tv->text_frame.pos.y, tv->text_frame.pos.x + tv->text_frame.size.x + 1, tv->text_frame.pos.y + tv->text_frame.size.y + 1,\n            COLOR_SKIN_WINDOW_BACKGROUND);*/\n\n        // Draw lines\n        const int line_y = tv->scroll_position_y / tv->font_height;\n        int y = tv->text_frame.pos.y - (tv->scroll_position_y % tv->font_height);\n        for (int i = line_y; i < tv->text_lines_count; i++)\n        {\n            Font_Print(tv->font, tv->text_lines[i], tv->text_frame.pos.x, y, COLOR_SKIN_WINDOW_TEXT);\n            y += tv->font_height;\n            if (y > tv->text_frame.pos.y + tv->text_frame.size.y)\n                break;\n        }\n\n        // Disable clipping\n        //al_set_clipping_rectangle(0, 0, al_get_bitmap_width(tv->box->gfx_buffer), al_get_bitmap_height(tv->box->gfx_buffer));\n    }\n}\n\nstatic void     TextViewer_Update_Inputs(t_app_textviewer *tv)\n{\n    // Check for focus\n    if (!gui_box_has_focus(tv->box)) //  && tv->vel_y == 0)\n        return;\n\n    // Update mouse wheel inputs\n    if (gui.mouse.wheel_rel != 0)\n    {\n        if (gui.mouse.wheel_rel > 0)\n            tv->scroll_velocity_y -= TEXTVIEWER_SCROLL_VELOCITY_BASE * 4.0f;\n        if (gui.mouse.wheel_rel < 0)\n            tv->scroll_velocity_y += TEXTVIEWER_SCROLL_VELOCITY_BASE * 4.0f;\n        tv->dirty = TRUE;\n    }\n\n    // Update keyboard inputs\n    if (Inputs_KeyPressed (ALLEGRO_KEY_HOME, FALSE))\n    {\n        tv->scroll_position_y = 0;\n        tv->scroll_velocity_y = 0;\n        tv->dirty = TRUE;\n    }\n    else if (Inputs_KeyPressed (ALLEGRO_KEY_END, FALSE))\n    {\n        tv->scroll_position_y = tv->scroll_position_y_max;\n        tv->scroll_velocity_y = 0;\n        tv->dirty = TRUE;\n    }\n    else if (Inputs_KeyPressed_Repeat (ALLEGRO_KEY_PGDN, FALSE, 25, 12))\n    {\n        tv->scroll_velocity_y += TEXTVIEWER_SCROLL_VELOCITY_BASE * 10.0f;\n        tv->dirty = TRUE;\n    }\n    else if (Inputs_KeyPressed_Repeat (ALLEGRO_KEY_PGUP, FALSE, 25, 12))\n    {\n        tv->scroll_velocity_y -= TEXTVIEWER_SCROLL_VELOCITY_BASE * 10.0f;\n        tv->dirty = TRUE;\n    }\n    else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_DOWN, FALSE, 2, 1))\n    {\n        tv->scroll_velocity_y += TEXTVIEWER_SCROLL_VELOCITY_BASE;\n        tv->dirty = TRUE;\n    }\n    else if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_UP, FALSE, 2, 1))\n    {\n        tv->scroll_velocity_y -= TEXTVIEWER_SCROLL_VELOCITY_BASE;\n        tv->dirty = TRUE;\n    }\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/app_textview.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - textview.h\n// Text Viewer Applet - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define TEXTVIEWER_PADDING              (4)\n#define TEXTVIEWER_SCROLLBAR_SIZE_X     (7)\n#define TEXTVIEWER_SCROLL_VELOCITY_BASE (2.5f)\n#define TEXTVIEWER_SCROLL_VELOCITY_MAX  (20.0f)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_app_textviewer\n{\n    bool        active;\n    bool        dirty;\n    int         current_file;           // FIXME: REMOVE OUT OF APPLET\n\n    t_gui_box * box;\n    t_font_id   font;\n    int         font_height;\n\n    char **     text_lines;\n    int         text_lines_count;\n    t_frame     text_frame;\n    int         text_size_y;            // == text_lines_count * font_height\n    int         text_size_per_page;     // == size_y * font_height\n\n    int         scroll_position_y;\n    int         scroll_position_y_max;  // text_size_y - (text_lines_per_page * font_height)\n    float       scroll_velocity_y;\n\n    t_widget *  widget_scrollbar;\n\n};\n\nextern t_app_textviewer   TextViewer;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid                TextViewer_Init(t_app_textviewer* app);\nvoid                TextViewer_Close(t_app_textviewer* app);\nint                 TextViewer_Open(t_app_textviewer* app, const char *title, const char *filename);\nvoid                TextViewer_Update(t_app_textviewer* app);\nvoid                TextViewer_Switch(t_app_textviewer* app, const char *title, const char *filename, int current_file);\n\nvoid                TextViewer_Switch_Doc_Main();\nvoid                TextViewer_Switch_Doc_Compat();\nvoid                TextViewer_Switch_Doc_Multiplayer_Games();\nvoid                TextViewer_Switch_Doc_Changes();\n#ifdef MEKA_Z80_DEBUGGER\nvoid                TextViewer_Switch_Doc_Debugger();\n#endif\nvoid                TextViewer_Switch_Close();\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/app_tileview.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - tileview.c\r\n// Tile Viewer - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_tileview.h\"\r\n#include \"desktop.h\"\r\n#include \"g_tools.h\"\r\n#include \"g_widget.h\"\r\n#include \"palette.h\"\r\n#include \"video_c.h\"\r\n#include \"video_m2.h\"\r\n#include \"video_m5.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_app_tile_viewer   TileViewer;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    TileViewer_Layout(t_app_tile_viewer *app, bool setup);\r\n\r\nvoid    TileViewer_Change_Palette();\r\nvoid    TileViewer_SelectedTile_Select(t_widget *w);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    TileViewer_Init_Values()\r\n{\r\n    TileViewer.active               = FALSE;\r\n    TileViewer.dirty                = TRUE;\r\n    TileViewer.palette              = 0;\r\n    TileViewer.palette_max          = 2;\r\n    TileViewer.tile_displayed       = -1;\r\n    TileViewer.tile_hovered         = -1;\r\n    TileViewer.tile_selected        = -1;\r\n    TileViewer.tiles_per_page       = 512;\r\n    TileViewer.tiles_width          = -1;\r\n    TileViewer.tiles_height         = -1;\r\n    TileViewer.tiles_display_zone   = NULL;\r\n}\r\n\r\n// CREATE AND INITIALIZE TILE VIEWER APPLET ----------------------------------\r\nvoid    TileViewer_Init()\r\n{\r\n    t_app_tile_viewer *app = &TileViewer; // Global instance\r\n\r\n    // Setup members\r\n    app->tiles_width  = 16;\r\n    app->tiles_height = app->tiles_per_page / app->tiles_width;\r\n    app->tiles_display_frame.SetPos(0, 13);\r\n    app->tiles_display_frame.SetSize(app->tiles_width * 8, app->tiles_height * 8);\r\n\r\n\tapp->tile_selected_frame.SetPos(2, app->tiles_display_frame.GetMax().y+1);\r\n\tapp->tile_selected_frame.SetSize(8,8);\r\n\r\n\tapp->vram_addr_tms9918_current = 0;\r\n\r\n    // Create box\r\n    t_frame frame;\r\n    frame.pos.x     = 16;\r\n    frame.pos.y     = 65;\r\n    frame.size.x    = app->tiles_display_frame.size.x - 1;\r\n    frame.size.y    = app->tiles_display_frame.size.y + 13 + 13 - 1;\r\n    app->box = gui_box_new(&frame, Msg_Get(MSG_TilesViewer_BoxTitle));\r\n    Desktop_Register_Box (\"TILES\", app->box, true, &app->active);\r\n\r\n    // Layout\r\n    TileViewer_Layout(&TileViewer, TRUE);\r\n}\r\n\r\nvoid    TileViewer_Layout(t_app_tile_viewer *app, bool setup)\r\n{\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (setup)\r\n    {\r\n        // Add closebox widget\r\n        widget_closebox_add(app->box, (t_widget_callback)TileViewer_Switch);\r\n\r\n        // Create invisible buttons for hovering/selecting palette\r\n        app->tiles_display_zone = widget_button_add(app->box, &app->tiles_display_frame, 1, TileViewer_SelectedTile_Select, FONTID_NONE, NULL);\r\n        widget_button_add(app->box, &app->tiles_display_frame, 2, (t_widget_callback)TileViewer_Change_Palette, FONTID_NONE, NULL);\r\n    }\r\n\r\n\tif (setup)\r\n\t{\r\n\t\tt_frame frame;\r\n\t\tframe.SetPos(100, 2);\r\n\t\tframe.SetSize(4*6, 7);\r\n\t\tstatic const int step_count = 4;\r\n\t\tapp->vram_addr_tms9918_scrollbar = widget_scrollbar_add(app->box, WIDGET_SCROLLBAR_TYPE_HORIZONTAL, &frame, &step_count, &app->vram_addr_tms9918_current, 1, NULL);\r\n\t}\r\n\r\n    // Separators\r\n    al_draw_line(0, app->tiles_display_frame.pos.y-1+0.5f, app->tiles_display_frame.size.x, app->tiles_display_frame.pos.y-1+0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n    al_draw_line(0, 13+app->tiles_display_frame.size.y+0.5f, app->tiles_display_frame.size.x, 13+app->tiles_display_frame.size.y+0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n\r\n\t// Rectangle enclosing current/selected tile\r\n\tconst t_frame* fr = &app->tile_selected_frame;\r\n    gui_rect(LOOK_THIN, fr->pos.x, fr->pos.y, fr->pos.x + 11, fr->pos.y + 11, COLOR_SKIN_WIDGET_GENERIC_BORDER);\r\n}\r\n\r\nvoid    TileViewer_Update(t_app_tile_viewer *app)\r\n{\r\n    ALLEGRO_BITMAP *bmp = app->box->gfx_buffer;\r\n\r\n    // Skip update if not active\r\n    if (!app->active)\r\n        return;\r\n\r\n    // If skin has changed, redraw everything\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        TileViewer_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n        app->dirty = TRUE;\r\n    }\r\n\r\n    bool dirty_all = app->dirty || Palette_EmulationDirtyAny;\r\n    bool dirty = dirty_all;\r\n\r\n    // Update hovered tile index\r\n    {\r\n        const int mx = app->tiles_display_zone->mouse_x;\r\n        const int my = app->tiles_display_zone->mouse_y;\r\n        // Msg(MSGT_USER, \"mx = %d, my = %d\", mx, my);\r\n        if (app->tiles_display_zone->mouse_action & WIDGET_MOUSE_ACTION_HOVER)\r\n            app->tile_hovered = ((my / 8) * 16) + mx / 8;\r\n        else\r\n            app->tile_hovered = -1;\r\n    }\r\n\r\n    // Compute the tile that is to display in the bottom info line\r\n    int tile_current = (app->tile_hovered != -1) ? app->tile_hovered : app->tile_selected;\r\n    bool tile_current_refresh = /*(tile_current == -1) ? FALSE : */ (((tile_current != app->tile_displayed) || dirty_all || tgfx.Tile_Dirty [tile_current]));\r\n    int tile_current_addr = -1;\r\n\t\r\n\tconst v2i tiles_frame_pos = app->tiles_display_frame.pos;\r\n\tconst v2i tile_selected_pos = v2i(app->tile_selected_frame.pos.x + 2, app->tile_selected_frame.pos.y + 2);\r\n\r\n\tint vram_addr_min = 0x0000;\r\n\tint vram_addr_size = 0;\r\n\tint vram_tile_size = 1;\r\n\r\n    // Then redraw all tiles\r\n\tALLEGRO_LOCKED_REGION* locked_region = al_lock_bitmap(app->box->gfx_buffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);\r\n    switch (g_driver->vdp)\r\n    {\r\n    case VDP_SMSGG:\r\n        {\r\n\t\t\twidget_set_enabled(app->vram_addr_tms9918_scrollbar, false);\r\n\t\t\tvram_addr_min = 0;\r\n\t\t\tvram_addr_size = 0x4000;\r\n\t\t\tvram_tile_size = 32;\r\n\r\n            int n = 0;\r\n            const u8 *    nd = &tgfx.Tile_Decoded[0][0];\r\n            const u32 *   palette_host = app->palette ? &Palette_EmulationToHostGui[16] : &Palette_EmulationToHostGui[0];\r\n            for (int y = 0; y != app->tiles_height; y++)\r\n\t\t\t{\r\n                for (int x = 0; x != app->tiles_width; x++)\r\n                {\r\n                    if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\r\n                        Decode_Tile (n);\r\n                    if (dirty_all || tgfx.Tile_Dirty [n])\r\n                    {\r\n                        VDP_Mode4_DrawTile(app->box->gfx_buffer, locked_region, nd, palette_host, tiles_frame_pos.x+(x * 8), tiles_frame_pos.y+(y * 8), 0);\r\n                        tgfx.Tile_Dirty [n] = 0;\r\n                        dirty = TRUE;\r\n                    }\r\n                    if (n == tile_current)\r\n\t\t\t\t\t{\r\n                        tile_current_addr = vram_addr_min + (n * 32);\r\n\t\t\t\t\t\tVDP_Mode4_DrawTile(app->box->gfx_buffer, locked_region, nd, palette_host, tile_selected_pos.x, tile_selected_pos.y, 0);\r\n\t\t\t\t\t}\r\n                    n ++;\r\n                    nd += 64;\r\n                }\r\n\t\t\t}\r\n            break;\r\n        }\r\n    case VDP_TMS9918:\r\n        {\r\n\t\t\twidget_set_enabled(app->vram_addr_tms9918_scrollbar, true);\r\n\t\t\tvram_addr_min = 0x0000 + app->vram_addr_tms9918_current*0x1000;\r\n\t\t\tvram_addr_size = 0x1000;\r\n\t\t\tvram_tile_size = 8;\r\n\r\n\t\t\tconst int fg_color = Palette_EmulationToHostGui[app->palette + 1];\r\n            const int bg_color = Palette_EmulationToHostGui[(app->palette != 0) ? 1 : 15];\r\n            const u8 * addr = VRAM + vram_addr_min;\r\n\t\t\t//VRAM = g_machine.VDP.sg_pattern_gen_address;\r\n            // addr = &VRAM[apps.opt.Tiles_Base];\r\n           \r\n            int n = 0;\r\n            for (int y = 0; y != app->tiles_height; y ++)\r\n\t\t\t{\r\n                for (int x = 0; x != app->tiles_width; x ++)\r\n                {\r\n                    if ((addr - VRAM) > 0x4000)\r\n                        break;\r\n                    VDP_Mode0123_DrawTile(bmp, locked_region, tiles_frame_pos.x+(x * 8), tiles_frame_pos.y+(y * 8), addr, fg_color, bg_color);\r\n                    if (n == tile_current)\r\n\t\t\t\t\t{\r\n                        tile_current_addr = vram_addr_min + (n * 8);\r\n\t\t\t\t\t\tVDP_Mode0123_DrawTile(bmp, locked_region, tile_selected_pos.x, tile_selected_pos.y, addr, fg_color, bg_color);\r\n\t\t\t\t\t}\r\n\r\n                    n++;\r\n                    addr += 8;\r\n                }\r\n\t\t\t}\r\n            dirty = TRUE; // to be replaced later\r\n            break;\r\n        }\r\n    }\r\n\tal_unlock_bitmap(app->box->gfx_buffer);\r\n\r\n\t// Refresh top status line (address range)\r\n\tal_set_target_bitmap(bmp);\r\n\t{\r\n\t\t// FIXME-OPT\r\n\t\tconst int y = -1;\r\n\t\tal_draw_filled_rectangle(0, y + 1, app->vram_addr_tms9918_scrollbar->enabled ? app->vram_addr_tms9918_scrollbar->frame.pos.x-1 : 128-1, y + 11+1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n\t\tchar buf[64];\r\n\t\tsprintf(buf, \"Range: $%04X-$%04X\", vram_addr_min, vram_addr_min+vram_addr_size-1);\r\n\t\tFont_Print(FONTID_SMALL, buf, 0, y + 1, COLOR_SKIN_WINDOW_TEXT);\r\n\t\tdirty = true;\r\n\t}\r\n\r\n    // Refresh bottom status line (selected tile)\r\n    if (dirty_all || tile_current_refresh)\r\n    {\r\n\t\tconst int y = app->tiles_display_frame.GetMax().y;\r\n\r\n        al_draw_filled_rectangle(16, y + 1, 127+1, y + 11+1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n        dirty = TRUE;\r\n\r\n        if (tile_current != -1)\r\n        {\r\n            // Description\r\n            char addr[16];\r\n            if (tile_current_addr != -1)\r\n                sprintf(addr, \"$%04X\", tile_current_addr);\r\n            else\r\n                sprintf(addr, \"????\");\r\n\r\n\t\t\tchar buf[128];\r\n\t\t\tconst int tile_index = tile_current_addr / vram_tile_size;\r\n            sprintf(buf, Msg_Get(MSG_TilesViewer_Tile), tile_index, tile_index, addr);\r\n            Font_Print(FONTID_SMALL, buf, 16, y + 1, COLOR_SKIN_WINDOW_TEXT);\r\n            app->tile_displayed = tile_current;\r\n        }\r\n        else\r\n        {\r\n            // Fill tile with black\r\n\t\t\tconst t_frame* fr = &app->tile_selected_frame;\r\n            al_draw_filled_rectangle(fr->pos.x+2, fr->pos.y+2, fr->pos.x+2+8, fr->pos.y+2+8, COLOR_BLACK);\r\n        }\r\n    }\r\n\r\n    if (dirty_all || dirty)\r\n        app->dirty = FALSE;\r\n}\r\n\r\nvoid    TileViewer_Change_Palette()\r\n{\r\n    //int   i;\r\n    TileViewer.palette = (TileViewer.palette + 1) % TileViewer.palette_max;\r\n    //for (i = 0; i < MAX_TILES; i++)\r\n    //    tgfx.Tile_Dirty [i] |= TILE_DIRTY_REDRAW;\r\n    TileViewer.dirty = TRUE;\r\n}\r\n\r\nvoid        TileViewer_Configure_PaletteMax (int palette_max)\r\n{\r\n    if (palette_max == TileViewer.palette_max)\r\n        return;\r\n    TileViewer.palette_max = palette_max;\r\n    if (TileViewer.palette >= palette_max)\r\n        TileViewer.palette %= palette_max;\r\n    TileViewer.dirty = TRUE;\r\n}\r\n\r\nvoid    TileViewer_SelectedTile_Select(t_widget *w)\r\n{\r\n    if (w->mouse_action & WIDGET_MOUSE_ACTION_HOVER)\r\n        TileViewer.tile_selected = ((w->mouse_y / 8) * 16) + (w->mouse_x / 8);\r\n}\r\n\r\nvoid    TileViewer_Switch()\r\n{\r\n    if (TileViewer.active ^= 1)\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_TilesViewer_Enabled));\r\n    else\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_TilesViewer_Disabled));\r\n    gui_box_show (TileViewer.box, TileViewer.active, TRUE);\r\n    gui_menu_toggle_check (menus_ID.tools, 2);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/app_tileview.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - tileview.h\r\n// Tile Viewer - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_app_tile_viewer\r\n{\r\n    bool        active;\r\n    bool        dirty;\r\n    t_gui_box * box;\r\n    int         palette;        // 0 to palette_max-1\r\n    int         palette_max;    // 1+\r\n    int         tile_displayed; // -1 if none, else 0 to tiles_max-1\r\n    int         tile_hovered;   // -1 if none, else 0 to tiles_max-1\r\n    int         tile_selected;  // -1 if none, else 0 to tiles_max-1\r\n    int         tiles_per_page;\r\n    int         tiles_width;\r\n    int         tiles_height;\r\n    t_frame     tiles_display_frame;\r\n\tt_frame\t\ttile_selected_frame;\r\n    t_widget *  tiles_display_zone;\r\n\r\n\tt_widget *\tvram_addr_tms9918_scrollbar;\r\n\tint\t\t\tvram_addr_tms9918_current;\r\n};\r\n\r\nextern t_app_tile_viewer   TileViewer;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    TileViewer_Init_Values();\r\nvoid    TileViewer_Init();\r\n\r\nvoid    TileViewer_Update(t_app_tile_viewer* app);\r\n\r\nvoid    TileViewer_Switch();\r\nvoid    TileViewer_Configure_PaletteMax(int palette_max);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/areplay.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - areplay.c\n// Action Replay Emulation - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n\n//-----------------------------------------------------------------------------\n\n// ...\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/areplay.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - areplay.h\n// Action Replay Emulation - Headers\n//-----------------------------------------------------------------------------\n\n// ...\n\n//-----------------------------------------------------------------------------\n\n\n\n"
  },
  {
    "path": "meka/srcs/beam.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - beam.c\r\n// VDP Refresh Beam Position - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"beam.h\"\r\n#include \"lightgun.h\"\r\n#include \"tvtype.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Horizontal Beam Counter (X)\r\n// Two dots are equivalent to one count, and three counts are equivalent\r\n// to four CPU clock pulses (1H = 342 dots = 171 counts = 228 CPU clock pulses)\r\n\r\n// F4h ---- FFh | 00h --------- 20h --LCD-- 6FH -------- 93H | E9H ---- F3H\r\n//  <-- 12 --->   <------------------ 148 ----------------->   <--- 11 --->\r\n\r\nint         Beam_Calc_X()\r\n{\r\n    int     c;\r\n\r\n    c = ((CPU_GetIPeriod() - CPU_GetICount()) * 256) / CPU_GetIPeriod();\r\n    return (c);\r\n\r\n  /*c = ((sms.R.IPeriod - sms.R.ICount) * 0x80) / sms.R.IPeriod;\r\n  return (0x08 + c);*/\r\n\r\n  /*c = (sms.R.IPeriod - sms.R.ICount) * 0.75;\r\n  c %= 171;\r\n  if (c < 12)\r\n     return (c + 244);\r\n  if (c < 12 + 148)\r\n     return (c - 12);\r\n  return (c + 72);*/\r\n}\r\n\r\nint         Beam_X()\r\n{\r\n    return (LightPhaser_GetX ()); // FIXME: ...\r\n    // return (Beam_Calc_X () / 2);\r\n}\r\n\r\n// Vertical Beam Counter (Y)\r\n// One line is equivalent to one count\r\n\r\n// NTSC\r\n// 1 frame = 262 lines\r\n// D8H ---- FFH | 00H ----- 18H --LCD-- A7H ----- DAH | D5H -- D7H\r\n// At the end of the effective screen, counter jump from DAH to D5H\r\n\r\n// PAL/SECAM\r\n// 1 frame = 313 lines\r\n// 00h -- F2h | BAh -- FFh (unconfirmed)\r\n\r\nINLINE int  Beam_Calc_Y()\r\n{\r\n    int c = tsms.VDP_Line;\r\n    if (CPU_GetICount() < 8)\r\n        c = (c + 1) % g_machine.TV_lines;\r\n\r\n    // Msg(MSGT_USER, \"At PC=%04X, Read Beam Y%s\", sms.R.PC.W, (CPU_GetICount() < 8) ? \" (Affected)\" : \"\");\r\n    // Msg(MSGT_USER, \"At PC=%04X, Read Beam Y, returning %d\", sms.R.PC.W, (c < 256) ? c : 255);\r\n\r\n    // return ((c < 255) ? c : 255);\r\n\r\n    switch (g_machine.TV->id)\r\n    {\r\n    case TVTYPE_NTSC:\r\n        {\r\n            if (c <= 0xDA)\r\n                return (c);\r\n            //if (c - 6 == 0xE0 || c - 6 == 0xDF)\r\n            //{\r\n            //    Msg(MSGT_USER, \"PC = %04X\", CPU_GetPC);\r\n            //}\r\n            return (c - 6);\r\n        }\r\n    case TVTYPE_PAL_SECAM:\r\n        {\r\n            if (c <= 0xF2)\r\n                //Msg(MSGT_USER, \"%d @ Read Beam Y, returning %X\", tsms.VDP_Line, c);\r\n                return (c);\r\n            // Msg(MSGT_USER, \"%d @ Read Beam Y, returning %X\", tsms.VDP_Line, c - 57);\r\n            return (c - 57);\r\n        }\r\n    default:\r\n        {\r\n            Msg(MSGT_USER, \"BeamY Error: unknown TV Type\");\r\n            return ((c < 255) ? c : 255);\r\n        }\r\n    }\r\n}\r\n\r\nint         Beam_Y()\r\n{\r\n    return Beam_Calc_Y();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/beam.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - beam.h\n// VDP Refresh Beam Position - Headers\n//-----------------------------------------------------------------------------\n\nint     Beam_X();\nint     Beam_Y();\n\nint     Beam_Calc_X();\nint     Beam_Calc_Y();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/bios.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - bios.c\n// Interface with the Master System BIOS ROMs - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"bios.h\"\n#include \"vmachine.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nu8* BIOS_ROM;\nu8* BIOS_ROM_Jap;\nu8* BIOS_ROM_SF7000;\nu8* BIOS_ROM_Coleco;\n\n// Switch from loaded BIOS to ROM\nvoid    BIOS_Switch_to_Game()\n{\n    BIOS_Unload();\n    Machine_Reset();\n}\n\n// Unload BIOS ROM and replace with Game ROM\nvoid    BIOS_Unload()\n{\n    ROM = Game_ROM;\n    g_machine_flags |= MACHINE_NOT_IN_BIOS;\n}\n\n// Load BIOS ROM\nvoid    BIOS_Load()\n{\n    if (sms.Country == COUNTRY_JAPAN)\n    {\n        ROM = BIOS_ROM_Jap;\n    }\n    else\n    {\n        ROM = BIOS_ROM;\n    }\n    g_machine.driver_id = DRV_SMS;\n    Machine_Reset();\n}\n\n// Free memory used by BIOS ROMs\nvoid    BIOS_Free_Roms()\n{\n    // FIXME: aren't the data released by Allegro datafile routines ?!\n    // free (Bios_ROM);\n    // free (Bios_ROM_Jap);\n    // free (Bios_ROM_Coleco);\n    // free (Bios_ROM_Sf7000);\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/bios.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - bios.h\n// Interface with the Master System BIOS ROMs - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nextern u8*  BIOS_ROM;\nextern u8*  BIOS_ROM_Jap;\nextern u8*  BIOS_ROM_SF7000;\nextern u8*  BIOS_ROM_Coleco;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    BIOS_Load();\nvoid    BIOS_Unload();\nvoid    BIOS_Switch_to_Game();\nvoid    BIOS_Free_Roms();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/blit.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - blit.c\n// Blitters - Code\n//-----------------------------------------------------------------------------\n// FIXME: lots of room for optimization in the copying functions.\n// FIXME: need a full rewrite/rethinking. Now that hi-color modes are well\n// supported, this will be more straightforward than before.\n//-----------------------------------------------------------------------------\n//\n// Typical resolutions:\n//\n// SMS      256x192     512x384     768x576     1024x768\n// SMS-EXT  256x224     512x448     768x672     1024x896\n// GG       160x144     320x288     480x432     640x576     800x720     960x864\n//\n// refresh_rate     -> external to blitter, FS only\n// flip             -> external to blitter, FS only\n//\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"blit.h\"\n#include \"blitintf.h\"\n#include \"fskipper.h\"\n#include \"glasses.h\"\n#include \"hq2x.h\"\n#include \"palette.h\"\n#include \"vdp.h\"\n#include \"video.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nALLEGRO_BITMAP * Blit_Buffer_LineScratch = NULL;    // Line buffer scratch pad, 16-bits\nALLEGRO_BITMAP * Blit_Buffer_Double = NULL;         // Double-sized buffer, 16-bits\n\nstruct t_blitters_table_entry\n{\n    void    (*blit_func)();\n    int     x_fact;\n    int     y_fact;\n};\n\nstruct t_blit_cfg\n{\n    int     src_pos_x;\n    int     src_pos_y;\n    int     src_size_x;\n    int     src_size_y;\n    int     dst_scale;\n    float   tv_mode_factor;\n};\n\nt_blit_cfg  g_blit;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Blit_Init()\n{\n    g_blit.src_pos_x = 0;\n    g_blit.src_pos_y = 0;\n    g_blit.src_size_x = 0;\n    g_blit.src_size_y = 0;\n    g_blit.dst_scale = 0;\n    g_blit.tv_mode_factor = 0.700f; // FIXME-TUNING\n    Blit_CreateVideoBuffers();\n\n    // Initialize HQ2X filters\n    HQ2X_Init();\n}\n\nvoid    Blit_DestroyVideoBuffers()\n{\n    if (Blit_Buffer_LineScratch)\n    {\n        al_destroy_bitmap(Blit_Buffer_LineScratch);\n        Blit_Buffer_LineScratch = NULL;\n    }\n    if (Blit_Buffer_Double)\n    {\n        al_destroy_bitmap(Blit_Buffer_Double);\n        Blit_Buffer_Double = NULL;\n    }\n}\n\nvoid    Blit_CreateVideoBuffers()\n{\n    Blit_DestroyVideoBuffers();\n\n    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);\n    al_set_new_bitmap_format(g_config.video_game_format_request);\n    Blit_Buffer_LineScratch = al_create_bitmap(MAX_RES_X * 2, 1);\n    Blit_Buffer_Double      = al_create_bitmap((MAX_RES_X + 32) * 2, (MAX_RES_Y + 32)*2);\n}\n\nstatic const t_blitters_table_entry     Blitters_Table[BLITTER_MAX] =\n{\n    { Blit_Fullscreen_Normal,           1,      1 },\n    { Blit_Fullscreen_TV_Mode,          1,      2 },\n    { Blit_Fullscreen_TV_Mode_Double,   2,      2 },\n    { Blit_Fullscreen_HQ2X,             2,      2 },\n};\n\nstatic void Blit_Fullscreen_Misc()\n{\n    // Wait for VSync if necessary\n    // (not done if speed is higher than 70 hz)\n    // FIXME: 70 should be replaced by actual screen refresh rate ... how can we obtain it ?\n    if (g_config.video_mode_game_vsync)\n    {\n        if (!(fskipper.Mode == FRAMESKIP_MODE_THROTTLED && fskipper.Throttled_Speed > 70))\n            al_wait_for_vsync();\n    }\n\n    // Clear Screen if it has been asked\n    if (g_video.clear_requests > 0)\n    {\n        g_video.clear_requests--;\n        al_set_target_bitmap(al_get_backbuffer(g_display));\n        al_clear_to_color(BORDER_COLOR);\n    }\n\n    // Update 3-D Glasses\n    if (Glasses.Enabled)\n        Glasses_Update();\n}\n\nstatic void Blit_Fullscreen_Message(ALLEGRO_BITMAP* dst, int time_left)\n{\n    al_set_target_bitmap(dst);\n\n    int x = 10;\n    int y = al_get_bitmap_height(dst) - 16;\n    if (time_left < 20)\n        y += (20 - time_left);\n    al_draw_filled_rectangle(0, y-6, al_get_bitmap_width(dst), al_get_bitmap_height(dst), al_map_rgba(0,0,0,128));\n\n    // FIXME-OPT: use a dedicated font. This is slow as hell!!\n    Font_SetCurrent(FONTID_LARGE);\n    Font_Print(FONTID_CUR, g_gui_status.message, x - 1, y - 1, COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x,     y - 1, COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x + 1, y - 1, COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x - 1, y + 1, COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x,     y + 1, COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x + 1, y + 1, COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x - 1, y,     COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x + 1, y,     COLOR_BLACK);\n    Font_Print(FONTID_CUR, g_gui_status.message, x,     y,     COLOR_WHITE);\n}\n\nvoid Blit_Fullscreen_UpdateBounds()\n{\n    // Scale implied by the blitter effect (eg: HQ2X double the resolution)\n    const int blit_scale_x = Blitters_Table[Blitters.current->blitter].x_fact;\n    const int blit_scale_y = Blitters_Table[Blitters.current->blitter].y_fact;\n\n    g_blit.src_pos_x = blit_scale_x * g_driver->x_start;\n    g_blit.src_pos_y = blit_scale_y * g_driver->y_show_start;\n    g_blit.src_size_x = blit_scale_x * g_driver->x_res;\n    g_blit.src_size_y = blit_scale_y * g_driver->y_res;\n    g_blit.dst_scale = 1;\n\n    const t_blitter_stretch stretch_mode = Blitters.current->stretch;\n    if (stretch_mode == BLITTER_STRETCH_MAX_INT)\n    {\n        // Automatic integer scale\n        const int scale_x = (int)g_video.res_x / g_blit.src_size_x;\n        const int scale_y = (int)g_video.res_y / g_blit.src_size_y;\n        g_blit.dst_scale = MIN(scale_x, scale_y);\n    }\n\n    if (stretch_mode == BLITTER_STRETCH_MAX)\n    {\n        // Cover all screen\n        g_video.game_area_x1 = 0;\n        g_video.game_area_y1 = 0;\n        g_video.game_area_x2 = g_video.res_x;\n        g_video.game_area_y2 = g_video.res_y;\n        g_blit.dst_scale = 0;\n    }\n    else\n    {\n        // Integer scale\n        g_video.game_area_x1 = (g_video.res_x - g_blit.src_size_x*g_blit.dst_scale) / 2;\n        g_video.game_area_y1 = (g_video.res_y - g_blit.src_size_y*g_blit.dst_scale) / 2;\n        g_video.game_area_x2 = g_video.game_area_x1 + g_blit.src_size_x*g_blit.dst_scale;\n        g_video.game_area_y2 = g_video.game_area_y1 + g_blit.src_size_y*g_blit.dst_scale;\n    }\n}\n\n// This is the actual final blitting function.\nstatic void Blit_Fullscreen_CopyStretch(ALLEGRO_BITMAP *src_buffer)\n{\n    al_set_target_bitmap(fs_out);\n    if (g_blit.dst_scale == 1)\n    {\n        al_draw_bitmap_region(src_buffer,\n            g_blit.src_pos_x, g_blit.src_pos_y,\n            g_blit.src_size_x, g_blit.src_size_y,\n            g_video.game_area_x1, g_video.game_area_y1,\n            0x0000);\n    }\n    else\n    {\n        al_draw_scaled_bitmap(src_buffer,\n            g_blit.src_pos_x, g_blit.src_pos_y,\n            g_blit.src_size_x, g_blit.src_size_y,\n            g_video.game_area_x1, g_video.game_area_y1,\n            g_video.game_area_x2 - g_video.game_area_x1, g_video.game_area_y2 - g_video.game_area_y1,\n            0x0000);\n    }\n}\n\nvoid    Blit_Fullscreen_Normal()\n{\n    Blit_Fullscreen_Misc();\n    Blit_Fullscreen_CopyStretch(screenbuffer);\n}\n\nvoid    Blit_Fullscreen_HQ2X()\n{\n    // Perform HQ2X into double buffer\n    // FIXME-OPT: Applied on full width.\n#if 0 // FIXME-ALLEGRO5: blitter hq2x\n    ALLEGRO_LOCKED_REGION* lr_src = al_lock_bitmap(screenbuffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);\n    ALLEGRO_LOCKED_REGION* lr_dst = al_lock_bitmap(Blit_Buffer_Double, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);\n\n    u8* addr_src = ((u8*)lr_src->data + (lr_src->pitch * blit_cfg.src_sy * 1) + (0 * sizeof(u16)));\n    u8* addr_dst = ((u8*)lr_dst->data + (lr_dst->pitch * blit_cfg.src_sy * 2) + (0 * sizeof(u16)));\n    hq2x_16(addr_src, addr_dst, MAX_RES_X+32, g_driver->y_res, (MAX_RES_X+32)*4);\n    al_unlock_bitmap(screenbuffer);\n    al_unlock_bitmap(Blit_Buffer_Double);\n#endif\n    Blit_Fullscreen_Misc();\n    Blit_Fullscreen_CopyStretch(Blit_Buffer_Double);\n}\n\nvoid    Blit_Fullscreen_TV_Mode()\n{\n#if 0 // FIXME-ALLEGRO5: blitter tv mode\n    int i;\n    for (i = 0; i < g_driver->y_res; i ++)\n    {\n        const u16 *psrc  = (u16 *)screenbuffer->line[blit_cfg.src_sy + i] + blit_cfg.src_sx;\n        u16 *pdst1 = (u16 *)Blit_Buffer_Double->line[(blit_cfg.src_sy + i) * 2] + (blit_cfg.src_sx * 1);\n        u16 *pdst2 = (u16 *)Blit_Buffer_Double->line[(blit_cfg.src_sy + i) * 2 + 1] + (blit_cfg.src_sx * 1);\n        int j = g_driver->x_res;\n        while (j-- != 0)\n        {\n            const u16 color_org = *psrc++;\n            const u32 color_mod_r = ((color_org      ) & 0x1F) * blit_cfg.tv_mode_factor;\n            const u32 color_mod_g = ((color_org >> 5 ) & 0x3F) * blit_cfg.tv_mode_factor;\n            const u32 color_mod_b = ((color_org >> 11) & 0x1F) * blit_cfg.tv_mode_factor;\n            const u16 color_mod = (color_mod_r) | (color_mod_g << 5) | (color_mod_b << 11);\n            *((u16 *)pdst1)++ = color_org;\n            *((u16 *)pdst2)++ = color_mod;\n        }\n    }\n#endif\n    Blit_Fullscreen_Misc();\n    Blit_Fullscreen_CopyStretch(Blit_Buffer_Double);\n}\n\n// FIXME-OPT: Obviously this is very slow. Just trying to get something working for 0.72. Later shall work better solution (generating inline assembly, etc).\nvoid    Blit_Fullscreen_TV_Mode_Double()\n{\n#if 0 // FIXME-ALLEGRO5: blitter tv mode double\n    int i;\n    for (i = 0; i < g_driver->y_res; i ++)\n    {\n        const u16 *psrc  = (u16 *)screenbuffer->line[blit_cfg.src_sy + i] + blit_cfg.src_sx;\n        u16 *pdst1 = (u16 *)Blit_Buffer_Double->line[(blit_cfg.src_sy + i) * 2] + (blit_cfg.src_sx * 2);\n        u16 *pdst2 = (u16 *)Blit_Buffer_Double->line[(blit_cfg.src_sy + i) * 2 + 1] + (blit_cfg.src_sx * 2);\n        int j = g_driver->x_res;\n        while (j-- != 0)\n        {\n            const u16 color_org = *psrc++;\n            const u32 color_org_32 = color_org | (color_org << 16);\n            const u32 color_mod_r = ((color_org      ) & 0x1F) * blit_cfg.tv_mode_factor;\n            const u32 color_mod_g = ((color_org >> 5 ) & 0x3F) * blit_cfg.tv_mode_factor;\n            const u32 color_mod_b = ((color_org >> 11) & 0x1F) * blit_cfg.tv_mode_factor;\n            const u16 color_mod = (color_mod_r) | (color_mod_g << 5) | (color_mod_b << 11);\n            const u32 color_mod_32 = color_mod | (color_mod << 16);\n            *(u32 *)pdst1 = color_org_32;\n            *(u32 *)pdst2 = color_mod_32;\n            pdst1 += 2;\n            pdst2 += 2;\n            // Note: adding ++ to the above u32 * cast somehow cause problems with GCC\n        }\n    }\n#endif\n    Blit_Fullscreen_Misc();\n    Blit_Fullscreen_CopyStretch(Blit_Buffer_Double);\n}\n\n// Blit screenbuffer to video memory in fullscreen mode\nvoid    Blit_Fullscreen()\n{\n    Blit_Fullscreen_UpdateBounds();\n\n#if 0\n    {\n        static char buf[512];\n        Font_Set (F_SMALL);\n        if (fskipper.FPS_Temp == 0) strcpy(buf, \"\");\n        sprintf(buf+strlen(buf), \"%1d\", fskipper.FPS_Temp % 10);\n        //Font_Print (screenbuffer, buf, 49 + (fskipper.FPS_Temp % 10) * 6, 49 + (fskipper.FPS_Temp / 10)*10, COLOR_BLACK);\n        //Font_Print (screenbuffer, buf, 50 + (fskipper.FPS_Temp % 10) * 6, 50 + (fskipper.FPS_Temp / 10)*10, COLOR_WHITE);\n        Font_Print (screenbuffer, buf, 19, 49, COLOR_BLACK);\n        Font_Print (screenbuffer, buf, 20, 50, COLOR_WHITE);\n    }\n#endif\n\n    Blitters_Table[Blitters.current->blitter].blit_func();\n\n    if (g_gui_status.timeleft && g_config.show_fullscreen_messages)\n    {\n        Blit_Fullscreen_Message(fs_out, g_gui_status.timeleft);\n        g_gui_status.timeleft --;\n    }\n\n    al_flip_display();\n}\n\nvoid    Blit_GUI()\n{\n    // Wait for VSync if necessary\n    if (g_config.video_mode_gui_vsync)\n    {\n        // FIXME: see note about line below in Blit_Fullscreen()\n        if (!(fskipper.Mode == FRAMESKIP_MODE_THROTTLED && fskipper.Throttled_Speed > 70))\n            al_wait_for_vsync();\n        // Update 3-D Glasses (if VSync)\n        if (Glasses.Enabled)\n            Glasses_Update();\n        PROFILE_STEP(\"gui_vsync\");\n    }\n\n    // Blit\n    ALLEGRO_BITMAP* backbuffer = al_get_backbuffer(g_display);\n    al_set_target_bitmap(backbuffer);\n    al_draw_bitmap(gui_buffer, 0, 0, 0x0000);\n    PROFILE_STEP(\"al_draw_bitmap()\");\n\n    al_flip_display();\n    PROFILE_STEP(\"al_flip_display\");\n\n    // Update 3-D Glasses (if no VSync)\n    if (!g_config.video_mode_gui_vsync)\n        if (Glasses.Enabled)\n            Glasses_Update();\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/blit.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - blit.h\n// Blitters - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define BLITTER_NORMAL          (0)\n#define BLITTER_TVMODE          (1)\n#define BLITTER_TVMODE_DOUBLE   (2)\n#define BLITTER_HQ2X            (3)\n#define BLITTER_MAX             (4)\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Blit_Init();\nvoid    Blit_CreateVideoBuffers();\nvoid    Blit_DestroyVideoBuffers();\n\nvoid    Blit_Fullscreen();\nvoid    Blit_Fullscreen_UpdateBounds();\n\nvoid    Blit_GUI();\n\nvoid    Blit_Fullscreen_Normal();\nvoid    Blit_Fullscreen_TV_Mode();\nvoid    Blit_Fullscreen_TV_Mode_Double();\nvoid    Blit_Fullscreen_HQ2X();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\n// Buffers\nextern ALLEGRO_BITMAP*  Blit_Buffer_LineScratch;    // Line buffer scratch pad\nextern ALLEGRO_BITMAP*  Blit_Buffer_Double;         // Double-sized buffer\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/blit_c.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - blit_c.c\n// Blitters/Video Configuration Applet - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"blit_c.h\"\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/blit_c.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - blit_c.h\n// Blitters/Video Configuration Applet - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/blitintf.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - blitintf.c\r\n// Blitter configuration file and GUI interface - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"blit.h\"\r\n#include \"blitintf.h\"\r\n#include \"video.h\"\r\n#include \"libparse.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_blitters Blitters;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic int     Blitters_Str2Num(const char *s);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Note: 'name' not const because the string is actually overwritten (could be done without)\r\nt_blitter *     Blitter_New(char *name)\r\n{\r\n    // Look for system identifier\r\n    char * p = name + strlen(name) - 1;\r\n    if (*p == ']')\r\n        *p = EOSTR;\r\n    p = strstr(name, BLITTER_OS_SEP);\r\n\r\n    // Ignore blitter if it is not for current system\r\n#ifdef ARCH_WIN32\r\n    if (p == NULL || stricmp(p + strlen(BLITTER_OS_SEP), BLITTER_OS_WIN) != 0)\r\n        return (NULL);\r\n#elif ARCH_UNIX\r\n    if (p == NULL || stricmp(p + strlen(BLITTER_OS_SEP), BLITTER_OS_UNIX) != 0)\r\n        return (NULL);\r\n#endif\r\n    if (p != NULL)\r\n        *p = EOSTR;\r\n\r\n    // Allocate a blitter and set it with name and default values\r\n    t_blitter * b = (t_blitter*)malloc(sizeof (t_blitter));\r\n    b->name             = strdup(name);\r\n    b->index            = Blitters.count;\r\n    b->res_x            = 320;\r\n    b->res_y            = 240;\r\n    b->blitter          = BLITTER_NORMAL;\r\n    b->tv_colors        = FALSE;\r\n    b->refresh_rate     = 0;                                        // Default\r\n    b->stretch          = BLITTER_STRETCH_NONE; // BLITTER_STRETCH_MAX_INT;\r\n    return (b);\r\n}\r\n\r\nvoid Blitter_Delete(t_blitter *b)\r\n{\r\n    free(b->name);\r\n    free(b);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid Blitters_Close()\r\n{\r\n    list_free_custom(&Blitters.list, (t_list_free_handler)Blitter_Delete);\r\n}\r\n\r\nstatic const char * Blitters_Def_Variables[] =\r\n{\r\n    \"res\",\r\n    \"blitter\",\r\n    \"refresh_rate\",\r\n    \"stretch\",\r\n    NULL\r\n};\r\n\r\nstatic int  Blitters_Parse_Line(char *s, char *s_case)\r\n{\r\n    if (s[0] == '[')\r\n    {\r\n        Blitters.current = Blitter_New(&s_case[1]);\r\n        if (Blitters.current != NULL)\r\n        {\r\n            Blitters.count++;\r\n            list_add_to_end(&Blitters.list, Blitters.current);\r\n        }\r\n        return (MEKA_ERR_OK);\r\n    }\r\n\r\n    // Skip line when we're inside a blitter we can ignore\r\n    if (Blitters.current == NULL)\r\n        return (MEKA_ERR_OK);\r\n\r\n    // Set attributes\r\n    char w[256];\r\n    parse_getword(w, sizeof(w), &s, \"=\", ';', PARSE_FLAGS_NONE);\r\n    int i;\r\n    for (i = 0; Blitters_Def_Variables [i]; i++)\r\n        if (!strcmp(w, Blitters_Def_Variables [i]))\r\n            break;\r\n    if (Blitters.current == NULL)\r\n        return (MEKA_ERR_MISSING);\r\n    switch (i)\r\n    {\r\n        // Resolution\r\n    case 0:\r\n        {\r\n            int x, y;\r\n            parse_skip_spaces(&s);\r\n            if (sscanf(s, \"%dx%d\", &x, &y) == 2)\r\n            {\r\n                Blitters.current->res_x = x;\r\n                Blitters.current->res_y = y;\r\n            }\r\n            return MEKA_ERR_OK;\r\n        }\r\n        // Blitter\r\n    case 1:\r\n        Blitters.current->blitter = Blitters_Str2Num (s);\r\n        if (Blitters.current->blitter == BLITTER_TVMODE || Blitters.current->blitter == BLITTER_TVMODE_DOUBLE)\r\n            Blitters.current->tv_colors = TRUE;\r\n        else\r\n            Blitters.current->tv_colors = FALSE;\r\n        return MEKA_ERR_OK;\r\n    case 2:\r\n        if (!strcmp(w, \"auto\"))\r\n            Blitters.current->refresh_rate = 0;\r\n        else\r\n            Blitters.current->refresh_rate = atoi(s);\r\n        return MEKA_ERR_OK;\r\n        // Stretch\r\n    case 3:\r\n        Blitters.current->stretch = BLITTER_STRETCH_MAX_INT;\r\n        return MEKA_ERR_OK;\r\n    }\r\n    return MEKA_ERR_UNKNOWN;\r\n}\r\n\r\nvoid    Blitters_Init_Values()\r\n{\r\n    Blitters.current = NULL;\r\n    Blitters.blitter_configuration_name = NULL;\r\n}\r\n\r\nvoid    Blitters_Init()\r\n{\r\n    ConsolePrint(Msg_Get(MSG_Blitters_Loading));\r\n\r\n    Blitters.list = NULL;\r\n    Blitters.current = NULL;\r\n\r\n    // Open and read file\r\n    t_tfile * tf;\r\n    if ((tf = tfile_read (Blitters.filename)) == NULL)\r\n        Quit_Msg(\"%s\", meka_strerror());\r\n    ConsolePrint(\"\\n\");\r\n\r\n    // Parse each line\r\n    int line_cnt = 0;\r\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        const char* line = (char*)lines->elem;\r\n        line_cnt += 1;\r\n\r\n        int i, j;\r\n        char s1 [256], s2 [256];\r\n        for (i = 0, j = 0; line [i] != 0 && line [i] != ';'; i ++)\r\n            if ((line [0] == '[') || (line [i] != ' ' && line [i] != '\\t'))\r\n                s2 [j ++] = line [i];\r\n        s2 [j] = 0;\r\n        if (StrIsNull (s2))\r\n            continue;\r\n\r\n        strcpy(s1, s2);\r\n        StrLower(s1);\r\n\r\n        switch (Blitters_Parse_Line (s1, s2))\r\n        {\r\n        case MEKA_ERR_UNKNOWN:          tfile_free(tf); Quit_Msg(Msg_Get(MSG_Blitters_Error_Unrecognized), line_cnt);\r\n        case MEKA_ERR_MISSING:          tfile_free(tf); Quit_Msg(Msg_Get(MSG_Blitters_Error_Missing), line_cnt);\r\n        case MEKA_ERR_VALUE_INCORRECT:  tfile_free(tf); Quit_Msg(Msg_Get(MSG_Blitters_Error_Incorrect_Value), line_cnt);\r\n        }\r\n    }\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n\r\n    // Requires at least 1 blitter\r\n    if (Blitters.count == 0)\r\n        Quit_Msg(\"%s\", Msg_Get(MSG_Blitters_Error_Not_Enough));\r\n\r\n    // Current blitter\r\n    if (Blitters.blitter_configuration_name != NULL)\r\n        Blitters.current = Blitters_FindBlitterByName(Blitters.blitter_configuration_name);\r\n    if (Blitters.current == NULL)\r\n        Blitters.current = (t_blitter*)Blitters.list->elem; // first\r\n}\r\n\r\nt_blitter * Blitters_FindBlitterByName(const char *name)\r\n{\r\n    for (t_list* blitters = Blitters.list; blitters != NULL; blitters = blitters->next)\r\n    {\r\n        t_blitter* blitter = (t_blitter*)blitters->elem;\r\n        if (stricmp(blitter->name, name) == 0)\r\n            return (blitter);\r\n    }\r\n    return (NULL);\r\n}\r\n\r\nconst static struct\r\n{\r\n    int value;\r\n    const char *name;\r\n} Blitters_Str2Num_Table [] =\r\n{\r\n    { BLITTER_NORMAL,        \"normal\"        },\r\n    { BLITTER_TVMODE,        \"tv\"            },\r\n    { BLITTER_TVMODE,        \"tvmode\"        },\r\n    { BLITTER_TVMODE_DOUBLE, \"tvmode_double\" },\r\n    { BLITTER_HQ2X,          \"hq2x\"          },\r\n    { 0, 0 }\r\n};\r\n\r\nstatic int     Blitters_Str2Num(const char *s)\r\n{\r\n    for (int i = 0; Blitters_Str2Num_Table[i].name; i ++)\r\n        if (strcmp(s, Blitters_Str2Num_Table[i].name) == 0)\r\n            return (Blitters_Str2Num_Table[i].value);\r\n    return (BLITTER_NORMAL);\r\n}\r\n\r\nvoid    Blitters_Switch_Common()\r\n{\r\n    if (g_env.state == MEKA_STATE_GAME)\r\n        Video_Setup_State();\r\n    Msg(MSGT_USER, Msg_Get(MSG_Blitters_Set), Blitters.current->name);\r\n    gui_menu_uncheck_all (menus_ID.blitters);\r\n    gui_menu_check (menus_ID.blitters, Blitters.current->index);\r\n}\r\n\r\nvoid    Blitters_SwitchNext()\r\n{\r\n    int index = (Blitters.current->index + 1) % Blitters.count;\r\n    t_list* blitters;\r\n    for (blitters = Blitters.list; blitters != NULL; blitters = blitters->next)\r\n        if (index-- == 0)\r\n            break;\r\n    assert(blitters != NULL);\r\n    Blitters.current = (t_blitter*)blitters->elem;\r\n    Blitters_Switch_Common();\r\n}\r\n\r\nstatic void    Blitters_Switch_Handler (t_menu_event *event)\r\n{\r\n    Blitters.current = (t_blitter *)event->user_data;\r\n    Blitters_Switch_Common();\r\n}\r\n\r\nvoid    Blitters_Menu_Init (int menu_id)\r\n{\r\n    for (t_list* blitters = Blitters.list; blitters != NULL; blitters = blitters->next)\r\n    {\r\n        t_blitter* blitter = (t_blitter*)blitters->elem;\r\n        menu_add_item(menu_id,\r\n            blitter->name,\r\n            NULL,\r\n            MENU_ITEM_FLAG_ACTIVE | ((blitter == Blitters.current) ? MENU_ITEM_FLAG_CHECKED : 0),\r\n            (t_menu_callback)Blitters_Switch_Handler, blitter);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/blitintf.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - blitintf.h\n// Blitter configuration file and GUI interface - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define BLITTER_OS_SEP              \"::\"\n#define BLITTER_OS_WIN              \"WIN\"\n#define BLITTER_OS_UNIX             \"UNIX\"\n\nenum t_blitter_stretch\n{\n    BLITTER_STRETCH_NONE        = 0,\n    BLITTER_STRETCH_MAX_INT     = 1,     // Default\n    BLITTER_STRETCH_MAX         = 2,\n};\n\n//-----------------------------------------------------------------------------\n// Blitter Data\n//-----------------------------------------------------------------------------\n\nstruct t_blitter\n{\n    char *              name;\n    int                 index;\n    int                 res_x;\n    int                 res_y;\n    int                 blitter;\n    bool                tv_colors;\n    int                 refresh_rate;\n    t_blitter_stretch   stretch;\n};\n\n//-----------------------------------------------------------------------------\n// Blitter Functions\n//-----------------------------------------------------------------------------\n\nt_blitter *     Blitter_New(char *name);\nvoid            Blitter_Delete(t_blitter *b);\n\n//-----------------------------------------------------------------------------\n// Blitters Data\n//-----------------------------------------------------------------------------\n\nstruct t_blitters\n{\n    int         count;\n    t_blitter * current;\n    t_list *    list;\n    char        filename[FILENAME_LEN];\n    char *      blitter_configuration_name;\n};\n\nextern t_blitters Blitters;\n\n//-----------------------------------------------------------------------------\n// Blitters Functions\n//-----------------------------------------------------------------------------\n\nvoid        Blitters_Init_Values();\nvoid        Blitters_Init();\nvoid        Blitters_Close();\n\nt_blitter * Blitters_FindBlitterByName(const char *name);\n\nvoid        Blitters_SwitchNext();\nvoid        Blitters_Menu_Init(int menu_id);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/bmemory.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - bmemory.c\n// Battery Backed Memory Emulation - Code\n//-----------------------------------------------------------------------------\n// TODO: rename everything to OB*\n//                           (OnBoard Memory)\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"mappers.h\"\n#include \"eeprom.h\"\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    BMemory_Verify_Usage()\n{\n    int   i;\n    const byte *p;\n\n    while (sms.SRAM_Pages > 1)\n    {\n        p = &SRAM[(sms.SRAM_Pages - 1) * 0x2000];\n        for (i = 0; i < 0x2000; i++)\n            if (p[i] != 0x00)\n                return;\n        sms.SRAM_Pages--;\n    }\n}\n\nvoid    BMemory_Get_Infos(void** data, int* len)\n{\n    switch (g_machine.mapper)\n    {\n    case MAPPER_Standard:\n        BMemory_SRAM_Get_Infos (data, len);\n        return;\n    case MAPPER_93c46:\n        BMemory_93c46_Get_Infos(data, len);\n        return;\n    default:\n        (*data) = NULL;\n        (*len) = 0;\n        return;\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid        BMemory_Load()\n{\n    // FIXME: Clear() handler\n    // May want to totally move BMemory stuff to a driver based system\n    memset (SRAM, 0, 0x8000);\n    if (g_machine.mapper == MAPPER_93c46)\n        EEPROM_93c46_Clear();\n\n    FILE* f = fopen(g_env.Paths.BatteryBackedMemoryFile, \"rb\");\n    if (f == NULL)\n        return;\n    switch (g_machine.mapper)\n    {\n    case MAPPER_Standard:       BMemory_SRAM_Load (f);  break;\n    case MAPPER_93c46:          BMemory_93c46_Load (f); break;\n    }\n    fclose (f);\n}\n\nvoid        BMemory_Save()\n{\n    FILE *  f;\n\n    BMemory_Verify_Usage();\n    switch (g_machine.mapper)\n    {\n    case MAPPER_Standard:       if (sms.SRAM_Pages == 0) return; break;\n    case MAPPER_93c46:          break;\n    default:                    return;\n    }\n    if (!al_filename_exists(g_env.Paths.SavegameDirectory))\n        al_make_directory(g_env.Paths.SavegameDirectory);\n    f = fopen(g_env.Paths.BatteryBackedMemoryFile, \"wb\");\n    switch (g_machine.mapper)\n    {\n    case MAPPER_Standard:       BMemory_SRAM_Save (f); break;\n    case MAPPER_93c46:          BMemory_93c46_Save (f); break;\n    }\n    if (f)\n        fclose (f);\n}\n\nvoid    BMemory_Load_State(FILE* f)\n{\n    switch (g_machine.mapper)\n    {\n    case MAPPER_Standard:       BMemory_SRAM_Load_State (f);  break;\n    case MAPPER_93c46:          BMemory_93c46_Load_State (f); break;\n    }\n}\n\nvoid    BMemory_Save_State(FILE* f)\n{\n    switch (g_machine.mapper)\n    {\n    case MAPPER_Standard:       BMemory_SRAM_Save_State (f);  break;\n    case MAPPER_93c46:          BMemory_93c46_Save_State (f); break;\n    }\n}\n\n//-----------------------------------------------------------------------------\n// SRAM\n//-----------------------------------------------------------------------------\n\nvoid    BMemory_SRAM_Load(FILE* f)\n{\n    sms.SRAM_Pages = 0;\n    do\n    {\n        if (fread (&SRAM[sms.SRAM_Pages * 0x2000], 0x2000, 1, f) == 1)\n            sms.SRAM_Pages++;\n        else\n            break;\n    }\n    while (sms.SRAM_Pages < 4); // This is the max value\n\n    if (sms.SRAM_Pages > 0)\n        Msg(MSGT_USER, Msg_Get(MSG_SRAM_Loaded), sms.SRAM_Pages * 8);\n    else\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_SRAM_Load_Unable));\n}\n\nvoid    BMemory_SRAM_Save(FILE* f)\n{\n    if (f && fwrite (SRAM, sms.SRAM_Pages * 0x2000, 1, f) == 1)\n        Msg(MSGT_USER, Msg_Get(MSG_SRAM_Wrote), sms.SRAM_Pages * 8);\n    else\n        Msg(MSGT_USER, Msg_Get(MSG_SRAM_Write_Unable), sms.SRAM_Pages * 8);\n}\n\nvoid    BMemory_SRAM_Load_State(FILE* f)\n{\n    fread (SRAM, sms.SRAM_Pages * 0x2000, 1, f);\n    if (sms.SRAM_Pages < 4)\n        memset (SRAM + sms.SRAM_Pages * 0x2000, 0, (4 - sms.SRAM_Pages) * 0x2000);\n}\n\nvoid    BMemory_SRAM_Save_State(FILE* f)\n{\n    if (sms.SRAM_Pages > 0)\n        fwrite (SRAM, sms.SRAM_Pages * 0x2000, 1, f);\n}\n\nvoid    BMemory_SRAM_Get_Infos(void** data, int* len)\n{\n    if (sms.SRAM_Pages > 0)\n    {\n        (*data) = SRAM;\n        (*len)  = sms.SRAM_Pages * 0x2000;\n    }\n    else\n    {\n        (*data) = NULL;\n        (*len) = 0;\n    }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/bmemory.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - bmemory.h\n// Backed Memory Devices Emulation - Headers\n//-----------------------------------------------------------------------------\n\nvoid    BMemory_Verify_Usage();\n\nvoid    BMemory_Load();\nvoid    BMemory_Save();\nvoid    BMemory_Load_State(FILE* f);\nvoid    BMemory_Save_State(FILE* f);\nvoid    BMemory_Get_Infos(void** data, int* len);\n\n//-----------------------------------------------------------------------------\n// SRAM\n//-----------------------------------------------------------------------------\n\nvoid    BMemory_SRAM_Load(FILE* f);\nvoid    BMemory_SRAM_Save(FILE* f);\nvoid    BMemory_SRAM_Load_State(FILE* f);\nvoid    BMemory_SRAM_Save_State(FILE* f);\nvoid    BMemory_SRAM_Get_Infos(void** data, int* len);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/build.cpp",
    "content": "#include \"shared.h\"\r\nchar MEKA_BUILD_DATE[] = __DATE__;\r\nchar MEKA_BUILD_TIME[] = __TIME__;\r\n"
  },
  {
    "path": "meka/srcs/build.h",
    "content": ""
  },
  {
    "path": "meka/srcs/capture.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - capture.c\r\n// Screen Capture - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"capture.h\"\r\n#include \"vmachine.h\"\r\n#include \"vdp.h\"\r\n\r\n// Keep request enabled if we're in 'all frames' capture mode\r\n//if (!g_config.capture_all_frames)\r\n//Capture.request = FALSE;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_capture   Capture;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Initialize screen capture system\r\n// Needs to be called before loading the configuration file\r\nvoid        Capture_Init()\r\n{\r\n    Capture.request = FALSE;\r\n    Capture.request_all_frames = FALSE;\r\n    Capture_Init_Game();\r\n}\r\n\r\n// Screen capture per-game initialization\r\n// Called each time a new Game/ROM is loaded\r\nvoid        Capture_Init_Game()\r\n{\r\n    Capture.id_number = 1;\r\n}\r\n\r\n// Request a screen capture (will be actually done on next rendering)\r\nvoid        Capture_Request()\r\n{\r\n    Capture.request = TRUE;\r\n}\r\n\r\n// Compute filename for next screen capture\r\nstatic void Capture_FileName_Get(char* dst)\r\n{\r\n    // Create directory if necessary\r\n    if (!al_filename_exists(g_env.Paths.ScreenshotDirectory))\r\n        al_make_directory(g_env.Paths.ScreenshotDirectory);\r\n\r\n    // Figure out a base filename\r\n    const char* game_name;\r\n    char s1[FILENAME_LEN];\r\n    if ((g_machine_flags & MACHINE_RUN) == MACHINE_RUN) // If a game is loaded & running\r\n    {\r\n        strcpy(s1, g_env.Paths.MediaImageFile);\r\n        StrPath_RemoveDirectory(s1);\r\n        StrPath_RemoveExtension(s1);\r\n        game_name = s1;\r\n    }\r\n    else\r\n    {\r\n        game_name = CAPTURE_DEFAULT_PREFIX;\r\n    }\r\n\r\n    char s2[FILENAME_LEN];\r\n    sprintf(s2, \"%%s/%s\", g_config.capture_filename_template);\r\n\r\n    // Create a full filename and check if the file already exists. Loop if it is the case.\r\n    // Note: CAPTURE_ID_MAX is 9999, for all capturing this gives us 2mn46s worth of frames at 60 FPS.\r\n    do\r\n    {\r\n        sprintf(dst, s2, g_env.Paths.ScreenshotDirectory, game_name, Capture.id_number);\r\n        Capture.id_number++;\r\n    }\r\n    while (al_filename_exists(dst) != 0 && Capture.id_number < CAPTURE_ID_MAX);\r\n}\r\n\r\n// Capture current screen to a file\r\nstatic void     Capture_Screen()\r\n{\r\n    //PALETTE     pal;\r\n\r\n    // Get a filename\r\n    char filename[FILENAME_LEN];\r\n    Capture_FileName_Get(filename);\r\n    if (Capture.id_number >= CAPTURE_ID_MAX)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Capture_Error_File));\r\n        return;\r\n    }\r\n\r\n    int x_start, x_len;\r\n    int y_start, y_len;\r\n    ALLEGRO_BITMAP* source = NULL;\r\n    if ((g_env.state == MEKA_STATE_GAME) || (!g_config.capture_include_gui)) \r\n    {\r\n        // Fullscreen\r\n        source = screenbuffer;\r\n        x_start = g_driver->x_start;\r\n        y_start = g_driver->y_show_start;\r\n        x_len = g_driver->x_res;\r\n        y_len = g_driver->y_res;\r\n\r\n        // Crop left column\r\n        if (g_config.capture_crop_scrolling_column)\r\n        {\r\n            if ((g_driver->id == DRV_SMS) && (tsms.VDP_VideoMode > 4) && (Mask_Left_8))\r\n            {\r\n                x_start += 8;\r\n                x_len -= 8;\r\n            }\r\n        }\r\n\r\n        // Automatic crop on tile boundaries (for map making)\r\n        // In total, remove 8 pixels from each axis\r\n        if (g_config.capture_crop_align_8x8)\r\n        {\r\n            const int scroll_x = g_machine.VDP.scroll_x_latched;\r\n            const int scroll_y = g_machine.VDP.scroll_y_latched;\r\n            x_start += scroll_x & 7;\r\n            y_start += 8 - (scroll_y & 7);\r\n            x_len -= 8;\r\n            y_len -= 8;\r\n        }\r\n    }\r\n    else if (g_env.state == MEKA_STATE_GUI)\r\n    {\r\n        // GUI mode\r\n        x_start = 0;\r\n        y_start = 0;\r\n        x_len = g_config.video_mode_gui_res_x;\r\n        y_len = g_config.video_mode_gui_res_y;\r\n        source = gui_buffer;\r\n    }\r\n    else\r\n    {\r\n        // Unknown Mode\r\n        assert(0);\r\n        return;\r\n    }\r\n\r\n    ALLEGRO_BITMAP* bmp = al_create_sub_bitmap(source, x_start, y_start, x_len, y_len);\r\n    if (bmp == NULL)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Capture_Error));\r\n        return;\r\n    }\r\n\r\n    //get_palette(pal);\r\n    if (!al_save_bitmap(filename, bmp))\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Capture_Error));\r\n        al_destroy_bitmap(bmp);\r\n        return;\r\n    }\r\n\r\n    al_destroy_bitmap(bmp);\r\n\r\n    // Verbose\r\n    StrPath_RemoveDirectory(filename);\r\n    Msg(MSGT_USER, Msg_Get(MSG_Capture_Done), filename);\r\n}\r\n\r\nvoid    Capture_Update()\r\n{\r\n    if (Capture.request)\r\n    {\r\n        Capture_Screen();\r\n        Capture.request = FALSE;\r\n    }\r\n    if (Capture.request_all_frames && !(g_machine_flags & MACHINE_PAUSED))\r\n    {\r\n        Capture_Screen();\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Capture_MenuHandler_Capture()\r\n{\r\n    Capture_Request();\r\n}\r\n\r\nvoid    Capture_MenuHandler_AllFrames()\r\n{\r\n    Capture.request_all_frames = !Capture.request_all_frames;\r\n    gui_menu_toggle_check(menus_ID.screenshots, 1);\r\n    if (Capture.request_all_frames)\r\n    {\r\n        // FIXME-CAPTURE\r\n    }\r\n}\r\n\r\nvoid    Capture_MenuHandler_IncludeGui()\r\n{\r\n    g_config.capture_include_gui = !g_config.capture_include_gui;\r\n    gui_menu_toggle_check(menus_ID.screenshots, 2);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/capture.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - capture.h\n// Screen Capture - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define CAPTURE_ID_MAX          (99999)      // Security measure for not going in infinite loop with short file name.\n#define CAPTURE_DEFAULT_PREFIX  \"meka\"\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Capture_Init();\nvoid    Capture_Init_Game();\nvoid    Capture_Request();\nvoid    Capture_Update();\n\nvoid    Capture_MenuHandler_Capture();\nvoid    Capture_MenuHandler_AllFrames();\nvoid    Capture_MenuHandler_IncludeGui();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_capture\n{\n    int         request;\n    int         request_all_frames;\n    int         id_number;\n};\n\nextern t_capture    Capture;\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/checksum.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - checksum.c\r\n// Checksum - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include <zlib.h>\r\n#include \"db.h\"\r\n#include \"vlfn.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     mekacrc(t_meka_crc *dst, const u8 *data, int data_size)\r\n{\r\n    int         i;\r\n    long        Checksum_8 [8];\r\n\r\n    if ((data_size > 0x2000) && (data_size & 0x1FFF) != 0)\r\n        data_size -= (data_size % 8192);\r\n    for (i = 0; i < 8; i ++)\r\n        Checksum_8 [i] = 0;\r\n    for (i = 0; i < data_size; i++)\r\n    {\r\n        int v = data[i];\r\n        Checksum_8 [v & 7] ++;\r\n        Checksum_8 [v >> 5] ++;\r\n    }\r\n    for (i = 0; i < 8; i ++)\r\n        Checksum_8 [i] &= 0xFF;\r\n\r\n    // This is totally stupid. Can't use a cast, or something?\r\n    // I remember that at some point I had a problem and reverted\r\n    // to this formula, but it looks stupid now.\r\n    dst->v[0] = dst->v[1] = 0x00000000;\r\n    for (i = 0; i < 8; i ++)\r\n        dst->v[(i & 4) ? 0 : 1] |= Checksum_8 [7 - i] << ((i & 3) * 8);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Checksum_Perform(const u8 *data, int data_size)\r\n// Compute checksums for given set of ROM and update appropriate date\r\n//-----------------------------------------------------------------------------\r\n// FIXME: should take a media in parameter?\r\n//-----------------------------------------------------------------------------\r\nvoid            Checksum_Perform(const u8 *data, int data_size)\r\n{\r\n    t_meka_crc  crc_mekacrc;\r\n\r\n    // Compute and store MekaCRC\r\n    mekacrc(&crc_mekacrc, data, data_size);\r\n    g_media_rom.mekacrc.v[0] = crc_mekacrc.v[0];\r\n    g_media_rom.mekacrc.v[1] = crc_mekacrc.v[1];\r\n\r\n    // Compute and store CRC32\r\n    g_media_rom.crc32 = crc32(0, data, data_size);\r\n\r\n    // Print out checksums (debugging)\r\n    // Msg(MSGT_DEBUG, \"MekaCRC -> %08X.%08X ; CRC -> %08x\", g_media_rom.mekacrc.v[0], g_media_rom.mekacrc.v[1], g_media_rom.crc32);\r\n\r\n    // Find DB entry\r\n    DB.current_entry = DB_Entry_Find(g_media_rom.crc32, &g_media_rom.mekacrc);\r\n\r\n    // Update VLFN\r\n    {\r\n        char media_path[FILENAME_LEN];\r\n        StrPath_RemoveDirectory(media_path, g_env.Paths.MediaImageFile);\r\n        if (DB.current_entry)\r\n            VLFN_AddEntry(media_path, DB.current_entry);\r\n        else\r\n            VLFN_RemoveEntry(media_path);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/checksum.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - checksum.h\n// Checksum Database - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Checksum_Perform(const u8 *data, int size);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/coleco.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - coleco.c\r\n// Coleco Vision Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"coleco.h\"\r\n#include \"debugger.h\"\r\n#include \"fskipper.h\"\r\n#include \"inputs_t.h\"\r\n#include \"mappers.h\"\r\n#include \"patch.h\"\r\n#include \"vdp.h\"\r\n#include \"video.h\"\r\n#include \"video_m2.h\"\r\n#include \"sound/psg.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic u8 Coleco_Joy_Table_Conv [64];\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// [MAPPER: COLECOVISION] WRITE BYTE ------------------------------------------\r\nWRITE_FUNC (Write_Mapper_Coleco)\r\n{\r\n    if ((Addr >= 0x6000) && (Addr < 0x8000))\r\n    {\r\n        // 0x6000 & 0xE3FF = 0x6000\r\n        // 0x6001 & 0xE3FF = 0x6001\r\n        // 0x6401 & 0xE3FF = 0x6001\r\n        // 0x7001 & 0xE3FF = 0x6001\r\n        // 0x7FFF & 0xE3FF = 0x63FF\r\n        // etc...\r\n        Addr &= 0xE3FF;\r\n        Mem_Pages[3][Addr] = Mem_Pages[3][Addr|0x0400] = Mem_Pages[3][Addr|0x0800] =\r\n            Mem_Pages[3][Addr|0x0C00] = Mem_Pages[3][Addr|0x1000] = Mem_Pages[3][Addr|0x1400] =\r\n            Mem_Pages[3][Addr|0x1800] = Mem_Pages[3][Addr|0x1C00] = Value;\r\n        return;\r\n    }\r\n    // Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Write), sms.R.PC.W, Value, Addr);\r\n}\r\n\r\nvoid    Coleco_Port_Out (word Port, byte Value)\r\n{\r\n    switch (Port & 0xE0)\r\n    {\r\n    case 0xA0: // Video\r\n        if (Port & 1) Tms_VDP_Out_Address (Value);\r\n        else Tms_VDP_Out_Data (Value); return;\r\n    case 0xE0: // Sound\r\n        SN76489_Write(Value); /* PSG_0_Write (Value); */ return;\r\n    case 0x80: // Change Input Mode\r\n        sms.Input_Mode = 0; return;\r\n    case 0xC0: // Change Input Mode\r\n        sms.Input_Mode = 1; return;\r\n    }\r\n#ifdef DEBUG_IO\r\n    Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Port_Write), sms.R.PC.W, Port, Value);\r\n#endif\r\n}\r\n\r\nbyte    Coleco_Port_In (word Port)\r\n{\r\n    switch (Port & 0xE0)\r\n    {\r\n    case 0xA0: // Video\r\n        if (Port & 1) return (Tms_VDP_In_Status ());\r\n        else return (Tms_VDP_In_Data ());\r\n    case 0xE0: // Controls\r\n        return (Coleco_Inputs (Port));\r\n    }\r\n#ifdef DEBUG_IO\r\n    Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Port_Read), sms.R.PC.W, Port);\r\n#endif\r\n    return (0xFF);\r\n}\r\n\r\n// Colecovision Inputs emulation ----------------------------------------------\r\nbyte    Coleco_Inputs (word Port)\r\n{\r\n    // Msg(MSGT_DEBUG, \"[coleco_inputs] %d, %d\", Port & 2, sms.Input_Mode);\r\n    if ((Port & 2) == 0)\r\n    {\r\n        // Player 1\r\n        if (sms.Input_Mode == 0)\r\n            return (Coleco_Keypad_1 ());\r\n        return (Coleco_Joy_Table_Conv [tsms.Control[7] & 0x3F]);\r\n    }\r\n    else\r\n    {\r\n        // Player 2\r\n        if (sms.Input_Mode == 0)\r\n            return (Coleco_Keypad_2 ());\r\n        return (Coleco_Joy_Table_Conv [(tsms.Control[7] >> 8) & 0x3F]);\r\n    }\r\n}\r\n\r\n// Colecovision keypad 1, emulation -------------------------------------------\r\nbyte    Coleco_Keypad_1()\r\n{\r\n    int    v;\r\n\r\n         if (Inputs_KeyDown(ALLEGRO_KEY_0))        v = 10; // 0\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_1))        v = 13; // 1\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_2))        v =  7; // 2\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_3))        v = 12; // 3\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_4))        v =  2; // 4\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_5))        v =  3; // 5\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_6))        v = 14; // 6\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_7))        v =  5; // 7\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_8))        v =  1; // 8\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_9))        v = 11; // 9\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_MINUS))    v =  9; // *\r\n    else if (Inputs_KeyDown(ALLEGRO_KEY_EQUALS))   v =  6; // #\r\n    else v = 0x0F;\r\n    if (tsms.Control[7] & 0x20)\r\n        v |= 0x40;\r\n    return (v | 0x10 | 0x20 /*| 0x80*/);\r\n}\r\n\r\n// Colecovision keypad 2, non working emulation -------------------------------\r\n// FIXME: ...\r\nbyte        Coleco_Keypad_2()\r\n{\r\n    int     v = 0x0F;\r\n    if ((tsms.Control[7] >> 8) & 0x20)\r\n        v |= 0x40;\r\n    return (v | 0x10 | 0x20 /*| 0x80*/);\r\n}\r\n\r\n// Build Coleco Input Conversion table\r\n// This is because the input system currently fills input value for Sega 8-bit\r\nvoid        Coleco_Init_Table_Inputs()\r\n{\r\n    int     i;\r\n\r\n    /*\r\n    Bit 0=Left                    1\r\n    Bit 1=Down                    2\r\n    Bit 2=Right                   4\r\n    Bit 3=Up                      8\r\n    Bit 6=Left button             64\r\n    */\r\n\r\n    for (i = 0; i <= 0x3F; i ++)\r\n    {\r\n        Coleco_Joy_Table_Conv [i] =\r\n            0x10 | 0x20 //| 0x80\r\n            | ((i & 0x01) ? 0x01 : 0)\r\n            | ((i & 0x02) ? 0x04 : 0)\r\n            | ((i & 0x04) ? 0x08 : 0)\r\n            | ((i & 0x08) ? 0x02 : 0)\r\n            | ((i & 0x10) ? 0x40 : 0)\r\n            //| ((i & 0x20) ? 0x20 : 0)\r\n            ;\r\n    }\r\n}\r\n\r\nword    Loop_Coleco()\r\n{\r\n    // Update sound cycle counter\r\n    Sound.CycleCounter += opt.Cur_IPeriod;\r\n\r\n    tsms.VDP_Line = (tsms.VDP_Line + 1) % g_machine.TV_lines;\r\n\r\n    // Debugger hook\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n    if (Debugger.active)\r\n        Debugger_RasterLine_Hook(tsms.VDP_Line);\r\n    #endif\r\n\r\n    if (tsms.VDP_Line == 0)\r\n    {\r\n        Interrupt_Loop_Misc_Line_Zero();\r\n    }\r\n\r\n    if (tsms.VDP_Line >= 0 && tsms.VDP_Line < 192)\r\n    {\r\n        // Skip collision check if the sprite collision flag is already set\r\n        if (!(sms.VDP_Status & VDP_STATUS_SpriteCollision))\r\n            Check_Sprites_Collision_Modes_1_2_3_Line (tsms.VDP_Line);\r\n    }\r\n\r\n    if (tsms.VDP_Line == 192)\r\n    {\r\n        if (Interrupt_Loop_Misc_Common())\r\n            Macro_Stop_CPU;\r\n        if (fskipper.Show_Current_Frame)\r\n            Refresh_Modes_0_1_2_3();\r\n\r\n        // sms.VDP_Status &= ~VDP_STATUS_SpriteCollision;\r\n        sms.VDP_Status |= VDP_STATUS_VBlank;\r\n        //if (!(sms.VDP_Status & VDP_STATUS_SpriteCollision))\r\n        //   Check_Sprites_Collision_Modes_1_2_3();\r\n\r\n        // Note: refresh screen may reset the system, so you can NOT change\r\n        // the status AFTER it, or else it would screw the newly emulated code\r\n        Video_RefreshScreen();\r\n        if ((opt.Force_Quit) || (CPU_Loop_Stop))\r\n            Macro_Stop_CPU;\r\n    }\r\n\r\n    if ((VBlank_ON) && (sms.VDP_Status & VDP_STATUS_VBlank) && (sms.Pending_NMI == FALSE) /* && (sms.VDP_Access_Mode == VDP_Access_Mode_1) */ )\r\n    {\r\n        sms.VDP_Status &= ~VDP_STATUS_VBlank;\r\n        sms.Pending_NMI = TRUE;\r\n        return (INT_NMI);\r\n    }\r\n\r\n    return (INT_NONE);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/coleco.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - coleco.h\n// Coleco Vision Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n// FIXME: use WRITE_FUNC from mappers.h\nvoid    Write_Mapper_Coleco(register word Addr, register byte Value);\n\nbyte    Coleco_Port_In(word Port);\nvoid    Coleco_Port_Out(word Port, byte Value);\n\nword    Loop_Coleco();\n\nvoid    Coleco_Init_Table_Inputs();\n\nbyte    Coleco_Inputs(word Port);\nbyte    Coleco_Keypad_1();\nbyte    Coleco_Keypad_2();\n\n//-----------------------------------------------------------------------------\n\n\n"
  },
  {
    "path": "meka/srcs/commport.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - commport.c\n// Gear-to-Gear Communication Port Emulation - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"commport.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_gear_to_gear  Gear_to_Gear;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n// [01]  R/W\n//       Bits 6 to 0: PC6 -> PC0\n//       Read/Write data when the EXT connector is used as 7-bit I/O port.\n\n// [02]  R/W\n//       Bit 7: NMI Enabled\n//         0: NMI are generated at the fall of PC6, 1: no NMI generated\n//         Note: the bit has to be re-set everytime to keep NMI enabled\n//       Bits 6 to 0: DirectionPC6 -> DirectionPC0\n//         0 = input, 1 = output\n\n// [03]  R/W\n//       Bits 7 to 0: TD7 -> TD0\n//       Used to send data during serial communication.\n\n// [04]  R\n//       Bits 7 to 0: RD7 -> RD0\n//       Used to receive data during serial communication\n\n// [05]  R/W\n//       Bits 7 to 6: BS1 -> BS0 (write only?)\n//         Baud rate setting\n//         00: 4800 Bds (default), 01: 2400 Bds, 10: 1200 Bds, 11: 300 Bds\n//       Bit 5: RON\n//         0: Receive disable, 1: Receive enable\n//         PC5 is forced to input mode (ignoring DPC5)\n//       Bit 4: TON\n//         0: Send disable, 1: Send enable\n//         PC4 is forced to output mode (ignoring DPC4)\n//       Bit 3: INT\n//         0: no NMI generated, 1: an NMI is generated when data is received\n//       Bit 2: FRER (read only)\n//         0: No framing error, 1: framing error\n//       Bit 1: RXRD (read only)\n//         0: Nothing received, 1: something has been received\n//       Bit 0: TXFL (read only)\n//         0: Data to send has been transfered, 1: not yet\n\n//-----------------------------------------------------------------------------\n\n// Reset emulated communication port\nvoid    Comm_Reset()\n{\n  Gear_to_Gear.Config = 0;\n  Gear_to_Gear.Data_Direction_NMIe = 0;\n  Gear_to_Gear.Data_01 = 0;\n}\n\nint     Comm_Read_01()\n{\n  return (Gear_to_Gear.Data_01 & 0x7F);\n}\n\nvoid    Comm_Write_01(int value)\n{\n  Gear_to_Gear.Config |= 1;                      // not yet sent (never sent!)\n  Gear_to_Gear.Data_01 = value & 0x7F;\n}\n\n// Read Data Direction and NMI Configuration\nint     Comm_Read_02()\n{\n  return (Gear_to_Gear.Data_Direction_NMIe);\n}\n\n// Write Data Direction and NMI Configuration\nvoid    Comm_Write_02(int value)\n{\n  Gear_to_Gear.Data_Direction_NMIe = value & 0xFF;\n}\n\n// Read Data During Serial Communication\nint     Comm_Read_03()\n{\n  return (0x00);\n}\n\n// Send Data During Serial Communication\nvoid    Comm_Write_03(int value)\n{\n  Gear_to_Gear.Config |= 1;                      // not yet sent (never sent!)\n /* Ignoring actual write */\n}\n\n// Receive Data During Serial Communications ----------------------------------\nint     Comm_Read_04()\n{\n  return (0x00);\n}\n\n// Configuration / Status byte ------------------------------------------------\nint     Comm_Read_05()\n{\n  byte t = Gear_to_Gear.Config;\n  // return (0);\n  Gear_to_Gear.Config &= 252; // 11111100\n  return (t);\n}\n\n// Configuration / Status byte ------------------------------------------------\nvoid    Comm_Write_05(int value)\n{\n  Gear_to_Gear.Config |= (value & /*0x38*/ 0xF8);\n  // 0x38 = 0x08 | 0x10 | 0x20\n  // 0xF8 = 0x08 | 0x10 | 0x20 | 0x40 | 0x80\n}\n\n//-----------------------------------------------------------------------------\n\n\n"
  },
  {
    "path": "meka/srcs/commport.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - commport.h\n// Gear-to-Gear Communication Port Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_gear_to_gear\n{\n byte           Config;\n byte           Data_01;\n byte           Data_Direction_NMIe;\n};\n\nextern t_gear_to_gear  Gear_to_Gear;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Comm_Reset();\n\nint     Comm_Read_01();\nint     Comm_Read_02();\nint     Comm_Read_03();\nint     Comm_Read_04();\nint     Comm_Read_05();\n\nvoid    Comm_Write_01(int value);\nvoid    Comm_Write_02(int value);\nvoid    Comm_Write_03(int value);\nvoid    Comm_Write_05(int value);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/config.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - config.h\r\n// Configuration File Load/Save - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"app_tileview.h\"\r\n#include \"blitintf.h\"\r\n#include \"capture.h\"\r\n#include \"config.h\"\r\n#include \"debugger.h\"\r\n#include \"fskipper.h\"\r\n#include \"glasses.h\"\r\n#include \"rapidfir.h\"\r\n#include \"video.h\"\r\n#include \"textbox.h\"\r\n#include \"tvtype.h\"\r\n#include \"libparse.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic FILE *       CFG_File;\r\n\r\nstatic void  CFG_Write_Line(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    vfprintf(CFG_File, fmt, args);\r\n    va_end(args);\r\n    fprintf(CFG_File, \"\\n\");\r\n}\r\nstatic void  CFG_Write_Int(const char *name, int value)\r\n{\r\n    fprintf(CFG_File, \"%s = %d\\n\", name, value);\r\n}\r\nstatic void  CFG_Write_Str(const char *name, const char *str)\r\n{\r\n    fprintf(CFG_File, \"%s = %s\\n\", name, str);\r\n}\r\n\r\nstatic void  CFG_Write_StrEscape (const char *name, const char *str)\r\n{\r\n    char *str_escaped = parse_escape_string(str, NULL);\r\n    if (str_escaped)\r\n    {\r\n        fprintf(CFG_File, \"%s = %s\\n\", name, str_escaped);\r\n        free(str_escaped);\r\n    }\r\n    else\r\n    {\r\n        fprintf(CFG_File, \"%s = %s\\n\", name, str);\r\n    }\r\n}\r\n\r\nstatic void     Font_FindByName(const char* name, int* out)\r\n{\r\n    for (int i = 0; i < FONTID_COUNT_; i++)\r\n    {\r\n        if (stricmp(name, Fonts[i].text_id) == 0)\r\n        {\r\n            *out = (int)Fonts[i].id;\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\n// Handle a variable assignment during configuration file loading\r\nstatic void     Configuration_Load_Line (char *var, char *value)\r\n{\r\n    StrLower(var);\r\n\r\n    // All input is changed to lower case for easier compare (apart from 'last_directory')\r\n    if (strcmp(var, \"last_directory\") != 0)\r\n        StrLower(value);\r\n\r\n    // Select\r\n    if (!strcmp(var, \"frameskip_mode\"))                 { fskipper.Mode = !strcmp(value, \"unthrottled\") ? FRAMESKIP_MODE_UNTHROTTLED : FRAMESKIP_MODE_THROTTLED; return; }\r\n    if (!strcmp(var, \"frameskip_throttle_speed\"))       { fskipper.Throttled_Speed = atoi(value); return; }\r\n    if (!strcmp(var, \"frameskip_unthrottled_frameskip\")){ fskipper.Unthrottled_Frameskip = atoi(value); return; }\r\n    if (!strcmp(var, \"video_game_blitter\"))             { Blitters.blitter_configuration_name = strdup(value); return; }\r\n    if (!strcmp(var, \"sound_enabled\"))                  { Sound.Enabled = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"sound_rate\"))                     { const int n = atoi(value); if (n > 0) Sound.SampleRate = atoi(value); return; }\r\n    if (!strcmp(var, \"video_gui_resolution\"))\r\n    {\r\n        int x, y;\r\n        if (sscanf(value, \"%dx%d\", &x, &y) == 2)\r\n        {\r\n            g_config.video_mode_gui_res_x = x;\r\n            g_config.video_mode_gui_res_y = y;\r\n        }\r\n        return;\r\n    }\r\n    if (!strcmp(var, \"video_gui_vsync\"))                { g_config.video_mode_gui_vsync = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"start_in_gui\"))                   { g_config.start_in_gui = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"theme\"))                          { Skins_SetSkinConfiguration(value); return; }\r\n    if (!strcmp(var, \"game_window_scale\"))              { g_config.game_window_scale = atof(value); if (g_config.game_window_scale < 0) g_config.game_window_scale = 1.0f; return; }\r\n    if (!strcmp(var, \"fb_uses_db\"))                     { g_config.fb_uses_DB = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"fb_close_after_load\"))            { g_config.fb_close_after_load = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"fb_fullscreen_after_load\"))       { g_config.fullscreen_after_load = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"last_directory\"))                 { snprintf(FB.current_directory, FILENAME_LEN, \"%s\", value); return; }\r\n    if (!strcmp(var, \"bios_logo\"))                      { g_config.enable_BIOS = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"rapidfire\"))                      { RapidFire = atoi(value); return; }\r\n    if (!strcmp(var, \"country\"))                        { if (!strcmp(value, \"jp\")) g_config.country = COUNTRY_JAPAN; else g_config.country = COUNTRY_EXPORT; return; }\r\n    if (!strcmp(var, \"tv_type\"))\r\n    {\r\n        if (strcmp(value, \"ntsc\") == 0)\r\n            TV_Type_User = &TV_Type_Table[TVTYPE_NTSC];\r\n        else\r\n            if (strcmp(value, \"pal\") == 0 || strcmp(value, \"secam\") || strcmp(value, \"pal/secam\"))\r\n                TV_Type_User = &TV_Type_Table[TVTYPE_PAL_SECAM];\r\n        TVType_Update_Values();\r\n        return;\r\n    }\r\n    if (!strcmp(var, \"show_product_number\"))            { g_config.show_product_number = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"show_messages_fullscreen\"))       { g_config.show_fullscreen_messages = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"screenshot_template\"))\r\n    {\r\n        // Note: Obsolete variable name, see below\r\n        StrReplace(value, '*', ' ');\r\n        g_config.capture_filename_template = strdup(value);\r\n        return;\r\n    }\r\n    if (!strcmp(var, \"screenshots_filename_template\"))  { g_config.capture_filename_template = strdup(value); return; }\r\n    if (!strcmp(var, \"screenshots_crop_align_8x8\"))     { g_config.capture_crop_align_8x8 = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"3dglasses_mode\"))                 { Glasses_Set_Mode(atoi(value)); return; }\r\n    if (!strcmp(var, \"3dglasses_com_port\"))             { Glasses_Set_ComPort(atoi(value)); return; }\r\n    if (!strcmp(var, \"iperiod\"))                        { opt.IPeriod = atoi(value); return; }\r\n    if (!strcmp(var, \"iperiod_coleco\"))                 { opt.IPeriod_Coleco = atoi(value); return; }\r\n    if (!strcmp(var, \"iperiod_sg1000_sc3000\"))          { opt.IPeriod_Sg1000_Sc3000 = atoi(value); return; }\r\n    if (!strcmp(var, \"nes_sucks\"))                      { if (atoi(value) < 1) Quit_Msg(\"\\n%s\", Msg_Get(MSG_NES_Sucks)); return; }\r\n    if (!strcmp(var, \"sprite_flickering\"))\r\n    {\r\n        if (strcmp(value, \"auto\") == 0)\r\n            g_config.sprite_flickering = SPRITE_FLICKERING_AUTO;\r\n        else if (strcmp(value, \"yes\") == 0)\r\n            g_config.sprite_flickering = SPRITE_FLICKERING_ENABLED;\r\n        else if (strcmp(value, \"no\") == 0)\r\n            g_config.sprite_flickering = SPRITE_FLICKERING_NO;\r\n        return;\r\n    }\r\n    if (!strcmp(var, \"language\"))                       { Lang_Set_by_Name(value); return; }\r\n    if (!strcmp(var, \"music_wav_filename_template\"))    { Sound.LogWav_FileName_Template = strdup(value); return; }\r\n    if (!strcmp(var, \"music_vgm_filename_template\"))    { Sound.LogVGM_FileName_Template = strdup(value); return; }\r\n    if (!strcmp(var, \"music_vgm_log_accuracy\"))\r\n    {\r\n        if (strcmp(value, \"frame\") == 0)\r\n            Sound.LogVGM_Logging_Accuracy = VGM_LOGGING_ACCURACY_FRAME;\r\n        else if (strcmp(value, \"sample\") == 0)\r\n            Sound.LogVGM_Logging_Accuracy = VGM_LOGGING_ACCURACY_SAMPLE;\r\n        return;\r\n    }\r\n    if (!strcmp(var, \"fm_enabled\"))                     { Sound.FM_Enabled = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"video_gui_refresh_rate\"))\r\n    {\r\n        if (!strcmp(value, \"auto\"))\r\n            g_config.video_mode_gui_refresh_rate = 0;\r\n        else\r\n            g_config.video_mode_gui_refresh_rate = atoi(value);\r\n        return;\r\n    }\r\n    if (!strcmp(var, \"allow_opposite_directions\"))      { g_config.allow_opposite_directions = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"debugger_disassembly_display_labels\")) { g_config.debugger_disassembly_display_labels = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"debugger_log\"))                   { g_config.debugger_log_enabled = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"memory_editor_lines\"))            { g_config.memory_editor_lines = MAX(1, atoi(value)); return; }\r\n    if (!strcmp(var, \"memory_editor_columns\"))          { g_config.memory_editor_columns = MAX(1, atoi(value)); return; }\r\n    if (!strcmp(var, \"video_game_vsync\"))               { g_config.video_mode_game_vsync = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"screenshots_crop_scrolling_column\")) { g_config.capture_crop_scrolling_column = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"screenshots_include_gui\"))        { g_config.capture_include_gui = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"video_fullscreen\"))               { g_config.video_fullscreen = (bool)atoi(value); return; }\r\n    if (!strcmp(var, \"video_driver\"))                   { g_config.video_driver = VideoDriver_FindByName(value); return; }\r\n\r\n    // Fonts\r\n    if (!strcmp(var, (\"font_menus\")))           { Font_FindByName(value, &g_config.font_menus); }\r\n    if (!strcmp(var, (\"font_messages\")))        { Font_FindByName(value, &g_config.font_messages); }\r\n    if (!strcmp(var, (\"font_options\")))         { Font_FindByName(value, &g_config.font_options); }\r\n    if (!strcmp(var, (\"font_debugger\")))        { Font_FindByName(value, &g_config.font_debugger); }\r\n    if (!strcmp(var, (\"font_documentation\")))   { Font_FindByName(value, &g_config.font_documentation); }\r\n    if (!strcmp(var, (\"font_techinfo\")))        { Font_FindByName(value, &g_config.font_techinfo); }\r\n    if (!strcmp(var, (\"font_filebrowser\")))     { Font_FindByName(value, &g_config.font_filebrowser); }\r\n    if (!strcmp(var, (\"font_about\")))           { Font_FindByName(value, &g_config.font_about); }\r\n\r\n    // Obsolete variables\r\n    if (!strcmp(var, \"fm_emulator\"))            {}\r\n    if (!strcmp(var, \"opl_speed\"))              {}\r\n    if (!strcmp(var, \"gui_video_depth\"))        {}\r\n    if (!strcmp(var, \"gui_video_driver\"))       {}\r\n    if (!strcmp(var, \"mario_is_a_fat_plumber\")) {}\r\n    if (!strcmp(var, \"video_game_depth\"))       {}\r\n    if (!strcmp(var, \"frameskip_auto_speed\"))   {}\r\n    if (!strcmp(var, \"frameskip_normal_speed\")) {}\r\n    if (!strcmp(var, \"sound_card\"))             {}\r\n    if (!strcmp(var, \"video_game_triple_buffering\"))    {}\r\n    if (!strcmp(var, \"video_game_page_flipping\"))       {}\r\n}\r\n\r\n// Load configuration file data from MEKA.CFG\r\nvoid Configuration_Load()\r\n{\r\n    ConsolePrintf(Msg_Get(MSG_Config_Loading), g_env.Paths.ConfigurationFile);\r\n\r\n    // Open and read file\r\n    t_tfile *  tf;\r\n    if ((tf = tfile_read(g_env.Paths.ConfigurationFile)) == NULL)\r\n    {\r\n        ConsolePrintf(\"%s\\n\", meka_strerror());\r\n        opt.Setup_Interactive_Execute = true;\r\n        return;\r\n    }\r\n    ConsolePrint(\"\\n\");\r\n\r\n    // Parse each line\r\n    int line_cnt = 0;\r\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        line_cnt += 1;\r\n\r\n        char* line = (char*)lines->elem;\r\n        if (StrIsNull(line))\r\n            continue;\r\n\r\n        char variable[256], val[256];\r\n        if (parse_getword(variable, sizeof(variable), &line, \"=\", ';', PARSE_FLAGS_NONE))\r\n        {\r\n            parse_skip_spaces(&line);\r\n            if (parse_getword(val, sizeof(val), &line, \"\", ';', PARSE_FLAGS_NONE))\r\n                Configuration_Load_Line(variable, val);\r\n        }\r\n    }\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n\r\n    g_config.loaded_configuration_file = true;\r\n}\r\n\r\n// Save configuration file data to MEKA.CFG\r\nvoid Configuration_Save()\r\n{\r\n    char   s1 [256];\r\n\r\n    if (!(CFG_File = fopen(g_env.Paths.ConfigurationFile, \"wt\")))\r\n        return;\r\n\r\n    CFG_Write_Line (\";\");\r\n    CFG_Write_Line (\"; \" MEKA_NAME \" \" MEKA_VERSION \" - Configuration File\");\r\n    CFG_Write_Line (\";\");\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line ( \"-----< FRAME SKIPPING >-----------------------------------------------------\");\r\n    if (fskipper.Mode == FRAMESKIP_MODE_THROTTLED)\r\n        CFG_Write_Line  (\"frameskip_mode = throttled\");\r\n    else\r\n        CFG_Write_Line  (\"frameskip_mode = unthrottled\");\r\n    CFG_Write_Int  (\"frameskip_throttle_speed\", fskipper.Throttled_Speed);\r\n    CFG_Write_Int  (\"frameskip_unthrottled_frameskip\", fskipper.Unthrottled_Frameskip);\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line ( \"-----< VIDEO >--------------------------------------------------------------\");\r\n    CFG_Write_Str  (\"video_driver\", g_config.video_driver->name);\r\n    CFG_Write_Line (\"(Available video drivers: opengl, directx)\");\r\n    CFG_Write_Int  (\"video_fullscreen\", g_config.video_fullscreen);\r\n\r\n    CFG_Write_StrEscape(\"video_game_blitter\", Blitters.current->name);\r\n    CFG_Write_Line (\"(See MEKA.BLT file to configure blitters/fullscreen modes)\");\r\n    CFG_Write_Int  (\"video_game_vsync\", g_config.video_mode_game_vsync);\r\n\r\n    sprintf        (s1, \"%dx%d\", g_config.video_mode_gui_res_x, g_config.video_mode_gui_res_y);\r\n    CFG_Write_Str  (\"video_gui_resolution\", s1);\r\n    if (g_config.video_mode_gui_refresh_rate == 0)\r\n        CFG_Write_Str (\"video_gui_refresh_rate\", \"auto\");\r\n    else\r\n        CFG_Write_Int (\"video_gui_refresh_rate\", g_config.video_mode_gui_refresh_rate);\r\n    CFG_Write_Line (\"(Video mode refresh rate. Set 'auto' for default rate. Not all drivers\");\r\n    CFG_Write_Line (\" support non-default rate. Customized values then depends on your video\");\r\n    CFG_Write_Line (\" card and monitor. Setting to 60 (Hz) is usually a good thing as the screen\");\r\n    CFG_Write_Line (\" will be refreshed at the same time as the emulated systems.)\");\r\n    CFG_Write_Int  (\"video_gui_vsync\", g_config.video_mode_gui_vsync);\r\n    CFG_Write_Line (\"(enable vertical synchronisation for fast computers)\");\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< INPUTS >--------------------------------------------------------------\");\r\n    CFG_Write_Line (\"(See MEKA.INP file to configure inputs sources)\");\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< SOUND AND MUSIC >-----------------------------------------------------\");\r\n    CFG_Write_Int  (\"sound_enabled\", Sound.Enabled);\r\n    CFG_Write_Int  (\"sound_rate\", Sound.SampleRate);\r\n    CFG_Write_Int  (\"fm_enabled\", Sound.FM_Enabled);\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< GRAPHICAL USER INTERFACE CONFIGURATION >------------------------------\");\r\n    CFG_Write_Int  (\"start_in_gui\", g_config.start_in_gui);\r\n    CFG_Write_StrEscape(\"theme\", Skins_GetCurrentSkin()->name);\r\n    fprintf(CFG_File, \"game_window_scale = %.2f\\n\", g_config.game_window_scale);\r\n    CFG_Write_Int  (\"fb_uses_db\", g_config.fb_uses_DB);\r\n    CFG_Write_Int  (\"fb_close_after_load\", g_config.fb_close_after_load);\r\n    CFG_Write_Int  (\"fb_fullscreen_after_load\", g_config.fullscreen_after_load);\r\n    CFG_Write_StrEscape  (\"last_directory\", FB.current_directory);\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< MISCELLANEOUS OPTIONS >-----------------------------------------------\");\r\n    CFG_Write_StrEscape  (\"language\", Messages.Lang_Cur->Name);\r\n    CFG_Write_Int  (\"bios_logo\", g_config.enable_BIOS);\r\n    CFG_Write_Int  (\"rapidfire\", RapidFire);\r\n    CFG_Write_Str  (\"country\", (g_config.country == COUNTRY_EXPORT) ? \"us/eu\" : \"jp\");\r\n    CFG_Write_Line (\"(emulated machine country, either 'us/eu' or 'jp'\");\r\n    if (g_config.sprite_flickering & SPRITE_FLICKERING_AUTO)\r\n        CFG_Write_Line (\"sprite_flickering = auto\");\r\n    else\r\n        CFG_Write_Str (\"sprite_flickering\", (g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED) ? \"yes\" : \"no\");\r\n    CFG_Write_Line (\"(hardware sprite flickering emulator, either 'yes', 'no', or 'auto'\");\r\n    CFG_Write_Str  (\"tv_type\", (TV_Type_User->id == TVTYPE_NTSC) ? \"ntsc\" : \"pal/secam\");\r\n    CFG_Write_Line (\"(emulated TV type, either 'ntsc' or 'pal/secam'\");\r\n    //CFG_Write_Int  (\"tv_snow_effect\", effects.TV_Enabled);\r\n    //CFG_Write_Str  (\"palette\", (g_config.palette_type == PALETTE_TYPE_MUTED) ? \"muted\" : \"bright\");\r\n    //CFG_Write_Line (\"(palette type, either 'muted' or 'bright'\");\r\n    CFG_Write_Int  (\"show_product_number\", g_config.show_product_number);\r\n    CFG_Write_Int  (\"show_messages_fullscreen\", g_config.show_fullscreen_messages);\r\n    CFG_Write_Int  (\"allow_opposite_directions\", g_config.allow_opposite_directions);\r\n    CFG_Write_StrEscape  (\"screenshots_filename_template\", g_config.capture_filename_template);\r\n    CFG_Write_Int  (\"screenshots_crop_scrolling_column\", g_config.capture_crop_scrolling_column);\r\n    CFG_Write_Int  (\"screenshots_crop_align_8x8\", g_config.capture_crop_align_8x8);\r\n    CFG_Write_Int  (\"screenshots_include_gui\", g_config.capture_include_gui);\r\n    CFG_Write_StrEscape  (\"music_wav_filename_template\", Sound.LogWav_FileName_Template);\r\n    CFG_Write_StrEscape  (\"music_vgm_filename_template\", Sound.LogVGM_FileName_Template);\r\n    CFG_Write_Line (\"(see documentation for more information about templates)\");\r\n    CFG_Write_Str  (\"music_vgm_log_accuracy\", (Sound.LogVGM_Logging_Accuracy == VGM_LOGGING_ACCURACY_FRAME) ? \"frame\" : \"sample\");\r\n    CFG_Write_Line (\"(either 'frame' or 'sample')\");\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< FONTS >---------------------------------------------------------------\");\r\n    CFG_Write_Line (\"( available fonts:\");\r\n    for (int i = 0; i < FONTID_COUNT_; i++)\r\n        CFG_Write_Line(\"  - %s, %d px%s\", Fonts[i].text_id, Fonts[i].height, i+1==FONTID_COUNT_ ? \" )\" : \"\");\r\n    CFG_Write_Str  (\"font_menus\",           Fonts[g_config.font_menus].text_id);\r\n    CFG_Write_Str  (\"font_messages\",        Fonts[g_config.font_messages].text_id);\r\n    CFG_Write_Str  (\"font_options\",         Fonts[g_config.font_options].text_id);\r\n    CFG_Write_Str  (\"font_debugger\",        Fonts[g_config.font_debugger].text_id);\r\n    CFG_Write_Str  (\"font_documentation\",   Fonts[g_config.font_documentation].text_id);\r\n    CFG_Write_Str  (\"font_techinfo\",        Fonts[g_config.font_techinfo].text_id);\r\n    CFG_Write_Str  (\"font_filebrowser\",     Fonts[g_config.font_filebrowser].text_id);\r\n    CFG_Write_Str  (\"font_about\",           Fonts[g_config.font_about].text_id);\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< 3-D GLASSES EMULATION >-----------------------------------------------\");\r\n    CFG_Write_Int  (\"3dglasses_mode\", Glasses.Mode);\r\n    CFG_Write_Line (\"('0' = show both sides and become blind)\");\r\n    CFG_Write_Line (\"('1' = play without 3-D Glasses, show only left side)\");\r\n    CFG_Write_Line (\"('2' = play without 3-D Glasses, show only right side)\");\r\n    CFG_Write_Line (\"('3' = uses real 3-D Glasses connected to COM port)\");\r\n    // if (Glasses_Mode == GLASSES_MODE_COM_PORT)\r\n    {\r\n        CFG_Write_Int  (\"3dglasses_com_port\", Glasses.ComPort);\r\n        CFG_Write_Line (\"(this is on which COM port the Glasses are connected. Either 1 or 2)\");\r\n    }\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< EMULATION OPTIONS >---------------------------------------------------\");\r\n    CFG_Write_Int  (\"iperiod\", opt.IPeriod);\r\n    CFG_Write_Int  (\"iperiod_coleco\", opt.IPeriod_Coleco);\r\n    CFG_Write_Int  (\"iperiod_sg1000_sc3000\", opt.IPeriod_Sg1000_Sc3000);\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< DEBUGGING FUNCTIONNALITIES -------------------------------------------\");\r\n    CFG_Write_Int  (\"debugger_disassembly_display_labels\", g_config.debugger_disassembly_display_labels);\r\n    CFG_Write_Int  (\"debugger_log\", g_config.debugger_log_enabled);\r\n    CFG_Write_Int  (\"memory_editor_lines\", g_config.memory_editor_lines);\r\n    CFG_Write_Int  (\"memory_editor_columns\", g_config.memory_editor_columns);\r\n    CFG_Write_Line (\"(preferably make columns a multiple of 8)\");\r\n    CFG_Write_Line (\"\");\r\n\r\n    CFG_Write_Line (\"-----< FACTS >---------------------------------------------------------------\");\r\n    CFG_Write_Line (\"nes_sucks = 1\");\r\n\r\n    fclose (CFG_File);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     Param_Check(int *current, const char *msg)\r\n{\r\n    if ((*current) + 1 >= g_env.argc)\r\n        Quit_Msg(\"%s\", msg);\r\n    (*current)++;\r\n}\r\n\r\nvoid    Command_Line_Parse()\r\n{\r\n    const char* params[] =\r\n    {\r\n        \"HELP\", \"?\",\r\n        \"NOELEPHANT\", \"LOG\", \"LOAD\",\r\n        \"SETUP\",\r\n        \"DEBUG_INFOS\",\r\n        NULL\r\n    };\r\n\r\n    for (int i = 1; i != g_env.argc; i++)\r\n    {\r\n        const char *s = g_env.argv[i];\r\n        if (s[0] == '-'\r\n#if defined(ARCH_WIN32)\r\n            || s[0] == '/'\r\n#endif\r\n            )\r\n        {\r\n            int j;\r\n            for (j = 0; params[j]; j++)\r\n                if (!stricmp (s + 1, params[j]))\r\n                    break;\r\n            switch (j)\r\n            {\r\n            case 0: // HELP\r\n            case 1: Command_Line_Help();\r\n                break;\r\n            case 2: // NOELEPHANT\r\n                break;\r\n            case 3: // LOG\r\n                Param_Check(&i, Msg_Get(MSG_Log_Need_Param));\r\n                TB_Message.log_filename = strdup(g_env.argv[i]);\r\n                break;\r\n            case 4: // LOAD\r\n                Param_Check(&i, Msg_Get(MSG_Load_Need_Param));\r\n                opt.State_Load = atoi(g_env.argv[i]);\r\n                break;\r\n            case 5: // SETUP\r\n                opt.Setup_Interactive_Execute = true;\r\n                break;\r\n                // Private Usage\r\n            case 6: // DEBUG_INFOS\r\n                g_env.debug_dump_infos = true;\r\n                if (TB_Message.log_filename == NULL)\r\n                    TB_Message.log_filename = strdup(\"debuglog.txt\");\r\n                break;\r\n            default:\r\n                ConsolePrintf(Msg_Get(MSG_Error_Param), s);\r\n                ConsolePrint(\"\\n--\\n\");\r\n                Command_Line_Help();\r\n                return;\r\n            }\r\n        }\r\n        else\r\n        {\r\n            // FIXME: specifying more than one ROM ?\r\n            if (s[0] == '/' || s[0] == '\\\\' || (isalpha(s[0]) && s[1] == ':'))\r\n                strcpy(g_env.Paths.MediaImageFile, s);\r\n            else\r\n                sprintf(g_env.Paths.MediaImageFile, \"%s/%s\", g_env.Paths.StartingDirectory, s);\r\n            //MessageBox(NULL, s, s, 0);\r\n        }\r\n    }\r\n}\r\n\r\nvoid    Command_Line_Help()\r\n{\r\n    // Note: this help screen is not localized.\r\n    Quit_Msg(\r\n        #ifdef ARCH_WIN32\r\n        \"Syntax: MEKAW [rom] [options] ...\\n\"\r\n        #else\r\n        \"Syntax: MEKA [rom] [option1] ...\\n\"\r\n        #endif\r\n        \"\"                                                                   \"\\n\" \\\r\n        \"Where [rom] is a valid rom image to load. Available options are:\"   \"\\n\" \\\r\n        \"\"                                                                   \"\\n\" \\\r\n        \"  -HELP -?         : Display command line help\"                     \"\\n\" \\\r\n        \"  -SETUP           : Start with the setup screen\"                   \"\\n\" \\\r\n        \"  -EURO -US        : Emulate an European/US system for this session\"\"\\n\" \\\r\n        \"  -JAP -JP -JPN    : Emulate a Japanese system for this session\"    \"\\n\" \\\r\n        \"  -DEBUG           : Enable debugging features\"                     \"\\n\" \\\r\n        \"  -LOAD <n>        : Load savestate <n> on startup\"                 \"\\n\" \\\r\n        \"  -LOG <file>      : Log message to file <file> (appending it)\"     \"\\n\" \\\r\n        \"  -NOELEPHANT      : Just what it says\"                             \"\\n\"\r\n        );\r\n    //   \"  -NIRV            : Speed up emulation dramatically\"          \"\\n\"\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/config.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - config.h\r\n// Configuration File Load/Save - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Configuration_Load();\r\nvoid    Configuration_Save();\r\n\r\nvoid    Command_Line_Parse();\r\nvoid    Command_Line_Help();\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/country.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - country.c\n// Country / Nationalization - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"app_filebrowser.h\"\n#include \"app_game.h\"\n#include \"vmachine.h\"\n\n//-----------------------------------------------------------------------------\n\n// Also see stuff in CONFIG.C\n// Note that country handling is quite weird because:\n\n// If you have country in EUR/US mode, for example, and start\n// Meka with /JAP it will run in JAP mode, but will keep your\n// configuration in EUR/US unless you manually click on JAP.\n// This is very useful, user wise.\n// And that's the reason for _CL (CommandLine) stuff, too.\n\n//-----------------------------------------------------------------------------\n\nvoid    Set_Country_Export()\n{\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Country_European_US));\n    if (g_machine_flags & MACHINE_POWER_ON)\n        Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Must_Reset));\n    g_config.country = COUNTRY_EXPORT;\n    gui_menu_uncheck_all(menus_ID.region);\n    gui_menu_check(menus_ID.region, 0);\n\n    // Set emulation country\n    sms.Country = g_config.country;\n\n    // Update game boxes name and file browser\n    gamebox_rename_all();\n    FB_Reload_Names();\n}\n\nvoid    Set_Country_Japan()\n{\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Country_JAP));\n    if (g_machine_flags & MACHINE_POWER_ON)\n        Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Must_Reset));\n    g_config.country = COUNTRY_JAPAN;\n    gui_menu_uncheck_all (menus_ID.region);\n    gui_menu_check (menus_ID.region, 1);\n\n    // Set emulation country\n    sms.Country = g_config.country;\n\n    // Update game boxes name and file browser\n    gamebox_rename_all();\n    FB_Reload_Names();\n}\n\nvoid    Nationalize (byte *v)\n{\n    if (sms.Country == COUNTRY_EXPORT)\n        if ((tsms.Port3F & 0xF) == 0x5)\n        {\n            if ((tsms.Port3F & 0xF0) == 0xF0)\n            {\n                *v |= 0xC0; // set bits 6 and 7\n            }\n            else\n            {\n                *v &= 0x3F; // clear bits 6 and 7\n            }\n        }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/country.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - country.h\n// Country / Nationalization - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\nenum t_country\n{\n    COUNTRY_EXPORT      = 0,\n    COUNTRY_JAPAN       = 1,\n    COUNTRY_AUTO        = 2,\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid            Nationalize             (u8* v);\nvoid            Set_Country_Export      ();\nvoid            Set_Country_Japan       ();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/cpu.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - cpu.c\r\n// CPU related things (ports, memory accesses, interrupts) - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"inputs_t.h\"\r\n#include \"patch.h\"\r\n#include \"vdp.h\"\r\n#include \"video.h\"\r\n#include \"video_m2.h\"\r\n#include \"video_m5.h\"\r\n#include \"debugger.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nint     CPU_Loop_Stop;  // Set to break from CPU emulation and return to mainloop()\r\nint     CPU_ForceNMI;   // Set to force a NMI (currently only supported by the SG-1000/SC-3000 loop handlers)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Note: only MARAT_Z80 is functional/compiles now.\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid Interrupt_Loop_Misc_Line_Zero()\r\n{\r\n    if (tsms.VDP_Video_Change)\r\n        VDP_VideoMode_Change();\r\n    if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_SAMPLE)\r\n        VGM_NewFrame(&Sound.LogVGM); // For sample accurate, we want to reset its state on line 0\r\n    Patches_MEM_Apply();\r\n}\r\n\r\nbool Interrupt_Loop_Misc_Common()\r\n{\r\n    if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_FRAME)\r\n        VGM_NewFrame(&Sound.LogVGM); // For frame accurate, we want to consolidate data at the VBlank point\r\n    Sound_Update();\r\n    tsms.Control_Check_GUI = TRUE;\r\n    Inputs_Sources_Update(); // Poll input sources\r\n    Inputs_Emulation_Update(TRUE); // Might disable Control_Check_GUI\r\n    Inputs_Check_GUI(!tsms.Control_Check_GUI);\r\n    if ((opt.Force_Quit) || (CPU_Loop_Stop))\r\n    {\r\n        /*tsms.VDP_Line --;*/ // Not sure about its usefulness\r\n        return true; // -> will call Macro_Stop_CPU\r\n    }\r\n    return false;\r\n}\r\n\r\nbool Interrupt_Loop_Misc(int* out_interrupt)\r\n{\r\n    bool stop = Interrupt_Loop_Misc_Common();\r\n    if (Inputs.SK1100_Enabled)\r\n    {\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_SCROLLLOCK))\r\n            *out_interrupt = INT_NMI;\r\n    }\r\n    else if ((tsms.Control_Start_Pause == 1) && (g_driver->id != DRV_GG))\r\n    {\r\n        tsms.Control_Start_Pause = 2;\r\n        *out_interrupt = INT_NMI;\r\n    }\r\n    return stop;\r\n}\r\n\r\n// Z80 scanline handler\r\nword    Loop_SMS()\r\n{\r\n    int interrupt = INT_NONE;\r\n\r\n    tsms.VDP_Line = (tsms.VDP_Line + 1) % g_machine.TV_lines;\r\n    // Debugger hook\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n        if (Debugger.active)\r\n            Debugger_RasterLine_Hook(tsms.VDP_Line);\r\n    #endif\r\n\r\n    // Update sound cycle counter0\r\n    Sound.CycleCounter += opt.Cur_IPeriod;\r\n\r\n    if (tsms.VDP_Line == 0)\r\n    {\r\n        Interrupt_Loop_Misc_Line_Zero();\r\n        g_machine.VDP.scroll_x_latched = sms.VDP[8];\r\n        g_machine.VDP.scroll_y_latched = sms.VDP[9];\r\n        sms.Lines_Left = sms.VDP [10];\r\n    }\r\n\r\n    // Screen Refresh\r\n    if (tsms.VDP_Line >= g_driver->y_show_start && tsms.VDP_Line <= g_driver->y_show_end)\r\n    {\r\n        g_machine.VDP.scroll_x_latched_table[tsms.VDP_Line] = g_machine.VDP.scroll_x_latched;\r\n        if (tsms.VDP_VideoMode > 3)\r\n            Refresh_Line_5();\r\n        g_machine.VDP.scroll_x_latched = sms.VDP[8];\r\n        if (g_driver->vdp == VDP_TMS9918)\r\n            Check_Sprites_Collision_Modes_1_2_3_Line (tsms.VDP_Line);\r\n        if (tsms.VDP_Line == g_driver->y_show_end)\r\n        {\r\n            //if (g_driver->vdp == VDP_TMS)\r\n            //   Check_Sprites_Collision_Modes_1_2_3();\r\n            // Msg(MSGT_DEBUG, \"Loop_SMS: Video_RefreshScreen()\");\r\n            Video_RefreshScreen();\r\n            if ((opt.Force_Quit) || (CPU_Loop_Stop))\r\n                Macro_Stop_CPU;\r\n        }\r\n    }\r\n\r\n    if (tsms.VDP_Line <= g_driver->y_int)\r\n    {\r\n        if (sms.Lines_Left -- <= 0)\r\n        {\r\n            sms.Lines_Left = sms.VDP [10];\r\n            sms.Pending_HBlank = TRUE;\r\n            #ifdef DEBUG_VDP\r\n                Msg(MSGT_DEBUG, \"%d @ Lines_Left == 0, HBlank == %d, Reloading VDP[10] = %d\", tsms.VDP_Line, (HBlank_ON) ? 1 : 0, sms.VDP [10]);\r\n            #endif\r\n        }\r\n        if ((sms.Pending_HBlank) && (HBlank_ON))\r\n            interrupt = INT_IRQ;\r\n    }\r\n    else\r\n#if 1\r\n    {\r\n        // --------------------------------------------------------------------------\r\n        // New interrupt code\r\n        // --------------------------------------------------------------------------\r\n        // FIXME: Needless to say, this is vastly incorrect but has given pretty\r\n        // good result so far.\r\n        // --------------------------------------------------------------------------\r\n        if (tsms.VDP_Line == g_driver->y_int + 1)\r\n            sms.VDP_Status |= VDP_STATUS_VBlank;\r\n        else if (tsms.VDP_Line > g_driver->y_int && tsms.VDP_Line <= (g_driver->y_int + 32) && (sms.VDP_Status & VDP_STATUS_VBlank) && (VBlank_ON))\r\n            interrupt = INT_IRQ;\r\n        else if (tsms.VDP_Line == g_driver->y_int + 33)   // Interruption duration. Isn't that scary-lame?\r\n            if (Interrupt_Loop_Misc(&interrupt))\r\n                Macro_Stop_CPU;\r\n    }\r\n#else\r\n        // --------------------------------------------------------------------------\r\n        // Original interrupt code\r\n        // --------------------------------------------------------------------------\r\n    {\r\n        if (tsms.VDP_Line == 193)\r\n            sms.VDP_Status |= VDP_STATUS_VBlank;\r\n        else if (tsms.VDP_Line <= 224 && (sms.VDP_Status & 0x80) && (VBlank_ON))\r\n            interrupt = INT_IRQ;\r\n        else if (tsms.VDP_Line == 225)\r\n            if (Interrupt_Loop_Misc(&interrupt))\r\n                Macro_Stop_CPU;\r\n    }\r\n#endif\r\n    // ----------------------------------------------------------------------------\r\n    if (interrupt == INT_IRQ)\r\n    {\r\n        #ifdef MARAT_Z80\r\n            sms.R.IRequest = INT_IRQ;\r\n        #elif MAME_Z80\r\n            z80_set_irq_line (0, ASSERT_LINE);\r\n        #endif\r\n    }\r\n\r\n    return (interrupt);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef MAME_Z80\r\n// MAIN EMULATION LOOP (MAME CORE) --------------------------------------------\r\nvoid    CPU_Loop()\r\n{\r\n    for (;;)\r\n    {\r\n        z80_execute (opt.Cur_IPeriod);\r\n        switch (LoopZ80 ())\r\n        {\r\n        case INT_IRQ: break;\r\n        case INT_NMI: z80_set_nmi_line (ASSERT_LINE); z80_set_nmi_line (CLEAR_LINE); break;\r\n        case INT_QUIT: return;\r\n        }\r\n    }\r\n    /* z80_stop_emulating(); */\r\n}\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef RAZE_Z80\r\n// MAIN EMULATION LOOP (RAZE CORE) --------------------------------------------\r\nvoid    CPU_Loop()\r\n{\r\n    for (;;)\r\n    {\r\n        z80_emulate (opt.Cur_IPeriod);\r\n        switch (LoopZ80 ())\r\n        {\r\n        case INT_IRQ: z80_raise_IRQ (0xff); z80_lower_IRQ(); break;\r\n        case INT_NMI: z80_cause_NMI(); break;\r\n        case INT_QUIT: return;\r\n        }\r\n    }\r\n}\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Empty/Defaults Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef MARAT_Z80\r\n    void  PatchZ80(Z80 *R) { }\r\n#endif\r\n\r\n#ifdef MAME_Z80\r\n    INLINE int Get_Active_CPU()         { return (0);    }\r\n    INLINE int Get_IRQ_Vector(int p)    { return (0x38); }\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/cpu.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - cpu.h\r\n// CPU related things (ports, memory accesses, interrupts) - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nextern int     CPU_Loop_Stop;  // Set to break from CPU emulation and return to mainloop()\r\nextern int     CPU_ForceNMI;   // Set to force a NMI (currently only supported by the SG-1000/SC-3000 loop handlers)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Macros and declarations, per Z80 emulator\r\n//-----------------------------------------------------------------------------\r\n// NOTE: MARAT_Z80 is the only maintained Z80 emulator in MEKA.\r\n//       Some others may not compile as is, some may be way unusable.\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef MARAT_Z80\r\n  u16 Loop_SMS();\r\n  #define Macro_Stop_CPU    { return (INT_QUIT); }\r\n  #define CPU_GetPC()       (sms.R.PC.W)\r\n  #define CPU_GetICount()   (sms.R.ICount)\r\n  #define CPU_GetIPeriod()  (sms.R.IPeriod)\r\n#elif RAZE_Z80\r\n  #define INT_IRQ           (0x38)\r\n  #define INT_NMI           (0x66)\r\n  #define INT_NONE          (0xFFFF)\r\n  #define INT_QUIT          (0xFFFE)\r\n  #define Get_ICount        z80_get_cycles_elapsed ()\r\n  #define Get_IPeriod       opt.Cur_IPeriod\r\n#elif MAME_Z80\r\n  #define INT_IRQ           (0x38)\r\n  #define INT_NMI           (0x66)\r\n  #define INT_NONE          (0xFFFF)\r\n  #define INT_QUIT          (0xFFFE)\r\n  void (*WrZ80)(word, byte);\r\n  byte (*RdZ80)(word);\r\n  word (*LoopZ80)();\r\n  void CPU_Loop();\r\n  int Get_Active_CPU();\r\n  int Get_IRQ_Vector(int p);\r\n  #define Macro_Stop_CPU    z80_exit()\r\n  #define CPU_GetPC         z80_get_pc()\r\n  #define Get_ICount        z80_ICount\r\n  #define Get_IPeriod       opt.Cur_IPeriod\r\n  word Loop_SMS();\r\n#endif\r\n\r\n#ifdef RAZE_Z80\r\n  void (*WrZ80)(word, byte);\r\n  byte (*RdZ80)(word);\r\n  word (*LoopZ80)();\r\n  void CPU_Loop();\r\n  word Loop_SMS();\r\n  #define Macro_Stop_CPU { return (INT_QUIT); }\r\n  #define Raze_Update_Mapping(a, b, c) { z80_map_read (a, b, c); z80_map_fetch (a, b, c); }\r\n#else\r\n  #define Raze_Update_Mapping(a, b, c) { }\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid Interrupt_Loop_Misc_Line_Zero();\r\nbool Interrupt_Loop_Misc_Common();                  // Return true when need to leave loop\r\nbool Interrupt_Loop_Misc(int* out_interrupt);       // Return true when need to leave loop\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/data.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - data.c\r\n// Data Loading - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: The proper way of loading the data file would be to check for the\r\n// type of all data (eg: if known bitmap index is actually a bitmap, etc...).\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"bios.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_data_graphics     Graphics;\r\nenum\r\n{\r\n    DATA_PROCESS_NULLIFY = 0x01,\r\n    DATA_PROCESS_FREE    = 0x02,\r\n    DATA_PROCESS_LOAD    = 0x04,\r\n};\r\nstatic int DataProcessFlags;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void* Data_CopyInBiggerArea(void *src, int src_size, int dst_size)\r\n{\r\n    void *p = malloc (dst_size);\r\n    memcpy (p, src, src_size);\r\n    memset ((u8 *)p + src_size, 0, dst_size - src_size);\r\n    return (p);\r\n}\r\n\r\nstatic void* Data_LoadBinary(const char* name)\r\n{\r\n    char filename_buf[FILENAME_LEN];\r\n    sprintf(filename_buf, \"%s/Data/%s\", g_env.Paths.EmulatorDirectory, name);\r\n\r\n    FILE* f = fopen(filename_buf, \"rb\");\r\n    fseek(f, 0, SEEK_END);\r\n    const int size = ftell(f);\r\n    fseek(f, 0, SEEK_SET);\r\n\r\n    void* buf = Memory_Alloc(size);\r\n    fread(buf, 1, size, f);\r\n    return buf;\r\n}\r\n\r\nstatic bool Data_LoadBitmap(ALLEGRO_BITMAP** pbitmap, const char* name)\r\n{\r\n    if (DataProcessFlags & DATA_PROCESS_NULLIFY)\r\n        *pbitmap = NULL;\r\n\r\n    if (DataProcessFlags & DATA_PROCESS_FREE)\r\n    {\r\n        if (*pbitmap != NULL)\r\n        {\r\n            al_destroy_bitmap(*pbitmap);\r\n            *pbitmap = NULL;\r\n        }\r\n    }\r\n\r\n    if (DataProcessFlags & DATA_PROCESS_LOAD)\r\n    {\r\n        char filename_buf[FILENAME_LEN];\r\n        sprintf(filename_buf, \"%s/Data/%s\", g_env.Paths.EmulatorDirectory, name);\r\n\r\n        // Even when loaded from a file the system use the format specified by manually (good!)\r\n        al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);\r\n        al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA);\r\n\r\n        *pbitmap = al_load_bitmap(filename_buf);\r\n        if (!*pbitmap)\r\n        {\r\n            Quit_Msg(\"%s\\nError loading image: \\\"%s\\\"\", Msg_Get(MSG_Failed), name);\r\n            return false;\r\n        }\r\n\r\n        // We use ff00ff pink as alpha mask for practical purpose\r\n        al_convert_mask_to_alpha(*pbitmap, al_map_rgb(0xFF,0x00,0xFF));\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nstatic bool Data_LoadMouseCursor(ALLEGRO_MOUSE_CURSOR** pcursor, ALLEGRO_BITMAP* bitmap, int pivot_x, int pivot_y)\r\n{\r\n    if (DataProcessFlags & DATA_PROCESS_NULLIFY)\r\n        *pcursor = NULL;\r\n\r\n    if (DataProcessFlags & DATA_PROCESS_FREE)\r\n    {\r\n        if (*pcursor != NULL)\r\n        {\r\n            al_destroy_mouse_cursor(*pcursor);\r\n            *pcursor = NULL;\r\n        }\r\n    }\r\n\r\n    if (DataProcessFlags & DATA_PROCESS_LOAD)\r\n    {\r\n        *pcursor = al_create_mouse_cursor(bitmap, pivot_x, pivot_y);\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nbool Data_LoadFont(ALLEGRO_FONT** pfont, const char* name, int size)\r\n{\r\n    if (DataProcessFlags & DATA_PROCESS_NULLIFY)\r\n        *pfont = NULL;\r\n\r\n    if (DataProcessFlags & DATA_PROCESS_FREE)\r\n    {\r\n        if (*pfont != NULL)\r\n        {\r\n            al_destroy_font(*pfont);\r\n            *pfont = NULL;\r\n        }\r\n    }\r\n\r\n    if (DataProcessFlags & DATA_PROCESS_LOAD)\r\n    {\r\n        char filename_buf[FILENAME_LEN];\r\n        sprintf(filename_buf, \"%s/Data/%s\", g_env.Paths.EmulatorDirectory, name);\r\n\r\n        ALLEGRO_FONT* font = al_load_font(filename_buf, size, 0);\r\n        if (!font)\r\n        {\r\n            Quit_Msg(\"%s\\nError loading font: \\\"%s\\\"\", Msg_Get(MSG_Failed), name);\r\n            return false;\r\n        }\r\n        *pfont = font;\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nstatic void Data_LoadBinaries();\r\nstatic void Data_ProcessVideoBitmaps();\r\n\r\nvoid Data_Init()\r\n{\r\n    // Print loading message to console\r\n    ConsolePrint(Msg_Get(MSG_Datafile_Loading));\r\n\r\n    // FIXME-ALLEGRO5: Load from an archive file + minimal error handling.\r\n    DataProcessFlags = DATA_PROCESS_NULLIFY;// | DATA_PROCESS_FREE | DATA_PROCESS_LOAD;\r\n    Data_ProcessVideoBitmaps();\r\n    Data_LoadBinaries();\r\n\r\n    ConsolePrint(\"\\n\");\r\n}\r\n\r\nvoid Data_ProcessVideoBitmaps()\r\n{\r\n    // Cursors\r\n    Data_LoadBitmap(&Graphics.Cursors.Bitmaps.Main,         \"cursor_main.tga\");\r\n    Data_LoadBitmap(&Graphics.Cursors.Bitmaps.Wait,         \"cursor_wait.tga\");\r\n    Data_LoadBitmap(&Graphics.Cursors.Bitmaps.LightPhaser,  \"cursor_lightphaser.tga\");\r\n    Data_LoadBitmap(&Graphics.Cursors.Bitmaps.SportsPad,    \"cursor_sportspad.tga\");\r\n    Data_LoadBitmap(&Graphics.Cursors.Bitmaps.TvOekaki,     \"cursor_tvoekaki.tga\");\r\n\r\n    // Miscellaneous\r\n    Data_LoadBitmap(&Graphics.Misc.Dragon,                  \"gfx_dragon.tga\");\r\n    Data_LoadBitmap(&Graphics.Misc.Heart1,                  \"gfx_heart1.tga\");\r\n    Data_LoadBitmap(&Graphics.Misc.Heart2,                  \"gfx_heart2.tga\");\r\n\r\n    // Inputs\r\n    Data_LoadBitmap(&Graphics.Inputs.InputsBase,            \"gfx_inputs.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.Glasses,               \"gfx_glasses.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.Joypad,                \"gfx_joypad.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.LightPhaser,           \"gfx_lightphaser.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.PaddleControl,         \"gfx_paddlecontrol.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.SportsPad,             \"gfx_sportspad.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.SuperHeroPad,          \"gfx_superheropad.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.TvOekaki,              \"gfx_tvoekaki.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.GraphicBoardV2,        \"gfx_graphicboardv2.tga\");\r\n    Data_LoadBitmap(&Graphics.Inputs.SK1100_Keyboard,       \"gfx_keyboard.tga\");\r\n\r\n    // Machines\r\n    Data_LoadBitmap(&Graphics.Machines.MasterSystem,        \"machine_sms.tga\");\r\n    Data_LoadBitmap(&Graphics.Machines.MasterSystem_Cart,   \"machine_sms_cartridge.tga\");\r\n    Data_LoadBitmap(&Graphics.Machines.MasterSystem_Light,  \"machine_sms_light.tga\");\r\n    Data_LoadBitmap(&Graphics.Machines.ColecoVision,        \"machine_coleco.tga\");\r\n\r\n    // Flags\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_UNKNOWN],         \"flag_unknown.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_AU],              \"flag_au.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_BR],              \"flag_br.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_JP],              \"flag_jp.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_KR],              \"flag_kr.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_FR],              \"flag_fr.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_US],              \"flag_us.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_CH],              \"flag_ch.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_HK],              \"flag_hk.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_EU],              \"flag_eu.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_PT],              \"flag_pt.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_DE],              \"flag_de.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_IT],              \"flag_it.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_SP],              \"flag_sp.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_SW],              \"flag_sw.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_NZ],              \"flag_nz.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_UK],              \"flag_uk.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_CA],              \"flag_ca.tga\");\r\n    Data_LoadBitmap(&Graphics.Flags [FLAG_TW],              \"flag_tw.tga\");\r\n\r\n    // Icons\r\n    Data_LoadBitmap(&Graphics.Icons.BAD,                    \"icon_bad.tga\");\r\n    Data_LoadBitmap(&Graphics.Icons.BIOS,                   \"icon_bios.tga\");\r\n    Data_LoadBitmap(&Graphics.Icons.Hack,                   \"icon_hack.tga\");\r\n    Data_LoadBitmap(&Graphics.Icons.HomeBrew,               \"icon_homebrew.tga\");\r\n    Data_LoadBitmap(&Graphics.Icons.Prototype,              \"icon_proto.tga\");\r\n    Data_LoadBitmap(&Graphics.Icons.Translation_JP,         \"icon_trans_jp.tga\");\r\n    Data_LoadBitmap(&Graphics.Icons.Translation_JP_US,      \"icon_trans_jp_us.tga\");\r\n\r\n    // Fonts\r\n    for (int i = 0; i < FONTID_COUNT_; i++)\r\n    {\r\n        Data_LoadFont(&Fonts[i].library_data, Fonts[i].load_filename,   Fonts[i].load_size);\r\n        if (DataProcessFlags & DATA_PROCESS_LOAD)\r\n            Fonts[i].height = al_get_font_line_height(Fonts[i].library_data);\r\n    }\r\n\r\n    // Mouse cursors\r\n    Data_LoadMouseCursor(&Graphics.Cursors.Main,        Graphics.Cursors.Bitmaps.Main, 0, 0);\r\n    Data_LoadMouseCursor(&Graphics.Cursors.Wait,        Graphics.Cursors.Bitmaps.Wait, 6, 2);\r\n    Data_LoadMouseCursor(&Graphics.Cursors.LightPhaser, Graphics.Cursors.Bitmaps.LightPhaser, 7, 7);\r\n    Data_LoadMouseCursor(&Graphics.Cursors.SportsPad,   Graphics.Cursors.Bitmaps.SportsPad, 7, 7);\r\n    Data_LoadMouseCursor(&Graphics.Cursors.TvOekaki,    Graphics.Cursors.Bitmaps.TvOekaki, 3, 12);\r\n}\r\n\r\nvoid Data_LoadBinaries()\r\n{\r\n    // BIOS\r\n    // Note: BIOSes are unpacked in a bigger memory area, so they can be mapped\r\n    // without having to handle memory accesses outside their allocated range.\r\n    // The same trick is done on loading < 48 KB Sega 8-bits ROM images.\r\n    BIOS_ROM            = (u8*)Data_CopyInBiggerArea(Data_LoadBinary(\"rom_sms.rom\"),     0x2000, 0xC000);\r\n    BIOS_ROM_Jap        = (u8*)Data_CopyInBiggerArea(Data_LoadBinary(\"rom_smsj.rom\"),   0x2000, 0xC000);\r\n    BIOS_ROM_Coleco     = (u8*)Data_CopyInBiggerArea(Data_LoadBinary(\"rom_coleco.rom\"),  0x2000, 0x2000);\r\n    BIOS_ROM_SF7000     = (u8*)Data_CopyInBiggerArea(Data_LoadBinary(\"rom_sf7000.rom\"),  0x2000, 0x4000);\r\n\r\n    // Patch SF-7000 BIOS (FIXME: move to sf7000.c)\r\n    // Bios_ROM_SF7000[0x112] = Bios_ROM_SF7000[0x113] = Bios_ROM_SF7000[0x114] = 0x00;\r\n    // Bios_ROM_SF7000[0x183] = Bios_ROM_SF7000[0x184] = Bios_ROM_SF7000[0x185] = 0x00;\r\n    BIOS_ROM_SF7000[0x1D8] = BIOS_ROM_SF7000[0x1D9] = BIOS_ROM_SF7000[0x1DA] = 0x00;\r\n}\r\n\r\nvoid    Data_Close()\r\n{\r\n    Data_DestroyVideoBuffers();\r\n}\r\n\r\nvoid    Data_CreateVideoBuffers()\r\n{\r\n    DataProcessFlags = DATA_PROCESS_FREE | DATA_PROCESS_LOAD;\r\n    Data_ProcessVideoBitmaps();\r\n}\r\n\r\nvoid    Data_DestroyVideoBuffers()\r\n{\r\n    DataProcessFlags = DATA_PROCESS_FREE;\r\n    Data_ProcessVideoBitmaps();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/data.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - data.h\r\n// Data Loading - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Flags id\r\n#define FLAG_UNKNOWN    (0)\r\n#define FLAG_AU         (1)     // Australia\r\n#define FLAG_BR         (2)     // Brazil\r\n#define FLAG_JP         (3)     // Japan\r\n#define FLAG_KR         (4)     // Korea\r\n#define FLAG_FR         (5)     // France\r\n#define FLAG_US         (6)     // USA\r\n#define FLAG_CH         (7)     // China\r\n#define FLAG_HK         (8)     // Hong-Kong\r\n#define FLAG_EU         (9)     // Europe\r\n#define FLAG_PT         (10)    // Portugal\r\n#define FLAG_DE         (11)    // Deutschland/Germany\r\n#define FLAG_IT         (12)    // Italia\r\n#define FLAG_SP         (13)    // Spain\r\n#define FLAG_SW         (14)    // Sweden\r\n#define FLAG_NZ         (15)    // New-Zealand\r\n#define FLAG_UK         (16)    // United-Kingdom\r\n#define FLAG_CA         (17)    // Canada\r\n#define FLAG_TW         (18)    // Taiwan\r\n#define FLAG_COUNT      (19)\r\n\r\n//-----------------------------------------------------------------------------\r\n// t_data_graphics Graphics\r\n// Hold handler to all graphics data\r\n//-----------------------------------------------------------------------------\r\nstruct t_data_graphics\r\n{\r\n    // Cursors\r\n    struct\r\n    {\r\n        struct\r\n        {\r\n            ALLEGRO_BITMAP *    Main;\r\n            ALLEGRO_BITMAP *    Wait;\r\n            ALLEGRO_BITMAP *    LightPhaser;\r\n            ALLEGRO_BITMAP *    SportsPad;\r\n            ALLEGRO_BITMAP *    TvOekaki;\r\n        } Bitmaps;\r\n        ALLEGRO_MOUSE_CURSOR *  Main;\r\n        ALLEGRO_MOUSE_CURSOR *  Wait;\r\n        ALLEGRO_MOUSE_CURSOR *  LightPhaser;\r\n        ALLEGRO_MOUSE_CURSOR *  SportsPad;\r\n        ALLEGRO_MOUSE_CURSOR *  TvOekaki;\r\n    } Cursors;\r\n\r\n    // Flags\r\n    ALLEGRO_BITMAP *        Flags [FLAG_COUNT];\r\n\r\n    // Icons\r\n    struct\r\n    {\r\n        ALLEGRO_BITMAP *    BAD;\r\n        ALLEGRO_BITMAP *    BIOS;\r\n        ALLEGRO_BITMAP *    Hack;\r\n        ALLEGRO_BITMAP *    HomeBrew;\r\n        ALLEGRO_BITMAP *    Prototype;\r\n        ALLEGRO_BITMAP *    Translation_JP;\r\n        ALLEGRO_BITMAP *    Translation_JP_US;\r\n    } Icons;\r\n\r\n    // Inputs\r\n    struct\r\n    {\r\n        ALLEGRO_BITMAP *    InputsBase;\r\n        ALLEGRO_BITMAP *    Glasses;\r\n        ALLEGRO_BITMAP *    Joypad;\r\n        ALLEGRO_BITMAP *    LightPhaser;\r\n        ALLEGRO_BITMAP *    PaddleControl;\r\n        ALLEGRO_BITMAP *    SportsPad;\r\n        ALLEGRO_BITMAP *    SuperHeroPad;\r\n        ALLEGRO_BITMAP *    TvOekaki;\r\n        ALLEGRO_BITMAP *    GraphicBoardV2;\r\n        ALLEGRO_BITMAP *    SK1100_Keyboard;\r\n    } Inputs;\r\n\r\n    // Machines\r\n    struct\r\n    {\r\n        ALLEGRO_BITMAP *    MasterSystem;\r\n        ALLEGRO_BITMAP *    MasterSystem_Cart;\r\n        ALLEGRO_BITMAP *    MasterSystem_Light;\r\n        ALLEGRO_BITMAP *    ColecoVision;\r\n    } Machines;\r\n\r\n    // Miscellaneous\r\n    struct\r\n    {\r\n        ALLEGRO_BITMAP *    Dragon;\r\n        ALLEGRO_BITMAP *    Heart1;\r\n        ALLEGRO_BITMAP *    Heart2;\r\n    } Misc;\r\n\r\n};\r\n\r\nextern t_data_graphics     Graphics;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Data_Init                   ();\r\nvoid    Data_Close                  ();\r\n\r\nvoid    Data_CreateVideoBuffers     ();\r\nvoid    Data_DestroyVideoBuffers    ();\r\nbool    Data_LoadFont(ALLEGRO_FONT** pfont, const char* name, int size);\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/datadump.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - datadump.c\r\n// Data Dumping - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"mappers.h\"\r\n#include \"datadump.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_data_dump DataDump;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Types\r\n//-----------------------------------------------------------------------------\r\n\r\ntypedef int (*t_data_dump_handler_ascii)(FILE *f_dump, int pos, u8 const *data, int len, int start_addr);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Init ()\r\n// Initialize data dumping functionnality\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_Init (void)\r\n{\r\n    DataDump.Mode = DATADUMP_MODE_ASCII;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Init_Menus ()\r\n// Create data dumping menu items in given GUI menu\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_Init_Menus (int menu_id)\r\n{\r\n    menu_add_item (menu_id, \"RAM\",           NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_RAM,           NULL);\r\n    menu_add_item (menu_id, \"VRAM\",          NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_VRAM,          NULL);\r\n    menu_add_item (menu_id, \"Palette\",       NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_Palette,       NULL);\r\n    menu_add_item (menu_id, \"Sprites\",       NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_Sprites,       NULL);\r\n    //menu_add_item (menu_id, \"BG/FG Map\",   0,         (t_menu_callback)DataDump_BgFgMap,      NULL);\r\n    menu_add_item (menu_id, \"CPU Regs\",      NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_CPURegs,       NULL);\r\n    menu_add_item (menu_id, \"VDP Regs\",      NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_VRegs,         NULL);\r\n    menu_add_item (menu_id, \"OnBoardMemory\", NULL,  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)DataDump_OnBoardMemory, NULL);\r\n\r\n    menus_ID.dump_cfg = menu_add_menu (menu_id, \"Configuration\",   MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item (menus_ID.dump_cfg, \"ASCII\",  NULL,   MENU_ITEM_FLAG_ACTIVE | ((DataDump.Mode == DATADUMP_MODE_ASCII) ? MENU_ITEM_FLAG_CHECKED : 0), (t_menu_callback)DataDump_Mode_Ascii,        NULL);\r\n    menu_add_item (menus_ID.dump_cfg, \"Raw\",    NULL,   MENU_ITEM_FLAG_ACTIVE | ((DataDump.Mode == DATADUMP_MODE_RAW)   ? MENU_ITEM_FLAG_CHECKED : 0), (t_menu_callback)DataDump_Mode_Raw,      NULL);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Mode_Ascii ()\r\n// Activate ASCII dumping mode\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_Mode_Ascii (void)\r\n{\r\n    // Set ASCII mode\r\n    DataDump.Mode = DATADUMP_MODE_ASCII;\r\n\r\n    // Update GUI checks & print message to user\r\n    gui_menu_uncheck_all (menus_ID.dump_cfg);\r\n    gui_menu_check (menus_ID.dump_cfg, 0);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_DataDump_Mode_Ascii));\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Mode_Raw ()\r\n// Activate RAW dumping mode\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_Mode_Raw (void)\r\n{\r\n    // Set RAW mode\r\n    DataDump.Mode = DATADUMP_MODE_RAW;\r\n\r\n    // Update GUI checks & print message to user\r\n    gui_menu_uncheck_all (menus_ID.dump_cfg);\r\n    gui_menu_check (menus_ID.dump_cfg, 1);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_DataDump_Mode_Raw));\r\n}\r\n\r\nstatic void     DataDump_Write_Filename (char *s, const char *name)\r\n{\r\n    if (!al_filename_exists (g_env.Paths.DebugDirectory))\r\n        al_make_directory (g_env.Paths.DebugDirectory);\r\n    sprintf(s, \"%s/%s\", g_env.Paths.DebugDirectory, name);\r\n}\r\n\r\nstatic void     DataDump_Main_Raw (const char *name, const u8 *data, int len)\r\n{\r\n    FILE *      f_dump;\r\n    char        filename[FILENAME_LEN];\r\n\r\n    DataDump_Write_Filename (filename, name);\r\n    if ((f_dump = fopen(filename, \"wb\")) == NULL)\r\n    {\r\n        Msg(MSGT_USER, Msg_Get(MSG_DataDump_Error), name);\r\n        return;\r\n    }\r\n\r\n    // Dump\r\n    fwrite (data, 1, len, f_dump);\r\n\r\n    // Close file & print a message\r\n    fclose (f_dump);\r\n    Msg(MSGT_USER, Msg_Get(MSG_DataDump_Main),\r\n        name,\r\n        (len % 1024 == 0) ? (len / 1024) : len,\r\n        (len % 1024 == 0) ? \"KBytes\" : \"bytes\",\r\n        \"Raw\");\r\n}\r\n\r\nstatic void     DataDump_Main_Ascii (const char *name, const u8 *data, int len, int start_addr, t_data_dump_handler_ascii func)\r\n{\r\n    int         i;\r\n    FILE *      f_dump;\r\n    char        filename[FILENAME_LEN];\r\n\r\n    DataDump_Write_Filename (filename, name);\r\n    if ((f_dump = fopen(filename, \"wt\")) == NULL)\r\n    {\r\n        Msg(MSGT_USER, Msg_Get(MSG_DataDump_Error), name);\r\n        return;\r\n    }\r\n\r\n    // Print a header\r\n    fprintf(f_dump, MEKA_NAME_VERSION \"\\n\");\r\n    fprintf(f_dump, \"** %s dump\\n\", name);\r\n    fprintf(f_dump, \"** File: %s\\n\", g_env.Paths.MediaImageFile);\r\n    // Note: meka_date_getf() return a string with an ending \\n\r\n    fprintf(f_dump, \"** Date: %s\\n\", meka_date_getf());\r\n\r\n    // Dumping\r\n    i = 0;\r\n    while (i < len)\r\n        i = func(f_dump, i, data, len, start_addr);\r\n\r\n    // Close file & print a message\r\n    fclose (f_dump);\r\n    Msg(MSGT_USER, Msg_Get(MSG_DataDump_Main),\r\n        name,\r\n        (len % 1024 == 0) ? (len / 1024) : len,\r\n        (len % 1024 == 0) ? \"Kbytes\" : \"bytes\",\r\n        \"ASCII\");\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Handler_Ascii_Standard ()\r\n// Data dump ASCII output handler:\r\n// - Standard (hexadecimal & ascii equivalents, 16 per line)\r\n//-----------------------------------------------------------------------------\r\nstatic int  DataDump_Handler_Ascii_Standard (FILE *f_dump, int pos, u8 const *data, int len, int start_addr)\r\n{\r\n    int     i;\r\n\r\n    fprintf(f_dump, \"%04X-%04X | \", pos + start_addr, pos + start_addr + 15);\r\n    for (i = 0; (i < 16) && (pos + i < len); i++)\r\n        fprintf(f_dump, \"%02X \", data[pos + i]);\r\n    fprintf(f_dump, \"| \");\r\n    for (i = 0; (i < 16) && (pos + i < len); i++)\r\n        fprintf(f_dump, \"%c\", (data[pos + i] >= 32) ? data[pos + i] : '.');\r\n    fprintf(f_dump, \"\\n\");\r\n    return (pos + 16);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Handler_Ascii_CPURegs_Reg ()\r\n// Helper function to dump a Z80 CPU register\r\n//-----------------------------------------------------------------------------\r\nstatic void DataDump_Handler_Ascii_CPURegs_Reg (FILE *f_dump, const char *name, word value, const char *comment)\r\n{\r\n    char    bitfields[2][9];\r\n\r\n    StrWriteBitfield ((value >> 8) & 0xFF, 8, bitfields[0]);\r\n    StrWriteBitfield (value & 0xFF, 8, bitfields[1]);\r\n    if (comment)\r\n        fprintf(f_dump, \"%-3s = $%04X | %%%s.%s | %s\\n\", name, value, bitfields[0], bitfields[1], comment);\r\n    else\r\n        fprintf(f_dump, \"%-3s = $%04X | %%%s.%s |\\n\", name, value, bitfields[0], bitfields[1]);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Handler_Ascii_CPURegs ()\r\n// Data dump ASCII output handler:\r\n// - CPU Registers (all registers at once, given by 'data' pointer)\r\n//-----------------------------------------------------------------------------\r\nstatic int  DataDump_Handler_Ascii_CPURegs (FILE *f_dump, int pos, const u8 *data, int len, int start_addr)\r\n{\r\n    Z80 *   R;\r\n\r\n    R = (Z80 *)data;\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"AF\", R->AF.W, \"Accumulator and flags (SZ.H.PNC)\");\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"BC\", R->BC.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"DE\", R->DE.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"HL\", R->HL.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"IX\", R->IX.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"IY\", R->IY.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"PC\", R->PC.W, \"Program Counter\");\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"SP\", R->SP.W, \"Stack Pointer\");\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"AF'\", R->AF1.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"BC'\", R->BC1.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"DE'\", R->DE1.W, NULL);\r\n    DataDump_Handler_Ascii_CPURegs_Reg (f_dump, \"HL'\", R->HL1.W, NULL);\r\n    fprintf(f_dump, \"%-3s = $%02X\\n\", \"I\", (byte)(R->I));\r\n    fprintf(f_dump, \"%-3s = $%02X\\n\", \"R\", (byte)((R->R & 0x7F)|(R->R7)));\r\n    fprintf(f_dump, \"IPeriod = %d\\n\", R->IPeriod);\r\n    fprintf(f_dump, \"ICount  = %d\\n\", R->ICount);\r\n    fprintf(f_dump, \"IFF1 = %d\\nIFF2 = %d\\nIM   = %d\\nEI   = %d\\nHALT = %d\\n\",\r\n        (R->IFF & IFF_1) ? 1 : 0, (R->IFF & IFF_2) ? 1 : 0, (R->IFF & (IFF_IM1 | IFF_IM2)) >> 1, (R->IFF & IFF_EI) ? 1 : 0, (R->IFF & IFF_HALT) ? 1 : 0);\r\n    fprintf(f_dump, \"\\n\");\r\n    fprintf(f_dump, \"(some implementation information were not dumped here.\\n\");\r\n    fprintf(f_dump, \" Please contact me if they may be of your interest)\\n\");\r\n    return (sizeof (sms.R));\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Handler_Ascii_VReg ()\r\n// Data dump ASCII output handler:\r\n// - VDP Registers (hexadecimal & binary, 1 per line)\r\n//-----------------------------------------------------------------------------\r\nstatic int  DataDump_Handler_Ascii_VReg (FILE *f_dump, int pos, const u8 *data, int len, int start_addr)\r\n{\r\n    char    bitfield[9];\r\n\r\n    StrWriteBitfield (data[pos], 8, bitfield);\r\n    fprintf(f_dump, \"VReg[%02d] = $%02X | %%%s\\n\", pos, data[pos], bitfield);\r\n    return (pos + 1);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Handler_Ascii_Palette ()\r\n// Data dump ASCII output handler:\r\n// - Palette (colors, 1 or 2 bytes per line depending on driver)\r\n//-----------------------------------------------------------------------------\r\nstatic int  DataDump_Handler_Ascii_Palette (FILE *f_dump, int pos, const u8 *data, int len, int start_addr)\r\n{\r\n    char    bitfields[2][9];\r\n\r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_SMS:\r\n        {\r\n            const u8 palette_data = data[pos];\r\n            StrWriteBitfield (palette_data, 8, bitfields[0]);\r\n            fprintf(f_dump, \"Color %02d : %%%s | $%02X | R=%d, G=%d, B=%d\\n\", pos, bitfields[0], palette_data, palette_data & 3, (palette_data >> 2) & 3, (palette_data >> 4) & 3);\r\n            return (pos + 1);\r\n        }\r\n    case DRV_GG:\r\n        {\r\n            const u16 palette_data = *(u16 *)(data + pos);\r\n            StrWriteBitfield (data[pos+0], 8, bitfields[0]);\r\n            StrWriteBitfield (data[pos+1], 8, bitfields[1]);\r\n            fprintf(f_dump, \"Color %02d : %%%s.%s | $%04X | R=%d,%s G=%d,%s B=%d\\n\", pos / 2, bitfields[1], bitfields[0], palette_data, (palette_data & 15), (palette_data & 15) < 10 ? \" \" : \"\", (palette_data >> 4) & 15, ((palette_data >> 4) & 15) < 10 ? \" \" : \"\", (palette_data >> 8) & 15);\r\n            return (pos + 2);\r\n        }\r\n    }\r\n    Msg(MSGT_USER, \"Error #9011: datadump.c::DataDump_Handler_Ascii_Palette(). Please report.\");\r\n    return (len); // End dump\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DataDump_Handler_Ascii_Sprite ()\r\n// Data dump ASCII output handler:\r\n// - Sprites (x, y, attr, unknown)\r\n//-----------------------------------------------------------------------------\r\nstatic int  DataDump_Handler_Ascii_Sprite (FILE *f_dump, int pos, const u8 *data, int len, int start_addr)\r\n{\r\n    if (tsms.VDP_VideoMode > 4)\r\n    {\r\n        int  n;\r\n        n = pos / 4;\r\n        if (pos == 0)\r\n        {\r\n            fprintf(f_dump,\r\n                \"Sprite pattern base: $%04X\\n\"\r\n                \"Sprite shift X (early clock): %d pixels\\n\\n\",\r\n                (int)(g_machine.VDP.sprite_pattern_gen_address - VRAM),\r\n                g_machine.VDP.sprite_shift_x);\r\n            fprintf(f_dump,\r\n                \"            Raw Data      |    X     Y     T     ?\\n\"\r\n                \"---------- --------------- ------------------------\\n\");\r\n        }\r\n        fprintf(f_dump,\r\n            \"Sprite %02d : %02X %02X . %02X %02X |  % 4d  % 4d  % 4d  % 4d\\n\",\r\n            n, data[n], data[0x40 + n], data[0x80 + n*2], data[0x80 + n*2+1],\r\n            data[0x80 + n*2], data[n], data[0x80 + n*2+1], data[0x40 + n]);\r\n    }\r\n    else\r\n    {\r\n        if (pos == 0)\r\n        {\r\n            fprintf(f_dump,\r\n                \"Sprite pattern base: $%04X\\n\\n\",\r\n                (int)(g_machine.VDP.sprite_pattern_gen_address - VRAM));\r\n            fprintf(f_dump,\r\n                \"            Raw Data    |    X     Y     T    C/A\\n\"\r\n                \"----------- ------------ ------------------------\\n\");\r\n        }\r\n        fprintf(f_dump,\r\n            \"Sprite %02d : %02X %02X %02X %02X |  % 4d  % 4d  % 4d  % 4d%s\\n\",\r\n            pos / 4,\r\n            data[pos+0], data[pos+1], data[pos+2], data[pos+3],\r\n            data[pos+1], data[pos+0], data[pos+2], data[pos+3],\r\n            (data[pos+3] & 128) ? \" (Shifted)\" : \"\");\r\n\r\n    }\r\n\r\n    // Increase data pointer by 4 (size of a sprite entry)\r\n    return (pos + 4);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump RAM\r\n//-----------------------------------------------------------------------------\r\nvoid        DataDump_RAM()\r\n{\r\n    int     len;\r\n    int     start_addr;\r\n\r\n    Mapper_Get_RAM_Infos (&len, &start_addr);\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"RAM\", RAM, len);\r\n    else\r\n        DataDump_Main_Ascii (\"RAM\", RAM, len, start_addr, DataDump_Handler_Ascii_Standard);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump VRAM\r\n//-----------------------------------------------------------------------------\r\nvoid        DataDump_VRAM()\r\n{\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"VRAM\", VRAM, 0x4000);\r\n    else\r\n        DataDump_Main_Ascii (\"VRAM\", VRAM, 0x4000, 0x0000, DataDump_Handler_Ascii_Standard);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump Palette\r\n//-----------------------------------------------------------------------------\r\nvoid        DataDump_Palette()\r\n{\r\n    int     len;\r\n\r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_SMS:      len = 32;       break;\r\n    case DRV_GG:       len = 64;       break;\r\n    default:           len = 0;        break;\r\n    }\r\n    if (len == 0)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_DataDump_Error_Palette));\r\n        return;\r\n    }\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"Palette\", PRAM, len);\r\n    else\r\n        DataDump_Main_Ascii (\"Palette\", PRAM, len, 0, DataDump_Handler_Ascii_Palette);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump Sprites\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_Sprites()\r\n{\r\n    int n_sprites = 0;\r\n\r\n    switch (tsms.VDP_VideoMode)\r\n    {\r\n    case 0:  n_sprites = 0; break;\r\n    case 1:\r\n    case 2:\r\n    case 3:  n_sprites = 32; break;\r\n    default: n_sprites = 64; break;\r\n    }\r\n\r\n    if (n_sprites == 0)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_DataDump_Error_Sprites));\r\n        return;\r\n    }\r\n\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"Sprites\", g_machine.VDP.sprite_attribute_table, n_sprites * 4);\r\n    else\r\n        DataDump_Main_Ascii (\"Sprites\", g_machine.VDP.sprite_attribute_table, n_sprites * 4, /* Unused */ 0, DataDump_Handler_Ascii_Sprite);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump BackGround/ForeGround screen map\r\n// FIXME: To do\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_BgFgMap()\r\n{\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump CPU Registers\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_CPURegs()\r\n{\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"CPURegs\", (byte *)&sms.R, sizeof (sms.R));\r\n    else\r\n        DataDump_Main_Ascii (\"CPURegs\", (byte *)&sms.R, sizeof (sms.R), 0, DataDump_Handler_Ascii_CPURegs);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump VDP Registers\r\n//-----------------------------------------------------------------------------\r\nvoid    DataDump_VRegs()\r\n{\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"VRegs\", sms.VDP, 16);\r\n    else\r\n        DataDump_Main_Ascii (\"VRegs\", sms.VDP, 16, 0, DataDump_Handler_Ascii_VReg);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Dump OnBoard Memory\r\n//-----------------------------------------------------------------------------\r\nvoid        DataDump_OnBoardMemory (void)\r\n{\r\n    void *  data;\r\n    int     len;\r\n\r\n    BMemory_Get_Infos (&data, &len);\r\n    if (data == NULL)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_DataDump_Error_OB_Memory));\r\n        return;\r\n    }\r\n    if (DataDump.Mode == DATADUMP_MODE_RAW)\r\n        DataDump_Main_Raw   (\"OBMem\", (u8*)data, len);\r\n    else\r\n        DataDump_Main_Ascii (\"OBMem\", (u8*)data, len, 0, DataDump_Handler_Ascii_Standard);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/datadump.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - datadump.h\n// Data Dumping - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define DATADUMP_MODE_ASCII             (0) /* Default */\n#define DATADUMP_MODE_RAW               (1)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_data_dump\n{\n    int     Mode;\n};\n\nextern t_data_dump DataDump;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    DataDump_Init                   (void);\nvoid    DataDump_Init_Menus             (int menu_id);\n\nvoid    DataDump_Mode_Ascii             (void);\nvoid    DataDump_Mode_Raw               (void);\n\nvoid    DataDump_RAM                    (void);\nvoid    DataDump_VRAM                   (void);\nvoid    DataDump_Tiles                  (void);\nvoid    DataDump_Palette                (void);\nvoid    DataDump_Sprites                (void);\nvoid    DataDump_BgFgMap                (void);\nvoid    DataDump_CPURegs                (void);\nvoid    DataDump_VRegs                  (void);\nvoid    DataDump_OnBoardMemory          (void);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/datasrc/README.txt",
    "content": "\r\n2005/04/02\r\n\r\nSome of the data included in MEKA.DAT file.\r\n\r\nNote:\r\n- MEKA-WIP.DAT is the work datafile.\r\n- MEKA.DAT is the end-user datafile stripped of names.\r\nAlways work on MEKA-WIP.DAT then save stripped to MEKA.DAT.\r\n\r\nSee DATA.H for a full list of the data entries.\r\nUse Allegro GRABBER to manipulate DAT files.\r\nEncryption password is:\r\n    west0ne0000000\r\n:)\r\n\r\nIt may not be trivial for someone other than me to rebuild a \r\nMEKA.DAT file from stratch, given that I have various files\r\nscattered on my computer (hacked BIOS images, etc), but you can\r\nalways add or replace existing data and keeping the older one\r\nintact using Allegro GRABBER tool.\r\n\r\nIf you're concerned by this and you want to clean this part,\r\nfeel free to discuss with me. BIOS should eventually be removed\r\nfrom there in favor of real, non-hacked BIOS (with potentially\r\nBIOS hacks hardcoded in MEKA and enablable at will).\r\n\r\n-Omar\r\n"
  },
  {
    "path": "meka/srcs/datasrc/fonts/README.txt",
    "content": "\r\n2005/04/02\r\n\r\nThis is a mess. Note how I modified certain fonts\r\nto move around some accentued character.\r\nOn font 0 (the big one) I also manually added 3 glyphs\r\nfor usage in the GUI:\r\n    - Little star (for closing windows)\r\n    - Check (for when a menuitem is checked)\r\n    - Modified '>' (when a menuitem lead to a submenu)\r\n\r\nEventually, fonts should be replaced by some having those\r\nglyphs (refered in Unicode notation):\r\n    - Latin character set (U-00 to U-7F)\r\n    - Extended Latin (U-80 to U-FF)\r\n    - Selected asian characters set:\r\n        - Japanese katakana + hiragana\r\n        - Japanese kanjis (perhaps not all but only those used in game titles + localization)\r\n        - Korean characters (for some game titles) // less important\r\n\r\n-Omar"
  },
  {
    "path": "meka/srcs/datasrc/keyboard/README.txt",
    "content": "\r\n2005/04/02\r\n\r\nThis is a drawing of SC-3000 keyboard (also known as SK-1100 when\r\nsold separately).\r\n\r\nThis looked fairly accurate when I originally did it (last update \r\nwas on 1999/01/17) but now I'd say it's begging for improvement.\r\n\r\nPalette usage is a problem, though, as the palette is global and used \r\nfor other GUI graphics (won't be a problem when switching to hi-color).\r\nI made 3 skins but never used them. The last one (black) may be a \r\nbetter rendition of the most common SC-3000 color scheme than the\r\ncurrently used one.\r\n\r\n-Omar\r\n"
  },
  {
    "path": "meka/srcs/datasrc/keyboard/c1.pal",
    "content": "255 128 128\r\n84 100 132\r\n0 0 0\r\n60 60 60\r\n228 236 188\r\n156 156 4\r\n220 220 100\r\n28 28 36\r\n60 60 84\r\n252 236 4\r\n100 108 156\r\n252 252 252\r\n4 44 4\r\n84 92 140\r\n52 52 68\r\n220 220 220\r\n196 188 4\r\n36 36 52\r\n60 68 100\r\n252 252 4\r\n255 255 255\r\n"
  },
  {
    "path": "meka/srcs/datasrc/wb3.ans",
    "content": "\r\n\u001b[?7h\u001b[255D\u001b[0;30;41m\u001b[40m\r\n\u001b[41m\u001b[1;37mWONDERBOY\u001b[0;30;41m\u001b[1;37mIII\u001b[0;30;41m\u001b[40m\r\n\u001b[41m\u001b[1;37mSEGA\u001b[0;30;41m\u001b[40m\r\n\u001b[1m\r\n\u001b[0m\u001b[255D\r\n"
  },
  {
    "path": "meka/srcs/db.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - db.c\r\n// MEKA Database - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"db.h\"\r\n#include \"vdp.h\"\r\n#include \"tvtype.h\"\r\n#include \"libparse.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_db DB;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic bool     DB_Load         (const char* filename, bool verbose);\r\n\r\nt_db_entry*     DB_Entry_New    (int system, u32 crc32, t_meka_crc* mekacrc);\r\nvoid            DB_Entry_Delete (t_db_entry* entry);\r\n\r\nt_db_name*      DB_Name_New     (t_db_entry* entry, char* name, int country, int non_latin);\r\nvoid            DB_Name_Delete  (t_db_name* dbname);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n// Note: this is not exactly the same as the extension in the drivers.c table\r\nstatic struct\r\n{\r\n    char name[4];\r\n    int  driver_id;\r\n} DB_SystemTable[] =\r\n{\r\n    { \"SMS\",    DRV_SMS    },\r\n    { \"GG\\0\",   DRV_GG     },\r\n    { \"SG1\",    DRV_SG1000 },\r\n    { \"SC3\",    DRV_SC3000 },\r\n    { \"SF7\",    DRV_SF7000 },\r\n    { \"OMV\",    DRV_SG1000 },\r\n    { \"COL\",    DRV_COLECO },\r\n    { \"\",       -1         },\r\n};\r\n\r\nint         DB_FindDriverIdByName(const char* name)\r\n{\r\n    for (int i = 0; DB_SystemTable[i].driver_id != -1; i++)\r\n        if (!strcmp(name, DB_SystemTable[i].name))\r\n            return (DB_SystemTable[i].driver_id);\r\n    return (-1);\r\n}\r\n\r\nconst char*  DB_FindDriverNameById(int id)\r\n{\r\n    for (int i = 0; DB_SystemTable[i].driver_id != -1; i++)\r\n        if (DB_SystemTable[i].driver_id == id)\r\n            return (DB_SystemTable[i].name);\r\n    return NULL;\r\n}\r\n\r\nstatic struct\r\n{\r\n    char    name[3];\r\n    int     country_flag;\r\n} DB_CountryTable[] = \r\n{\r\n    { \"EU\", DB_COUNTRY_EU   },\r\n    { \"US\", DB_COUNTRY_US   },\r\n    { \"JP\", DB_COUNTRY_JP   },\r\n    { \"BR\", DB_COUNTRY_BR   },\r\n    { \"KR\", DB_COUNTRY_KR   },\r\n    { \"HK\", DB_COUNTRY_HK   },\r\n    { \"AU\", DB_COUNTRY_AU   },\r\n    { \"NZ\", DB_COUNTRY_NZ   },\r\n    { \"FR\", DB_COUNTRY_FR   },\r\n    { \"PT\", DB_COUNTRY_PT   },\r\n    { \"DE\", DB_COUNTRY_DE   },\r\n    { \"IT\", DB_COUNTRY_IT   },\r\n    { \"SP\", DB_COUNTRY_SP   },\r\n    { \"SW\", DB_COUNTRY_SW   },\r\n    { \"CH\", DB_COUNTRY_CH   },\r\n    { \"UK\", DB_COUNTRY_UK   },\r\n    { \"CA\", DB_COUNTRY_CA   },\r\n    { \"TW\", DB_COUNTRY_TW   },\r\n    { \"\",   -1              },\r\n};\r\n\r\nint  DB_FindCountryFlagByName(const char* name)\r\n{\r\n    for (int i = 0; DB_CountryTable[i].country_flag != -1; i++)\r\n        if (!strcmp(name, DB_CountryTable[i].name))\r\n            return (DB_CountryTable[i].country_flag);\r\n    return (-1);\r\n}\r\n\r\nconst char* DB_FindCountryNameByFlag(int country_flag)\r\n{\r\n    for (int i = 0; DB_CountryTable[i].country_flag != -1; i++)\r\n        if (country_flag == DB_CountryTable[i].country_flag)\r\n            return (DB_CountryTable[i].name);\r\n    return NULL;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// DB_Entry_New (int system, u32 crc32, t_meka_crc* mekacrc)\r\n// Create and initialize a new DB entry\r\n//-----------------------------------------------------------------------------\r\nt_db_entry*     DB_Entry_New (int system, u32 crc32, t_meka_crc* mekacrc)\r\n{\r\n    t_db_entry* entry = (t_db_entry*)Memory_Alloc(sizeof (t_db_entry));\r\n\r\n    // Initialize\r\n    entry->system       = system;\r\n    entry->crc_crc32    = crc32;\r\n    entry->crc_mekacrc  = *mekacrc;\r\n    entry->names        = NULL;\r\n    entry->country      = 0;\r\n    entry->flags        = 0;\r\n    entry->product_no   = NULL;\r\n    entry->version      = NULL;\r\n    entry->comments     = NULL;\r\n    entry->authors      = NULL;\r\n    entry->trans_country= -1;\r\n    entry->emu_country  = -1;\r\n    entry->emu_inputs   = -1;\r\n    entry->emu_iperiod  = -1;\r\n    entry->emu_mapper   = -1;\r\n    entry->emu_tvtype   = -1;\r\n    entry->emu_vdp_model= -1;\r\n    entry->emu_lightphaser_emu_func = -1;\r\n\r\n    return (entry);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DB_Entry_Delete (t_db_entry* entry)\r\n// Delete given DB Entry\r\n//-----------------------------------------------------------------------------\r\nvoid            DB_Entry_Delete (t_db_entry* entry)\r\n{\r\n    if (entry->names != NULL)\r\n    {\r\n        t_db_name* dbname = entry->names;\r\n        while (dbname != NULL)\r\n        {\r\n            t_db_name* next = dbname->next;\r\n            DB_Name_Delete (dbname);\r\n            dbname = next;\r\n        }\r\n    }\r\n    if (entry->product_no != NULL)\r\n        free (entry->product_no);\r\n    if (entry->version != NULL)\r\n        free (entry->version);\r\n    if (entry->comments != NULL)\r\n        free (entry->comments);\r\n    if (entry->authors != NULL)\r\n        free (entry->authors);\r\n    free (entry);\r\n}\r\n\r\n// Create and initialize a new DB Name, then add into a DB Entry\r\nt_db_name*     DB_Name_New(t_db_entry* entry, char* name, int country, int non_latin)\r\n{\r\n    t_db_name* dbname = (t_db_name*)Memory_Alloc(sizeof (t_db_name));\r\n\r\n    // Initialize\r\n    dbname->name        = name;\r\n    dbname->country     = country;\r\n    dbname->non_latin   = non_latin;\r\n    dbname->next        = NULL;\r\n\r\n    // Add at end of entry chained list (Note: this is a relatively slow operation)\r\n    if (entry->names == NULL)\r\n    {\r\n        entry->names = dbname;\r\n    }\r\n    else\r\n    {\r\n        t_db_name* previous = entry->names;\r\n        while (previous->next != NULL)\r\n            previous = previous->next;\r\n        previous->next = dbname;\r\n    }\r\n\r\n    return (dbname);\r\n}\r\n\r\n// Delete given DB Name\r\nvoid            DB_Name_Delete (t_db_name* dbname)\r\n{\r\n    free (dbname->name);\r\n    free (dbname);\r\n}\r\n\r\n// Initialize and load Meka database\r\nbool            DB_Init(const char* filename, bool verbose)\r\n{\r\n    DB.entries                      = NULL;\r\n    DB.entries_counter_format_old   = 0;\r\n    DB.entries_counter_format_new   = 0;\r\n\r\n    DB.current_entry = NULL;\r\n    return DB_Load(filename, verbose);\r\n}\r\n\r\n// Load DB entry from given line\r\nstatic int      DB_Load_Entry (char* line)\r\n{\r\n    t_db_entry* entry;\r\n    int         value;\r\n    u32         crc_crc32;\r\n    t_meka_crc  crc_mekacrc;\r\n    char*       w;\r\n    char        buf[1024+1];\r\n\r\n    // Get system\r\n    // FIXME: linear research with strcmp. Could be int compared, or even hashed.\r\n    parse_getword(buf, 4, &line, \" \\t\", ';');\r\n    value = DB_FindDriverIdByName(buf);\r\n    if (value == -1)\r\n        return (1); // Silent return if there's anything else than a system\r\n\r\n    parse_skip_spaces (&line);\r\n    // printf(\"line: %s\\n\", line);\r\n\r\n    // Get CRC32 & MekaCRC\r\n    if (sscanf (line, \"%08x %08X%08X\", &crc_crc32, &crc_mekacrc.v[0], &crc_mekacrc.v[1]) != 3)\r\n        return (0);\r\n    line += 8 + 1 + 16;\r\n    parse_skip_spaces (&line);\r\n\r\n    // Create and add entry to global list\r\n    entry = DB_Entry_New (value, crc_crc32, &crc_mekacrc); // value hold system\r\n    list_add (&DB.entries, entry);\r\n    DB.entries_counter_format_new++;\r\n\r\n    // Get and add default name\r\n    if (!(w = parse_getword(NULL, 0, &line, \"/\", ';')))\r\n        return (0);\r\n    DB_Name_New (entry, w, 0, FALSE);\r\n\r\n    // Parse optional parameters\r\n    while ((w = parse_getword(buf, 1024, &line, \"=/\", ';')) != NULL)\r\n    {\r\n        StrUpper(w);\r\n        // printf (\"field '%s'\\n\", w);\r\n\r\n        if (!strncmp (w, \"NAME_\", 5))\r\n        {\r\n            w += 5;\r\n            if ((value = DB_FindCountryFlagByName(w)) == -1)\r\n                return (0);\r\n            if (!(w = parse_getword(NULL, 0, &line, \"/\", ';')))\r\n                break;\r\n            DB_Name_New (entry, w, value, FALSE);\r\n            // printf(\"adding country %d name %s\", value, w);\r\n        }\r\n        else if (!strcmp(w, \"COUNTRY\"))\r\n        {\r\n            while (line[-1] == ',' || line[-1] == '=')\r\n            {\r\n                if (!(w = parse_getword(buf, 3, &line, \",/\", ';')))\r\n                    return (0);\r\n                if ((value = DB_FindCountryFlagByName(w)) == -1)\r\n                    return (0);\r\n                entry->country |= value;\r\n            }\r\n        }\r\n        else if (!strcmp(w, \"PRODUCT_NO\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->product_no = w;\r\n        }\r\n        else if (!strcmp(w, \"EMU_COUNTRY\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \",/\", ';')))\r\n                return (0);\r\n            entry->emu_country = atoi(w);\r\n        }\r\n        else if (!strcmp(w, \"EMU_INPUTS\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            StrLower(w);\r\n            if (!strcmp(w, \"joypad\"))\r\n                entry->emu_inputs = INPUT_JOYPAD;\r\n            else if (!strcmp(w, \"lightphaser\"))\r\n                entry->emu_inputs = INPUT_LIGHTPHASER;\r\n            else if (!strcmp(w, \"paddle\"))\r\n                entry->emu_inputs = INPUT_PADDLECONTROL;\r\n            else if (!strcmp(w, \"sportspad\"))\r\n                entry->emu_inputs = INPUT_SPORTSPAD;\r\n            else if (!strcmp(w, \"tvoekaki\"))\r\n                entry->emu_inputs = INPUT_GRAPHICBOARD;\r\n            else if (!strcmp(w, \"graphicboardv2\"))\r\n                entry->emu_inputs = INPUT_GRAPHICBOARD_V2;\r\n            else\r\n                return (0);\r\n        }\r\n        else if (!strcmp(w, \"EMU_IPERIOD\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->emu_iperiod = atoi(w);\r\n        }\r\n        else if (!strcmp(w, \"EMU_MAPPER\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->emu_mapper = atoi(w);\r\n        }\r\n        else if (!strcmp(w, \"EMU_LP_FUNC\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->emu_lightphaser_emu_func = atoi(w);\r\n        }\r\n        else if (!strcmp(w, \"EMU_VDP\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            if ((entry->emu_vdp_model = VDP_Model_FindByName(w)) == -1)\r\n                return (0);\r\n        }\r\n        else if (!strcmp(w, \"EMU_TVTYPE\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            StrLower(w);\r\n            if (!strcmp(w, \"pal\"))\r\n                entry->emu_tvtype = TVTYPE_PAL_SECAM;\r\n            else if (!strcmp(w, \"ntsc\"))\r\n                entry->emu_tvtype = TVTYPE_NTSC;\r\n            else\r\n                return (0);\r\n        }\r\n        else if (!strcmp(w, \"EMU_3D\"))\r\n            entry->flags |= DB_FLAG_EMU_3D;\r\n        else if (!strcmp(w, \"EMU_SPRITE_FLICKER\"))\r\n            entry->flags |= DB_FLAG_EMU_SPRITE_FLICKER;\r\n        else if (!strcmp(w, \"COMMENT\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->comments = w;\r\n        }\r\n        else if (!strcmp(w, \"FLAGS\"))\r\n        {\r\n            while (line[-1] == ',' || line[-1] == '=')\r\n            {\r\n                if (!(w = parse_getword(buf, 16, &line, \",/\", ';')))\r\n                    return (0);\r\n                if      (!strcmp(w, \"BAD\"))        entry->flags |= DB_FLAG_BAD;\r\n                else if (!strcmp(w, \"BIOS\"))       entry->flags |= DB_FLAG_BIOS;\r\n                else if (!strcmp(w, \"SMSGG_MODE\")) entry->flags |= DB_FLAG_SMSGG_MODE;\r\n                else if (!strcmp(w, \"HACK\"))       entry->flags |= DB_FLAG_HACK;\r\n                else if (!strcmp(w, \"TRANS\"))      entry->flags |= DB_FLAG_TRANS;\r\n                else if (!strcmp(w, \"PROTO\"))      entry->flags |= DB_FLAG_PROTO;\r\n                else if (!strcmp(w, \"HOMEBREW\"))   entry->flags |= DB_FLAG_HOMEBREW;\r\n                else return (0);\r\n            }\r\n        }\r\n        else if (!strcmp(w, \"TRANS\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \"/\", ';')))\r\n                return (0);\r\n            // In TRANS field only, 'EN' can be specified. It currently gets the UK flag.\r\n            if (!strcmp(w, \"EN\"))\r\n                value = DB_COUNTRY_UK;\r\n            else if ((value = DB_FindCountryFlagByName(w)) == -1)\r\n                return (0);\r\n            entry->trans_country = value;\r\n        }\r\n        else if (!strcmp(w, \"AUTHORS\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->authors = w;\r\n        }\r\n        else if (!strcmp(w, \"VERSION\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \"/\", ';')))\r\n                return (0);\r\n            entry->version = w;\r\n        }\r\n        else\r\n        {\r\n            // No error for empty fields (\",,\")\r\n            // This is mainly to handle end of line comments (\"FIELD=heh    ; comment\")\r\n            if (strlen(w) > 0)\r\n                return (0);\r\n        }\r\n    }\r\n\r\n    // Ok\r\n    return (1);\r\n}\r\n\r\n// Load DB entry in old format from given line\r\nstatic int      DB_Load_EntryOldFormat(char* line)\r\n{\r\n    t_db_entry* entry;\r\n    t_meka_crc  mekacrc;\r\n    char*       w;\r\n    char        buf[1024+1];\r\n\r\n    // Get MekaCRC\r\n    sscanf (line, \"%08X%08X\", &mekacrc.v[0], &mekacrc.v[1]);\r\n    line += 16 + 1;\r\n\r\n    // Get name\r\n    if (!(w = parse_getword(NULL, 0, &line, \",\", ';')))\r\n        return (0);\r\n\r\n    // Create and add entry to global list\r\n    // Note that the old format doesn't store system nor crc32\r\n    entry = DB_Entry_New (-1, 0, &mekacrc);\r\n    list_add (&DB.entries, entry);\r\n    DB.entries_counter_format_old++;\r\n\r\n    // Add default name\r\n    DB_Name_New (entry, w, 0, FALSE);\r\n\r\n    // Parse optional parameters\r\n    while ((w = parse_getword(buf, 1024, &line, \"=,\", ';')) != NULL)\r\n    {\r\n        StrUpper(w);\r\n        // printf (\"field '%s'\\n\", w);\r\n        if (!strcmp(w, \"JAPNAME\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \",\", ';')))\r\n                return (0);\r\n            DB_Name_New (entry, w, DB_COUNTRY_JP, FALSE);\r\n        }\r\n        else if (!strcmp(w, \"VER\"))\r\n        {\r\n            // In the old format, the 'VER' field holds both COUNTRY and VERSION\r\n            char* wp;\r\n            if (!(w = parse_getword(buf, 1024, &line, \",\", ';')))\r\n                return (0);\r\n\r\n            wp = buf;\r\n            // printf(\"VER = %s\\n\", wp);\r\n\r\n            // Get COUNTRY part\r\n            if      (!strnicmp (wp, \"Brazilian\", 9))\r\n            {   wp += 9; entry->country |= DB_COUNTRY_BR; }\r\n            else if (!strnicmp (wp, \"English\",   7))\r\n            {   wp += 7; entry->country |= DB_COUNTRY_EU | DB_COUNTRY_US; }\r\n            else if (!strnicmp (wp, \"European\",  8))\r\n            {   wp += 8; entry->country |= DB_COUNTRY_EU; }\r\n            else if (!strnicmp (wp, \"Export\",    6))\r\n            {   wp += 6; entry->country |= DB_COUNTRY_EU | DB_COUNTRY_US; }\r\n            else if (!strnicmp (wp, \"French\",    6))\r\n            {   wp += 6; entry->country |= DB_COUNTRY_FR; }\r\n            else if (!strnicmp (wp, \"Hong-Kong\", 9))\r\n            {   wp += 9; entry->country |= DB_COUNTRY_HK; }\r\n            else if (!strnicmp (wp, \"International\", 13))\r\n            {   wp += 13;   }\r\n            else if (!strnicmp (wp, \"Japanese\",  8))\r\n            {   wp += 8; entry->country |= DB_COUNTRY_JP; }\r\n            else if (!strnicmp (wp, \"Korean\",    6))\r\n            {   wp += 6; entry->country |= DB_COUNTRY_KR; }\r\n            else if (!strnicmp (wp, \"USA\",       3))\r\n            {   wp += 3; entry->country |= DB_COUNTRY_US; }\r\n            // else\r\n            //    printf(\"Unknown country in version!\");\r\n            \r\n            // If there's anything left after known countries, it goes to VERSION\r\n            if (*wp != EOSTR)\r\n            {\r\n                parse_skip_spaces (&wp);\r\n                entry->version = strdup (wp);\r\n                // printf(\"--> NEW VERSION = '%s'\\n\", entry->version);\r\n            }\r\n        }\r\n        else if (!strcmp(w, \"BAD\"))\r\n            entry->flags |= DB_FLAG_BAD;\r\n        else if (!strcmp(w, \"HACK\"))\r\n            entry->flags |= DB_FLAG_HACK;\r\n        else if (!strcmp(w, \"BIOS\"))\r\n            entry->flags |= DB_FLAG_BIOS;\r\n        else if (!strcmp(w, \"PROTO\"))\r\n            entry->flags |= DB_FLAG_PROTO;\r\n        else if (!strcmp(w, \"3D\"))\r\n            entry->flags |= DB_FLAG_EMU_3D;\r\n        else if (!strcmp(w, \"FLICKER\"))\r\n            entry->flags |= DB_FLAG_EMU_SPRITE_FLICKER;\r\n        else if (!strcmp(w, \"COMMENT\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \",\", ';')))\r\n                return (0);\r\n            entry->comments = w;\r\n        }\r\n        else if (!strcmp(w, \"ID\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \",\", ';')))\r\n                return (0);\r\n            entry->product_no = w;\r\n        }\r\n        else if (!strcmp(w, \"MAPPER\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \",\", ';')))\r\n                return (0);\r\n            entry->emu_mapper = atoi(w);\r\n        }\r\n        else if (!strcmp(w, \"TRANS\"))\r\n        {\r\n            int value;\r\n            if (!(w = parse_getword(buf, 1024, &line, \",\", ';')))\r\n                return (0);\r\n            // In TRANS field only, 'EN' can be specified. It currently gets the UK flag.\r\n            if (!strcmp(w, \"EN\"))\r\n                value = DB_COUNTRY_UK;\r\n            else\r\n                if ((value = DB_FindCountryFlagByName(w)) == -1)\r\n                    return (0);\r\n            entry->trans_country = value;\r\n            entry->flags |= DB_FLAG_TRANS;\r\n        }\r\n        else if (!strcmp(w, \"TVTYPE\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \",\", ';')))\r\n                return (0);\r\n            StrLower(w);\r\n            if (!strcmp(w, \"pal\") || !strcmp(w, \"secam\") || !strcmp(w, \"pal/secam\"))\r\n                entry->emu_tvtype = TVTYPE_PAL_SECAM;\r\n            else if (!strcmp(w, \"ntsc\"))\r\n                entry->emu_tvtype = TVTYPE_NTSC;\r\n            else\r\n                return (0);\r\n        }\r\n        else if (!strcmp(w, \"AUTHORS\"))\r\n        {\r\n            if (!(w = parse_getword(NULL, 0, &line, \",\", ';')))\r\n                return (0);\r\n            entry->authors = w;\r\n        }\r\n        else if (!strcmp(w, \"DATE\"))\r\n        {\r\n            if (!(w = parse_getword(buf, 1024, &line, \",\", ';')))\r\n                return (0);\r\n            // FIXME: yet ignored\r\n        }\r\n        else\r\n            return (0); // Unknown field\r\n    }\r\n\r\n    // Ok\r\n    return (1);\r\n}\r\n\r\n// Process one line loading\r\nstatic int      DB_Load_Line (char* line)\r\n{\r\n    int         i;\r\n    int         ret;\r\n\r\n    // printf(\"line: %s\\n\", line);\r\n\r\n    // Detect DB entry format\r\n    for (i = 0; i < 16; i++)\r\n        if (!isxdigit(line[i]))\r\n            break;\r\n    if (i == 16 && line[16] == ',')\r\n        ret = DB_Load_EntryOldFormat (line);\r\n    else\r\n        ret = DB_Load_Entry (line);\r\n\r\n    // Ok\r\n    return (ret);\r\n}\r\n\r\n// Initialize and load given Meka DB file\r\nstatic bool     DB_Load (const char* filename, bool verbose)\r\n{\r\n    if (verbose)\r\n        ConsolePrint(Msg_Get(MSG_DB_Loading));\r\n\r\n    // Open and read file\r\n    t_tfile* tf = tfile_read (filename);\r\n    if (tf == NULL)\r\n    {\r\n        ConsolePrintf (\"%s\\n\", meka_strerror());\r\n        return false;\r\n    }\r\n\r\n    // Ok\r\n    if (verbose)\r\n        ConsolePrint(\"\\n\");\r\n\r\n    // Parse each line\r\n    int line_cnt = 0;\r\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        line_cnt += 1;\r\n        char* line = (char*)lines->elem;\r\n\r\n        // Strip comments\r\n        // FIXME\r\n        // Trim spaces?\r\n        // FIXME\r\n        // Skip empty lines\r\n        //if (line[0] == EOSTR)\r\n        //    continue;\r\n\r\n        if (DB_Load_Line (line) == 0)\r\n        {\r\n            tfile_free(tf); \r\n            Quit_Msg(Msg_Get(MSG_DB_SyntaxError), line_cnt);\r\n        }\r\n    }\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n\r\n    // FIXME - Uncomment for counting progress of DB transition\r\n    //ConsolePrintf (\"ENTRIES NEW = %d, OLD = %d\\n\", DB.entries_counter_format_new, DB.entries_counter_format_old);\r\n    //Quit();\r\n\r\n    return true;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Release all Meka DB data\r\n//-----------------------------------------------------------------------------\r\nvoid            DB_Close()\r\n{\r\n    list_free_custom (&DB.entries, (t_list_free_handler)DB_Entry_Delete);\r\n    DB.entries = NULL;\r\n    DB.current_entry = NULL;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Find DB entry matching given crc32 and/or mekacrc\r\n// Set any parameter to zero for no comparaison\r\n//-----------------------------------------------------------------------------\r\n// FIXME: Could use a map/hash to find data back\r\n// FIXME: Once all DB entries will be converted to new format, MekaCRC should be dropped.\r\n//-----------------------------------------------------------------------------\r\nt_db_entry*     DB_Entry_Find(u32 crc32, const t_meka_crc* mekacrc)\r\n{\r\n    // All given CRC should not be null\r\n    if (!crc32 && (!mekacrc || (!mekacrc->v[0] && !mekacrc->v[1])))\r\n        return (NULL);\r\n\r\n    // Linear find\r\n    for (t_list* list = DB.entries; list != NULL; list = list->next)\r\n    {\r\n        t_db_entry* entry = (t_db_entry*)list->elem;\r\n        if ((!entry->crc_crc32 && mekacrc) || entry->crc_crc32 == crc32)\r\n        {\r\n            if (mekacrc)\r\n            {\r\n                if (entry->crc_mekacrc.v[0] != mekacrc->v[0] || entry->crc_mekacrc.v[1] != mekacrc->v[1])\r\n                    continue;\r\n            }\r\n            return (entry);\r\n        }\r\n    }\r\n\r\n    return (NULL);\r\n}\r\n\r\n// Get current name for current DB entry\r\n// Handle MEKA setting of the current country.\r\nconst char*    DB_Entry_GetCurrentName (const t_db_entry* entry)\r\n{\r\n    // In Japanese country mode, search for a Japanese name\r\n    if (g_config.country == COUNTRY_JAPAN)\r\n    {\r\n        const t_db_name* name = DB_Entry_GetNameByCountry (entry, DB_COUNTRY_JP);\r\n        if (name)\r\n            return (name->name);\r\n    }\r\n\r\n    // Return first name\r\n    return (entry->names->name);\r\n}\r\n\r\n// Find an entry name for given country. May return NULL if not found.\r\nconst t_db_name*    DB_Entry_GetNameByCountry (const t_db_entry* entry, int country)\r\n{\r\n    t_db_name* name = entry->names;\r\n    while (name)\r\n    {\r\n        if (name->country == country)\r\n            return (name);\r\n        name = name->next;\r\n    }\r\n    return (NULL);\r\n}\r\n\r\n// Select flag to display for given DB entry\r\n// Note: this is named 'Select' as it may return nothing, and cannot return\r\n// multiple flags. This is used by the file browser / vlfn system.\r\nint             DB_Entry_SelectDisplayFlag(const t_db_entry* entry)\r\n{\r\n    int         country = entry->country;\r\n\r\n    // Return a flag only for single country games\r\n    switch (country)\r\n    {\r\n    case DB_COUNTRY_AU : return (FLAG_AU);\r\n    case DB_COUNTRY_BR : return (FLAG_BR);\r\n    case DB_COUNTRY_JP : return (FLAG_JP);\r\n    case DB_COUNTRY_KR : return (FLAG_KR);\r\n    case DB_COUNTRY_FR : return (FLAG_FR);\r\n    case DB_COUNTRY_US : return (FLAG_US);\r\n    case DB_COUNTRY_HK : return (FLAG_HK);\r\n    case DB_COUNTRY_NZ : return (FLAG_NZ);\r\n    case DB_COUNTRY_PT : return (FLAG_PT);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_DE : return (FLAG_DE);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_IT : return (FLAG_IT);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_SP : return (FLAG_SP);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_SW : return (FLAG_SW);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_CH : return (FLAG_CH);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_UK : return (FLAG_UK);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_CA : return (FLAG_CA);\r\n    case DB_COUNTRY_TW : return (FLAG_TW);\r\n    case DB_COUNTRY_EU : break;             // No country for Europe only\r\n    }\r\n\r\n    // Special case to account for asian releases\r\n    if (country == (DB_COUNTRY_JP | DB_COUNTRY_KR))\r\n        return FLAG_JP;\r\n    if (country == (DB_COUNTRY_JP | DB_COUNTRY_TW))\r\n        return FLAG_JP;\r\n\r\n    // Do not display a flag\r\n    return (-1);\r\n}\r\n\r\n// Get translation flag for given DB entry\r\nint             DB_Entry_GetTranslationFlag  (const t_db_entry* entry)\r\n{\r\n    switch (entry->trans_country)\r\n    {\r\n    case DB_COUNTRY_AU : return (FLAG_AU);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_BR : return (FLAG_BR);  // Unused in MEKA DataBase -> portuguese is used\r\n    case DB_COUNTRY_JP : return (FLAG_JP);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_KR : return (FLAG_KR);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_FR : return (FLAG_FR);\r\n    case DB_COUNTRY_US : return (FLAG_US);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_HK : return (FLAG_HK);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_NZ : return (FLAG_NZ);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_PT : return (FLAG_PT);\r\n    case DB_COUNTRY_DE : return (FLAG_DE);\r\n    case DB_COUNTRY_IT : return (FLAG_IT);\r\n    case DB_COUNTRY_SP : return (FLAG_SP);\r\n    case DB_COUNTRY_SW : return (FLAG_SW);\r\n    case DB_COUNTRY_CH : return (FLAG_CH);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_EU : return (FLAG_EU);  // Unused in MEKA DataBase\r\n    case DB_COUNTRY_UK : return (FLAG_UK);\r\n    case DB_COUNTRY_CA : return (FLAG_CA);  // Unused in MEKA DataBase\r\n    }\r\n\r\n    return (-1);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/db.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - db.c\r\n// MEKA Database - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Flags\r\n#define DB_FLAG_BAD                 (1 << 0)\r\n#define DB_FLAG_BIOS                (1 << 1)\r\n#define DB_FLAG_HACK                (1 << 2)\r\n#define DB_FLAG_TRANS               (1 << 3)  // A translation is defined as a hack whose primary purpose is translation\r\n#define DB_FLAG_PROTO               (1 << 4)  // Do not apply to HOMEBREW stuff, because they're likely to be often updated\r\n#define DB_FLAG_HOMEBREW            (1 << 5)\r\n#define DB_FLAG_SMSGG_MODE          (1 << 6)\r\n\r\n// Emulation Flags\r\n#define DB_FLAG_EMU_3D              (1 << 7)\r\n#define DB_FLAG_EMU_SPRITE_FLICKER  (1 << 8)\r\n\r\n// Country Flags\r\n#define DB_COUNTRY_EU               (1 << 0)\r\n#define DB_COUNTRY_US               (1 << 1)\r\n#define DB_COUNTRY_JP               (1 << 2)\r\n#define DB_COUNTRY_BR               (1 << 3)\r\n#define DB_COUNTRY_KR               (1 << 4)\r\n#define DB_COUNTRY_HK               (1 << 5)\r\n#define DB_COUNTRY_AU               (1 << 6)\r\n#define DB_COUNTRY_NZ               (1 << 7)\r\n#define DB_COUNTRY_FR               (1 << 8)\r\n#define DB_COUNTRY_PT               (1 << 9)    // Used by translation\r\n#define DB_COUNTRY_DE               (1 << 10)   // Used by translation\r\n#define DB_COUNTRY_IT               (1 << 11)   // Used by translation\r\n#define DB_COUNTRY_SP               (1 << 12)   // Used by translation\r\n#define DB_COUNTRY_SW               (1 << 13)   // Used by translation\r\n#define DB_COUNTRY_CH               (1 << 14)   // Unused now ?\r\n#define DB_COUNTRY_UK               (1 << 15)   // Used by translation\r\n#define DB_COUNTRY_CA               (1 << 16)\r\n#define DB_COUNTRY_TW               (1 << 17)\r\n#define DB_COUNTRY_COUNT_           18\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_db_name\r\n{\r\n    // 16 bytes + name data\r\n    char*           name;                   // UTF-8\r\n    int             country     : 31;       // In this field, only specific LANGUAGE fields are specified (JP,BR,KR,HK) or if the name is different\r\n    int             non_latin   : 1;        // Set if non-latin UTF-8 data. If not set, name is romanized.\r\n    t_db_name*      next;\r\n};\r\n\r\nstruct t_db_entry\r\n{\r\n    // Basic fields (x bytes + names data + version + comment)\r\n    int             system;                 // Parsed to DRV_* definitions, -1 if unknown\r\n    u32             crc_crc32;              // CRC32\r\n    t_meka_crc      crc_mekacrc;            // MekaCRC\r\n    t_db_name*      names;                  // Names (1st is default name)\r\n    int             country;                // Country flags\r\n    int             flags;                  // Flags (see definitions above)\r\n    char*           product_no;             // Product Number\r\n    char*           version;                // Version note\r\n    char*           comments;               // Comments\r\n    char*           authors;                // Author(s)\r\n    int             trans_country;          // Translation country (if applicable)\r\n\r\n    // Emulation purpose (7 bytes)\r\n    // Note that the fields are s8 just to save a bit of memory\r\n    s8              emu_country;            // -1 if auto\r\n    s8              emu_inputs;             // -1 if auto\r\n    s8              emu_mapper;             // -1 if auto\r\n    s8              emu_tvtype;             // -1 if auto\r\n    s8              emu_vdp_model;          // -1 if auto\r\n    s8              emu_lightphaser_emu_func;// -1 if auto\r\n    s16             emu_iperiod;            // -1 if auto\r\n};\r\n\r\nstruct t_db\r\n{\r\n    t_list*         entries;\r\n    int             entries_counter_format_old;\r\n    int             entries_counter_format_new;\r\n    t_db_entry*     current_entry;\r\n};\r\n\r\nextern t_db         DB;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nbool                DB_Init                     (const char* filename, bool verbose = true);\r\nvoid                DB_Close                    ();\r\n\r\nt_db_entry*         DB_Entry_Find               (u32 crc32, const t_meka_crc* mekacrc = NULL);\r\n\r\n//void              DB_Entry_Print              (const t_db_entry* entry);\r\nint                 DB_Entry_SelectDisplayFlag  (const t_db_entry* entry);\r\nconst char*         DB_Entry_GetCurrentName     (const t_db_entry* entry);\r\nconst t_db_name*    DB_Entry_GetNameByCountry   (const t_db_entry* entry, int country);\r\nint                 DB_Entry_GetTranslationFlag (const t_db_entry* entry);\r\n\r\nint                 DB_FindDriverIdByName       (const char* name);\r\nconst char*         DB_FindDriverNameById       (int driver_id);\r\n\r\nint                 DB_FindCountryFlagByName    (const char* name);\r\nconst char*         DB_FindCountryNameByFlag    (int country_flag);\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/debugger.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - debugger.c\n// MEKA Z80 Debugger - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"app_memview.h\"\n#include \"bios.h\"\n#include \"debugger.h\"\n#include \"desktop.h\"\n#include \"g_widget.h\"\n#include \"mappers.h\"\n#include \"libparse.h\"\n#include \"vmachine.h\"\n#include \"z80marat/Z80DebugHelpers.h\"\n#include <ctype.h>\n#include <string.h>\n\n#ifdef MEKA_Z80_DEBUGGER\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define DEBUGGER_APP_TITLE              \"Debugger\"\n#define DEBUGGER_APP_CPUSTATE_LINES     (2)\n\n#define DEBUGGER_WATCH_FLOOD_LIMIT      (50)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_debugger      Debugger;\n\n//-----------------------------------------------------------------------------\n// External declaration\n//-----------------------------------------------------------------------------\n\nint Z80_Disassemble(char *dst, word addr, bool display_symbols, bool display_symbols_for_current_index_registers, bool resolve_indirect_offsets);\nint Z80_Assemble(const char *src, byte dst[8]);\n\n//-----------------------------------------------------------------------------\n// Forward declaration\n//-----------------------------------------------------------------------------\n\nstatic void     Debugger_Applet_Init();\nstatic void     Debugger_Applet_Layout(bool setup);\nstatic void     Debugger_Applet_RedrawState();\nstatic void     Debugger_Applet_UpdateShortcuts();\n\n// Misc\nstatic void     Debugger_Help(const char *cmd);\nstatic void     Debugger_SetTrap(int trap);\nstatic void     Debugger_InputBoxCallback(t_widget *w);\nstatic bool     Debugger_CompletionCallback(t_widget *w);\n\n// Evaluator\nstatic int      Debugger_Eval_GetValue(char **src, t_debugger_value *result);\nbool            Debugger_Eval_ParseConstant(const char *value, t_debugger_value *result, t_debugger_eval_value_format default_format);\nstatic int      Debugger_Eval_ParseExpression(char **expr, t_debugger_value *result);\nstatic bool     Debugger_Eval_ParseVariable(int variable_replacement_flags, const char *var, t_debugger_value *result);\n\nstatic void     Debugger_GetAccessString(int access, char buf[5])\n{\n    char *p = buf;\n    if (access & BREAKPOINT_ACCESS_R)\n        *p++ = 'R';\n    if (access & BREAKPOINT_ACCESS_W)\n        *p++ = 'W';\n    if (access & BREAKPOINT_ACCESS_X)\n        *p++ = 'X';\n    if (access & BREAKPOINT_ACCESS_E)\n        *p++ = 'E';\n    *p = 0;\n}\n\n// Hooks\nstatic void                     Debugger_Hooks_Install();\nstatic void                     Debugger_Hooks_Uninstall();\nstatic void                     Debugger_WrZ80_Hook(register u16 addr, register u8 value);\nstatic u8                       Debugger_RdZ80_Hook(register u16 addr);\nstatic void                     Debugger_OutZ80_Hook(register u16 addr, register u8 value);\nstatic u8                       Debugger_InZ80_Hook(register u16 addr);\n\n// Breakpoints\nstatic void                     Debugger_BreakPoints_List();\nstatic void                     Debugger_BreakPoints_Clear(bool disabled_only);\n//static void                   Debugger_BreakPoints_RefreshCpuExecTraps();\nstatic int                      Debugger_BreakPoints_AllocateId();\nstatic t_debugger_breakpoint *  Debugger_BreakPoints_SearchById(int id);\n\n// Breakpoint\nstatic t_debugger_breakpoint *  Debugger_BreakPoint_Add(int type, int location, int access_flags, int address_start, int address_end, int auto_delete, const char *desc);\nstatic void                     Debugger_BreakPoint_Remove(t_debugger_breakpoint *breakpoint);\nstatic void                     Debugger_BreakPoint_Enable(t_debugger_breakpoint *breakpoint);\nstatic void                     Debugger_BreakPoint_Disable(t_debugger_breakpoint *breakpoint);\nstatic void                     Debugger_BreakPoint_SetDataCompare(t_debugger_breakpoint *breakpoint, int data_compare_length, u8 data_compare_bytes[8]);\nstatic void                     Debugger_BreakPoint_GetSummaryLine(t_debugger_breakpoint *breakpoint, char *buf);\nstatic const char *             Debugger_BreakPoint_GetTypeName(t_debugger_breakpoint *breakpoint);\nstatic bool                     Debugger_BreakPoint_ActivatedVerbose(t_debugger_breakpoint *breakpoint, int access, int addr, int value);\n\n// Symbols\nbool                            Debugger_Symbols_Load();\nstatic void                     Debugger_Symbols_Clear();\nstatic void                     Debugger_Symbols_ListByName(char *search_name);\nstatic void                     Debugger_Symbols_ListByAddr(u32 cpu_addr);\nconst t_debugger_symbol *       Debugger_Symbols_GetFirstByAddr(u32 cpu_addr);\nconst t_debugger_symbol *       Debugger_Symbols_GetLastByAddr(u32 cpu_addr);\nconst t_debugger_symbol *       Debugger_Symbols_GetClosestPreviousByAddr(u32 cpu_addr, int range);\nstatic void                     Debugger_Symbols_Vars_ListByName(char *search_name);\nstatic void                     Debugger_Symbols_Vars_ListByAddr(u32 addr);\n\n// Symbol\nstatic t_debugger_symbol *      Debugger_Symbol_Add(u16 addr, int bank, const char *name);\nstatic void                     Debugger_Symbol_Remove(t_debugger_symbol *symbol);\nstatic int                      Debugger_Symbol_CompareByRomOrCpuAddress(const t_debugger_symbol *symbol1, const t_debugger_symbol *symbol2);\n\n// History\nstatic bool                     Debugger_History_Callback(t_widget *w, int level);\nstatic void                     Debugger_History_AddLine(const char *line_to_add);\nstatic void                     Debugger_History_List(const char *search_term_arg);\n\n// Shortcuts\nstatic void                     Debugger_ShortcutButton_Callback(t_widget* w);\n\n// Values\nstatic void                     Debugger_Value_SetCpuRegister(t_debugger_value *value, const char *name, void *data, int data_size);\nstatic void                     Debugger_Value_SetSymbol(t_debugger_value *value, t_debugger_symbol *symbol, bool rom_addr);\nstatic void                     Debugger_Value_SetComputed(t_debugger_value *value, u32 data, int data_size);\nstatic void                     Debugger_Value_SetDirect(t_debugger_value *value, u32 data, int data_size);\nstatic void                     Debugger_Value_Read(t_debugger_value *value);\nstatic void                     Debugger_Value_Write(t_debugger_value *value, u32 data);\n\n// Reverse Map\nstatic void                     Debugger_ReverseMap(u16 addr);\nstatic int                      Debugger_ReverseMapFindRomAddress(u16 addr, bool* is_bios);\n\n//-----------------------------------------------------------------------------\n// Data - Command Info/Help\n//-----------------------------------------------------------------------------\n\nstruct t_debugger_command_info\n{\n    const char *        command_short;\n    const char *        command_long;\n    const char *        abstract;\n    const char *        description;\n};\n\nstatic t_debugger_command_info              DebuggerCommandInfos[] =\n{\n    {\n        \"S\", \"STEP\",\n        \"Step over\",\n        // Description\n        \"S: Step over\\n\"\n        \"Usage:\\n\"\n        \" S             ; Step over current instruction\\n\"\n        \"Examples:\\n\"\n        \" 0000: CALL $0100\\n\"\n        \" 0003: LD HL, $1FFF\\n\"\n        \" S             ; Resume execution after the call\"\n    },\n    {\n        \"C\", \"CONT\",\n        \"Continue\",\n        // Description\n        \"C/CONT: Continue execution\\n\"\n        \"Usage:\\n\"\n        \" C             ; Continue\\n\"\n        \" C address     ; Continue up to reaching <address>\"\n    },\n    {\n        \"SO\", \"STEPOUT\",\n        \"Continue to next RET instruction\",\n        // Description\n        \"SO/STEPOUT: Continue to next RET* instruction\",\n    },\n    {\n        NULL, \"CLOCK\",\n        \"Display Z80 cycle accumulator\",\n        // Description\n        \"CLOCK: Display Z80 cycle accumulator\\n\"\n        \"Usage:\\n\"\n        \" CLOCK         ; Display cycle accumulator\\n\"\n        \" CLOCK R[ESET] ; Reset cycle accumulator\"\n    },\n    {\n        \"J\", \"JUMP\",\n        \"Jump\",\n        // Description\n        \"J/JUMP: Jump\\n\"\n        \"Usage:\\n\"\n        \" J address     ; Jump to <address>\\n\"\n        \"Examples:\\n\"\n        \" J 0           ; Jump back to $0000 (reset)\\n\"\n        \" J 1000        ; Jump to $1000\\n\"\n        \"Note:\\n\"\n        \" Equivalent to SET PC=address\"\n    },\n    {\n        \"B\", \"BREAK\",\n        \"Manage breakpoints\",\n        // Description\n        \"B/BREAK: Manage breakpoints\\n\"\n        \"Usage:\\n\"\n        \" B address [..address2]         ; Add CPU breakpoint\\n\"\n        \" B [access] [bus] address [=xx] ; Add breakpoint\\n\"\n        \" B LIST                         ; List breakpoints\\n\"\n        \" B REMOVE id                    ; Remove breakpoint <id>\\n\"\n        \" B ENABLE id                    ; Enable breakpoint <id>\\n\"\n        \" B DISABLE id                   ; Disable breakpoint <id>\\n\"\n        \" B CLEAR                        ; Clear breakpoints\\n\"\n        \"Parameters:\\n\"\n        \" address : breakpoint address, can be a range or label\\n\"\n        \" access  : access to trap, any from r/w/x (rwx)\\n\"\n        \" bus     : bus/event, one from cpu/io/vram/pal/rom/line (cpu)\\n\"\n        //\" id      : breakpoint identifier\\n\"\n        \"Examples:\\n\"\n        \" B 0038          ; break when CPU access $0038\\n\"\n        \" B w io 7f       ; break on IO write to $7F\\n\"\n        \" B rx e000..ffff ; break on CPU read/exec from $E000+\\n\"\n        \" B x =0,0,C9     ; break on CPU execution of NOP NOP RET\\n\"\n        \" B w vram 3f00.. ; break on VRAM write to SAT\\n\"\n        \" B w pram 0 =03  ; break on PRAM write of color 0 as $03\\n\"\n        \" B line #13      ; break on display line 13\"\n    },\n    {\n        \"W\", \"WATCH\",\n        \"Watchpoints\",\n        // Description\n        \"W/WATCH: Manage watchpoints\\n\"\n        \"Usage:\\n\"\n        \" Same as B/BREAK.\\n\"\n        \" Watchpoints will display value but won't break.\\n\"\n        \"Examples:\\n\"\n        \" W r io dd      ; watch all IO read from DDh\\n\"\n        \" W w pal 0..    ; watch all palette write\\n\"\n        \" W w pal 0.. =3 ; watch all palette write of red color\"\n        //\"Warning:\\n\"\n        //\" This feature can massively slow down display and fill up logs.\"\n        //\" As a safety measure, disk-logging is disabled for watchpoints\"\n        //\" reports.\"\n    },\n    {\n        \"P\", \"PRINT\",\n        \"Print expression\",\n        // Description\n        \"P/PRINT: Print expression\\n\"\n        \"Usage:\\n\"\n        \" P expr\\n\"\n        \" P expr[,expr,...]\\n\"\n        \"Examples:\\n\"\n        \" P IX,IY       ; print IX and IY registers\\n\"\n        \" P 1200+34     ; print $1234\\n\"\n        \" P %00101010   ; print 42\\n\"\n        \" P HL+(BC*4)   ; print HL+BC*4\\n\"\n        \" P label       ; print label\"\n    },\n    {\n        \"R\", \"REGS\",\n        \"Dump Z80 registers\",\n        // Description\n        \"R/REGS: Dump Z80 registers\\n\"\n        \"Usage:\\n\"\n        \" R\"\n    },\n    {\n        \"SYM\", \"SYMBOLS\",\n        \"Find symbols\",\n        // Description\n        \"SYM/SYMBOLS: Find symbols\\n\"\n        \"Usage:\\n\"\n        \" SYM [name]\\n\"\n        \" SYM @addr\\n\"\n        \"Parameters:\\n\"\n        \" name : symbol name to search for\\n\"\n        \" addr : symbol address to search for\\n\"\n        \"Examples:\\n\"\n        \" SYM vdp         ; search for symbol matching 'vdp'\\n\"\n        \" SYM @HL         ; search for symbol at address HL\"\n    },\n    {\n        NULL, \"VARS\",\n        \"Display variables\",\n        // Description\n        \"VARS: display variables\\n\"\n        \"Variables are symbols declared within a RAM location.\\n\"\n        \"Usage:\\n\"\n        \" VARS [name]\\n\"\n        \" VARS @addr\\n\"\n        \"Parameters:\\n\"\n        \" name : variable/symbol name to search for\\n\"\n        \" addr : variable/symbol address to search for\\n\"\n        \"Examples:\\n\"\n        \" VARS             ; display all variables\\n\"\n        \" VARS player      ; display variables matching 'player'\\n\"\n        \" VARS @HL         ; display variables at address HL\"\n    },\n    {\n        NULL, \"SET\",\n        \"Set Z80 register\",\n        // Description\n        \"SET: Set Z80 register\\n\"\n        \"Usage:\\n\"\n        \" SET register=value [,...]\\n\"\n        \"Parameters:\\n\"\n        \" register : Z80 register name\\n\"\n        \" value    : value to assign to register\\n\"\n        \"Examples:\\n\"\n        \" SET BC=$1234    ; set BC register to $1234\\n\"\n        \" SET DE=HL,HL=0  ; set DE=HL, then zero HL\"\n    },\n    {\n        NULL, \"RMAP\",\n        \"Reverse map Z80 address\",\n        // Description\n        \"RMAP: Reverse map Z80 address\\n\"\n        \"Usage:\\n\"\n        \" RMAP address\\n\"\n        \"Parameters:\\n\"\n        \" address : address in Z80 space\\n\"\n        \"Examples:\\n\"\n        \" RMAP $8001      ; eg: print 'ROM $14001 (Page 5 +0001)'\\n\"\n        \" RMAP $E001      ; eg: print 'RAM $C001'\"\n    },\n    {\n        \"M\", \"MEM\",\n        \"Dump memory\",\n        // Description\n        \"M/MEM: Dump memory\\n\"\n        \"Usage:\\n\"\n        \" M [address] [len]\\n\"\n        \"Parameters:\\n\"\n        \" address : address to dump memory from (PC)\\n\"\n        \" len     : bytes to dump (128)\"\n        \"Examples:\\n\"\n        \" M              ; dump 128 bytes at PC\\n\"\n        \" M HL BC        ; dump BC bytes at HL\"\n    },\n    {\n        \"ST\", \"STACK\",\n        \"Dump stack\",\n        // Description\n        \"ST/STACK: Dump stack\\n\"\n        \"Usage:\\n\"\n        \" ST [len]\\n\"\n        \"Parameters:\\n\"\n        \" len     : bytes to dump (8)\"\n        \"Examples:\\n\"\n        \" ST             ; dump 8 bytes at SP\\n\"\n        \" ST 100         ; dump 100 bytes at SP\"\n    },\n    {\n        \"TR\", \"TRACE\",\n        \"Trace past execution\",\n        // Description\n        \"TR/TRACE: Trace past execution\\n\"\n        \"Usage:\\n\"\n        \" TR [cnt]\\n\"\n        \" TR all         ; trace all (since last clear)\\n\"\n        \" TR clear       ; clear trace log\\n\"\n        \" TR regs        ; toggle dumping extra registers\\n\"\n        \"Parameters:\\n\"\n        \" cnt     : number of previous instruction (16)\"\n    },\n    {\n        \"D\", \"DASM\",\n        \"Disassemble\",\n        // Description\n        \"D/DASM: Disassemble instructions\\n\"\n        \"Usage:\\n\"\n        \" D [address] [cnt]\\n\"\n        \"Parameters:\\n\"\n        \" address : address to disassemble from (PC)\\n\"\n        \" cnt     : number of instruction to disassemble (10)\"\n    },\n    {\n        NULL, \"MEMEDIT\",\n        \"Memory Editor\",\n        // Description\n        \"MEMEDIT: Spawn memory editor\\n\"\n        \"Usage:\\n\"\n        \" MEMEDIT [lines] [cols]\\n\"\n        \"Parameters:\\n\"\n        \" lines : number of lines\\n\"\n        \" cols  : number of columns\"\n    },\n    {\n        \"HI\", \"HISTORY\",\n        \"History\",\n        // Description\n        \"HI/HISTORY: Print/search history\\n\"\n        \"Usage:\\n\"\n        \" HISTORY       ; Print history\\n\"\n        \" HISTORY word  ; Search history\\n\"\n    },\n    {\n        \"H\", \"HELP\",\n        \"Help\",\n        // Description\n        \"H/HELP: Online help\\n\"\n        \"Usage:\\n\"\n        \" H             ; Get general help\\n\"\n        \" H command     ; Get detailed help on a command\"\n    },\n    { 0 }\n};\n\n//-----------------------------------------------------------------------------\n// Data - Bus infos\n//-----------------------------------------------------------------------------\n\nstatic t_debugger_bus_info  DebuggerBusInfos[BREAKPOINT_LOCATION_MAX_] =\n{\n    { BREAKPOINT_LOCATION_CPU,      \"CPU\",  2,  0x0000,     0xFFFF,     BREAKPOINT_ACCESS_RWX,  DEBUGGER_DATA_COMPARE_LENGTH_MAX    },\n    { BREAKPOINT_LOCATION_ROM,      \"ROM\",  3,  0x000000,   0x1FFFFF,   BREAKPOINT_ACCESS_RWX,  DEBUGGER_DATA_COMPARE_LENGTH_MAX    },  // 'addr_max' is updated on media change. NB- 'w' is unusual but it doesn't hurt supporting it?\n    { BREAKPOINT_LOCATION_IO,       \"IO\",   1,  0x00,       0xFF,       BREAKPOINT_ACCESS_RW,   1                                   },\n    { BREAKPOINT_LOCATION_VRAM,     \"VRAM\", 2,  0x0000,     0x3FFF,     BREAKPOINT_ACCESS_RW,   DEBUGGER_DATA_COMPARE_LENGTH_MAX    },\n    { BREAKPOINT_LOCATION_PRAM,     \"PAL\",  1,  0x00,       0x3F,       BREAKPOINT_ACCESS_W,    DEBUGGER_DATA_COMPARE_LENGTH_MAX    },  // 'addr_max' is updated on driver change\n    { BREAKPOINT_LOCATION_LINE,     \"LINE\", 2,  0,          312,        BREAKPOINT_ACCESS_E,    0                                   },  // FIXME: A bit hacky\n};\n\n//-----------------------------------------------------------------------------\n// Data - Applet\n//-----------------------------------------------------------------------------\n\nstruct t_debugger_shortcut\n{\n    const char*         name;\n    const char*         command;\n    t_widget*           button;\n};\n\nstruct t_debugger_app\n{\n    t_gui_box *         box;\n    ALLEGRO_BITMAP *    box_gfx;\n    t_widget *          console;\n    t_widget *          input_box;\n    t_font_id           font_id;\n    int                 font_height;\n    t_frame             frame_disassembly;\n    t_frame             frame_shortcuts;\n    t_frame             frame_cpustate;\n    int                 disassembly_lines;\n\n    std::vector<t_debugger_shortcut>    shortcuts;\n    int                                 shortcuts_freeze;\n};\n\nt_debugger_app          DebuggerApp;\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS\n//-----------------------------------------------------------------------------\n\nvoid        Debugger_Init_Values()\n{\n    Debugger.enabled = FALSE;\n    Debugger.active = FALSE;\n    Debugger.trap_set = FALSE;\n    Debugger.trap_address = (u16)-1;\n    Debugger.stepping = 0;\n    Debugger.stepping_trace_after = 0;\n    Debugger.stepping_out_enable = false;\n    Debugger.stepping_out_stack_ref = 0x0000;\n    Debugger.breakpoints = NULL;\n    memset(Debugger.breakpoints_cpu_space,  0, sizeof(Debugger.breakpoints_cpu_space));\n    memset(Debugger.breakpoints_io_space,   0, sizeof(Debugger.breakpoints_io_space));\n    memset(Debugger.breakpoints_vram_space, 0, sizeof(Debugger.breakpoints_vram_space));\n    memset(Debugger.breakpoints_pram_space, 0, sizeof(Debugger.breakpoints_pram_space));\n    memset(Debugger.breakpoints_line_space, 0, sizeof(Debugger.breakpoints_line_space));\n    Debugger.symbols = NULL;\n    Debugger.symbols_count = 0;\n    memset(Debugger.symbols_cpu_space,  0, sizeof(Debugger.symbols_cpu_space));\n    Debugger.history_max = 99;  // Note: if more than 2 digits, update code in Debugger_History_List()\n    Debugger.history_count = 1;\n    Debugger.history = (t_debugger_history_item*)malloc(sizeof(t_debugger_history_item) * Debugger.history_max);\n    memset(Debugger.history, 0, sizeof(t_debugger_history_item) * Debugger.history_max);\n    Debugger.history_current_index = 0;\n    Debugger.log_file = NULL;\n    Debugger.log_filename = \"debuglog.txt\";\n    Debugger.watch_counter = 0;\n    Debugger.cycle_counter = 0;\n\n    memset(Debugger.cpu_exec_traps, 0, sizeof(Debugger.cpu_exec_traps));\n\n    Debugger.pc_detail_log_show_extra_registers = false;\n\n    Debugger.trackback_scroll_offset = 0;\n\n    // Add Z80 CPU registers variables\n    Debugger.variables_cpu_registers = NULL;\n    {\n        Z80 *cpu = &sms.R;\n        t_debugger_value *value;\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"PC\",   &cpu->PC.W, 16);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"SP\",   &cpu->SP.W, 16);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"AF\",   &cpu->AF.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"A\",    &cpu->AF.B.h, 8);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"BC\",   &cpu->BC.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"B\",    &cpu->BC.B.h, 8);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"C\",    &cpu->BC.B.l, 8);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"DE\",   &cpu->DE.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"D\",    &cpu->DE.B.h, 8);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"E\",    &cpu->DE.B.l, 8);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"HL\",   &cpu->HL.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"H\",    &cpu->HL.B.h, 8);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"L\",    &cpu->HL.B.l, 8);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"IX\",   &cpu->IX.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"IY\",   &cpu->IY.W, 16);\n\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"AF'\",  &cpu->AF1.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"BC'\",  &cpu->BC1.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"DE'\",  &cpu->DE1.W, 16);\n        list_add(&Debugger.variables_cpu_registers, (value = (t_debugger_value*)malloc(sizeof(t_debugger_value))));\n        Debugger_Value_SetCpuRegister(value, \"HL'\",  &cpu->HL1.W, 16);\n    }\n\n    // Note: Some more clearing will be done by Debugger_MachineReset()\n}\n\nstatic void Debugger_Init_LogFile()\n{\n    // Open log file if not already open\n    if (g_config.debugger_log_enabled && Debugger.log_file == NULL)\n    {\n        char filename[FILENAME_LEN];\n        if (!al_filename_exists(g_env.Paths.DebugDirectory))\n            al_make_directory(g_env.Paths.DebugDirectory);\n        sprintf(filename, \"%s/%s\", g_env.Paths.DebugDirectory, Debugger.log_filename);\n        Debugger.log_file = fopen(filename, \"a+t\");\n        if (Debugger.log_file != NULL)\n            fprintf(Debugger.log_file, Msg_Get(MSG_Log_Session_Start), meka_date_getf ());\n    }\n}\n\nvoid        Debugger_Init()\n{\n    ConsolePrintf(\"%s\\n\", Msg_Get(MSG_Debug_Init));\n    Debugger_Applet_Init();\n\n    // Open log file\n    if (Debugger.active)\n        Debugger_Init_LogFile();\n\n    // Print welcome line\n    Debugger_Printf(\"%s\\n\", Msg_Get(MSG_Debug_Welcome));\n    Debugger_Printf(\"Enter H for help. Open HELP menu for details.\\n\");\n    Debugger_Printf(\"Press TAB for completion.\\n\");\n}\n\nvoid        Debugger_Close()\n{\n    if (Debugger.log_file != NULL)\n    {\n        fclose(Debugger.log_file);\n        Debugger.log_file = NULL;\n    }\n    // FIXME-HISTORY: free history lines\n    free(Debugger.history);\n    Debugger.history = NULL;\n}\n\nvoid        Debugger_Enable()\n{\n    Debugger.enabled = TRUE;\n    Debugger.active  = FALSE;\n    Debugger.trap_set = FALSE;\n    Debugger.trap_address = 0x0000;\n}\n\n// Called when the machine gets reseted\nvoid        Debugger_MachineReset()\n{\n    if (!Debugger.active)\n        return;\n\n    // Reset breakpoint on CPU\n    Debugger_Printf(\"%s\\n\", Msg_Get(MSG_Machine_Reset));\n    Debugger_SetTrap(0x0000);\n    sms.R.Trace = 1;\n\n    // Reset trap table\n    // Debugger_BreakPointRefreshCpuExecTraps();\n\n    Debugger.pc_last = 0;\n    memset(Debugger.pc_exec_points, 0, sizeof(Debugger.pc_exec_points));\n    Debugger.pc_detail_log_data.resize(64*1024); // 256 KB buffer\n    Debugger.pc_detail_log_data[Debugger.pc_detail_log_data.size()-1].pc = 0xffff;\n    Debugger.pc_detail_log_head = 0;\n    Debugger.pc_detail_log_count = 0;\n\n    // Hook Z80 read/write and I/O\n    Debugger_Hooks_Install();\n\n    // Update PRAM size\n    if (g_driver->id == DRV_GG)\n        DebuggerBusInfos[BREAKPOINT_LOCATION_PRAM].addr_max = 0x3F;\n    else\n        DebuggerBusInfos[BREAKPOINT_LOCATION_PRAM].addr_max = 0x1F;\n\n    // Reset cycle counter\n    Debugger.cycle_counter = 0;\n}\n\n// Called when the media (ROM) gets changed/reloaded\nvoid        Debugger_MediaReload()\n{\n    if (!Debugger.enabled)\n        return;\n\n    // Update ROM size\n    DebuggerBusInfos[BREAKPOINT_LOCATION_ROM].addr_max = (tsms.Size_ROM - 1);\n\n    // Reload symbols\n    Debugger_Symbols_Load();\n}\n\nvoid    Debugger_Update()\n{\n    if (Debugger.active)\n    {\n        // If skin has changed, redraw everything\n        t_debugger_app* app = &DebuggerApp;\n        if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\n        {\n            Debugger_Applet_Layout(FALSE);\n            app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\n        }\n        Debugger_Applet_UpdateShortcuts();\n        Debugger_Applet_RedrawState();\n    }\n\n    // Reset watch counter\n    Debugger.watch_counter = 0;\n}\n\nvoid    Debugger_Applet_UpdateShortcuts()\n{\n    t_debugger_app* app = &DebuggerApp;\n\n    if (app->shortcuts_freeze > 0)\n    {\n        // We intentionally skip 1 update on simple STEP operation to avoid flickering buttons\n        app->shortcuts_freeze--;\n        return;\n    }\n\n    app->shortcuts[0].command = (bool)(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)) ? \"C\" : \"STEPINTO\";\n    widget_button_set_label(app->shortcuts[0].button, (bool)(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)) ? \"Cont\" : \"Stop\");\n    widget_button_set_grayed_out(app->shortcuts[0].button, !(bool)(g_machine_flags & (MACHINE_POWER_ON)));\n    widget_button_set_grayed_out(app->shortcuts[1].button, !(bool)(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)));\n    widget_button_set_grayed_out(app->shortcuts[2].button, !(bool)(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)));\n    widget_button_set_grayed_out(app->shortcuts[3].button, !(bool)(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)));\n    widget_button_set_grayed_out(app->shortcuts[4].button, !(bool)(g_machine_flags & (MACHINE_POWER_ON)));\n}\n\nint     Debugger_Hook(Z80 *R)\n{\n    const u16 pc = R->PC.W;\n    // Debugger_Printf(\"hook, pc=%04X\\n\", pc);\n\n    // If in stepping, disable current hook/breakpoint\n    // Note that the stepping flag is reseted after each opcode execution, so it\n    // only serves to avoid getting repeated breakpoint on the same location and\n    // unable to \"leave\" the instruction.\n    if (Debugger.stepping)\n    {\n        R->Trace = Debugger.stepping_trace_after;\n        Debugger.stepping = 0;\n        return (1);\n    }\n\n    // Always remove stepping flag, so we can break at another point\n    // eg: if we stepped on a CALL instruction, or if an interrupt was raised\n    // Debugger.stepping = -1;\n\n    // If we arrived from a trap, print a line about it\n    if (pc == Debugger.trap_address)\n        Debugger_Printf(\"Break at $%04X\\n\", pc);\n\n    // If we arrived from a breakpoint CPU exec trap...\n    if (Debugger.cpu_exec_traps[pc])\n    {\n        int cnt = Debugger.cpu_exec_traps[pc];\n        bool break_activated = FALSE;\n\n        for (t_list* breakpoints = Debugger.breakpoints_cpu_space[pc]; breakpoints != NULL; breakpoints = breakpoints->next)\n        {\n            t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n            if (breakpoint->enabled)\n            {\n                if ((breakpoint->access_flags & BREAKPOINT_ACCESS_X) && (breakpoint->location == BREAKPOINT_LOCATION_CPU || breakpoint->location == BREAKPOINT_LOCATION_ROM) )\n                {\n                    if (Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_X, pc, RdZ80_NoHook(pc)))\n                        break_activated = TRUE;\n                    cnt--;\n                }\n            }\n        }\n        assert(cnt == 0);\n        if (!break_activated && !R->Trace)\n        {\n            //R->Trace = 0;\n            return (1);\n        }\n    }\n\n    if (Debugger.stepping_out_enable)\n    {\n        if (R->SP.W < Debugger.stepping_out_stack_ref)\n            return (1);\n        if (!Z80DebugHelper_IsRetExecuting(R))\n            return (1);\n        Debugger.stepping_out_enable = false;\n    }\n\n    // Update state\n    //Debugger_Applet_UpdateShortcuts();\n    //Debugger_Applet_RedrawState();\n\n    // Set machine in debugging mode (halted)\n    Machine_Debug_Start();\n\n    // Ask Z80 emulator to stop now\n    return (0);\n}\n\nvoid    Debugger_SetTrap(int trap)\n{\n    if (trap == -1)\n    {\n        Debugger.trap_set = FALSE;\n        Debugger.trap_address = (u16)-1;\n        sms.R.Trap = 0xFFFF;\n    }\n    else\n    {\n        Debugger.trap_set = TRUE;\n        Debugger.trap_address = trap;\n        sms.R.Trap = Debugger.trap_address;\n    }\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - Breakpoints Manager\n//-----------------------------------------------------------------------------\n\nvoid    Debugger_BreakPoints_Clear(bool disabled_only)\n{\n    for (t_list* breakpoints = Debugger.breakpoints; breakpoints != NULL; )\n    {\n        t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n        breakpoints = breakpoints->next;\n        if (disabled_only && breakpoint->enabled)\n            continue;\n        Debugger_BreakPoint_Remove(breakpoint);\n    }\n    if (disabled_only)\n        Debugger_Printf(\"Disabled breakpoints cleared.\\n\");\n    else\n        Debugger_Printf(\"Breakpoints cleared.\\n\");\n}\n\nvoid    Debugger_BreakPoints_List()\n{\n    Debugger_Printf(\"Breakpoints/Watchpoints:\\n\");\n    if (Debugger.breakpoints == NULL)\n    {\n        Debugger_Printf(\" <None>\\n\");\n        return;\n    }\n    for (t_list* breakpoints = Debugger.breakpoints; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n        char buf[256];\n        Debugger_BreakPoint_GetSummaryLine(breakpoint, buf);\n        Debugger_Printf(\" %s\\n\", buf);\n    }\n}\n\n// FIXME: May want to find the first empty slot (instead of max+1)\nint     Debugger_BreakPoints_AllocateId()\n{\n    int max = -1;\n    for (t_list* breakpoints = Debugger.breakpoints; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n        if (breakpoint->id > max)\n            max = breakpoint->id;\n    }\n    return (max + 1);\n}\n\nt_debugger_breakpoint *     Debugger_BreakPoints_SearchById(int id)\n{\n    t_list *breakpoints;\n    for (breakpoints = Debugger.breakpoints; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n        if (breakpoint->id == id)\n            return (breakpoint);\n    }\n    return (NULL);\n}\n\n/*\nvoid    Debugger_BreakPoints_RefreshCpuExecTraps()\n{\n    // First clear table\n    memset(Debugger_Z80_PC_Trap, 0, sizeof(Debugger_Z80_PC_Trap));\n\n    // Then go thru all breakpoints to add their trap\n    for (t_list* breakpoints = Debugger.breakpoints; breakpoints != NULL; )\n    {\n        t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n        if (breakpoint->location == BREAKPOINT_LOCATION_CPU)\n            if (breakpoint->access_flags & BREAKPOINT_ACCESS_X)\n            {\n                int addr;\n                for (addr = breakpoint->address_range[0]; addr <= breakpoint->address_range[1]; addr++)// = (addr + 1) & 0xffff)\n                    Debugger_CPU_Exec_Traps[addr]++;\n            }\n    }\n}\n*/\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - Breakpoint\n//-----------------------------------------------------------------------------\n\nt_debugger_breakpoint *     Debugger_BreakPoint_Add(int type, int location, int access_flags, int address_start, int address_end, int auto_delete, const char *desc)\n{\n    t_debugger_breakpoint * breakpoint;\n\n    // Check parameters\n    assert(address_start <= address_end);\n    assert(address_start >= 0);\n    assert(address_end <= DebuggerBusInfos[location].addr_max);\n    assert(type == BREAKPOINT_TYPE_BREAK || type == BREAKPOINT_TYPE_WATCH);\n\n    // Create and setup breakpoint\n    breakpoint = (t_debugger_breakpoint*)malloc(sizeof (t_debugger_breakpoint));\n    breakpoint->enabled = FALSE;\n    breakpoint->id = Debugger_BreakPoints_AllocateId();\n    breakpoint->type = type;\n    breakpoint->location = location;\n    breakpoint->access_flags = access_flags;\n    breakpoint->address_range[0] = address_start;\n    breakpoint->address_range[1] = address_end;\n    breakpoint->auto_delete = auto_delete;\n    breakpoint->data_compare_length = 0;\n    breakpoint->desc = desc ? strdup(desc) : NULL;\n\n    // Add to global breakpoint list\n    list_add_to_end(&Debugger.breakpoints, breakpoint);\n\n    // Enable\n    Debugger_BreakPoint_Enable(breakpoint);\n\n    return (breakpoint);\n}\n\nvoid                        Debugger_BreakPoint_Remove(t_debugger_breakpoint *breakpoint)\n{\n    // Check parameters\n    assert(breakpoint != NULL);\n\n    // Disable\n    Debugger_BreakPoint_Disable(breakpoint);\n\n    // Remove from global breakpoint list\n    list_remove(&Debugger.breakpoints, breakpoint);\n\n    // Delete members\n    if (breakpoint->desc != NULL)\n        free (breakpoint->desc);\n\n    // Delete\n    free(breakpoint);\n}\n\nvoid                     Debugger_BreakPoint_Enable(t_debugger_breakpoint *breakpoint)\n{\n    if (breakpoint->enabled)\n        return;\n\n    // Set flag\n    breakpoint->enabled = true;\n\n    // Add to corresponding bus space list\n    t_list ** bus_lists;\n    switch (breakpoint->location)\n    {\n    case BREAKPOINT_LOCATION_CPU:   bus_lists = Debugger.breakpoints_cpu_space;   break;\n    case BREAKPOINT_LOCATION_ROM:   bus_lists = Debugger.breakpoints_cpu_space;   break;\n    case BREAKPOINT_LOCATION_IO:    bus_lists = Debugger.breakpoints_io_space;    break;\n    case BREAKPOINT_LOCATION_VRAM:  bus_lists = Debugger.breakpoints_vram_space;  break;\n    case BREAKPOINT_LOCATION_PRAM:  bus_lists = Debugger.breakpoints_pram_space;  break;\n    case BREAKPOINT_LOCATION_LINE:  bus_lists = Debugger.breakpoints_line_space;  break;\n    default: assert(0); return;\n    }\n\n    // Add to CPU exec trap?\n    bool cpu_exec_trap = false;\n    if (breakpoint->location == BREAKPOINT_LOCATION_CPU || breakpoint->location == BREAKPOINT_LOCATION_ROM)\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_X)\n            cpu_exec_trap = true;\n\n    if (breakpoint->location == BREAKPOINT_LOCATION_ROM)\n    {\n        // FIXME: Redundant breakpoints will be added if range span over the size of a page\n        // FIXME: Most mapper use 0x4000 sized pages, it would be an optimisation to know this information\n        const int mapper_page_size = 0x2000;\n        const int mapper_bank_count = 0xC000/mapper_page_size;\n        const int addr_min = (int)(breakpoint->address_range[0] & (mapper_page_size-1));\n        const int addr_max = (int)(breakpoint->address_range[1] & (mapper_page_size-1));    // Prewrap both ends of the range to avoid duplicate additions.\n        for (int addr = addr_min; ; addr++)\n        {\n            const u32 addr0 = (u32)(addr & (mapper_page_size-1));\n            for (int i = 0; i != mapper_bank_count; i++)\n            {\n                const u32 addr_candidate = addr0 | (i * mapper_page_size);\n                list_add(&bus_lists[addr_candidate], breakpoint);\n                if (cpu_exec_trap)\n                    Debugger.cpu_exec_traps[addr_candidate]++;\n            }\n            if (addr0 == (u32)addr_max)\n                break;\n        }\n    }\n    else\n    {\n        for (int addr = breakpoint->address_range[0]; addr <= breakpoint->address_range[1]; addr++)\n        {\n            list_add(&bus_lists[addr], breakpoint);\n            if (cpu_exec_trap)\n                Debugger.cpu_exec_traps[addr]++;\n        }\n    }\n}\n\nvoid                     Debugger_BreakPoint_Disable(t_debugger_breakpoint *breakpoint)\n{\n    if (!breakpoint->enabled)\n        return;\n\n    // Set flag\n    breakpoint->enabled = false;\n\n    // Remove from bus space list\n    t_list ** bus_lists;\n    switch (breakpoint->location)\n    {\n    case BREAKPOINT_LOCATION_CPU:   bus_lists = Debugger.breakpoints_cpu_space;   break;\n    case BREAKPOINT_LOCATION_ROM:   bus_lists = Debugger.breakpoints_cpu_space;   break;\n    case BREAKPOINT_LOCATION_IO:    bus_lists = Debugger.breakpoints_io_space;    break;\n    case BREAKPOINT_LOCATION_VRAM:  bus_lists = Debugger.breakpoints_vram_space;  break;\n    case BREAKPOINT_LOCATION_PRAM:  bus_lists = Debugger.breakpoints_pram_space;  break;\n    case BREAKPOINT_LOCATION_LINE:  bus_lists = Debugger.breakpoints_line_space;  break;\n    default: assert(0); return;\n    }\n\n    // Add to CPU exec trap?\n    bool cpu_exec_trap = false;\n    if (breakpoint->location == BREAKPOINT_LOCATION_CPU || breakpoint->location == BREAKPOINT_LOCATION_ROM)\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_X)\n            cpu_exec_trap = true;\n\n    if (breakpoint->location == BREAKPOINT_LOCATION_ROM)\n    {\n        const int mapper_page_size = 0x2000;\n        const int mapper_bank_count = 0xC000/mapper_page_size;\n        const int addr_min = (int)(breakpoint->address_range[0] & (mapper_page_size-1));\n        const int addr_max = (int)(breakpoint->address_range[1] & (mapper_page_size-1));    // Prewrap both ends of the range to avoid duplicate additions.\n        for (int addr = addr_min; ; addr++)\n        {\n            const u32 addr0 = (u32)(addr & (mapper_page_size-1));\n            for (int i = 0; i != mapper_bank_count; i++)\n            {\n                const u32 addr_candidate = addr0 | (i * mapper_page_size);\n                list_remove(&bus_lists[addr_candidate], breakpoint);\n                if (cpu_exec_trap)\n                    Debugger.cpu_exec_traps[addr_candidate]--;\n            }\n            if (addr0 == (u32)addr_max)\n                break;\n        }\n    }\n    else\n    {\n        for (int addr = breakpoint->address_range[0]; addr <= breakpoint->address_range[1]; addr++)\n        {\n            list_remove(&bus_lists[addr], breakpoint);\n            if (cpu_exec_trap)\n                Debugger.cpu_exec_traps[addr]--;\n        }\n    }\n}\n\nvoid                        Debugger_BreakPoint_SetDataCompare(t_debugger_breakpoint *breakpoint, int data_compare_length, u8 data_compare_bytes[8])\n{\n    assert(data_compare_length >= 0 && data_compare_length <= DEBUGGER_DATA_COMPARE_LENGTH_MAX);\n    breakpoint->data_compare_length = data_compare_length;\n    if (data_compare_length != 0)\n        memcpy(breakpoint->data_compare_bytes, data_compare_bytes, data_compare_length);\n}\n\nconst char *                Debugger_BreakPoint_GetTypeName(t_debugger_breakpoint *breakpoint)\n{\n    switch (breakpoint->type)\n    {\n    case BREAKPOINT_TYPE_BREAK:\n        return \"Breakpoint\";\n    case BREAKPOINT_TYPE_WATCH:\n        return \"Watchpoint\";\n    }\n    assert(0);\n    return (\"XXX\");\n}\n\nvoid    Debugger_BreakPoint_GetSummaryLine(t_debugger_breakpoint *breakpoint, char *buf)\n{\n    char    addr_string[16];\n    int     bus_size;\n    t_debugger_bus_info *bus_info = &DebuggerBusInfos[breakpoint->location];\n\n    bus_size = bus_info->bus_addr_size;\n\n    if (breakpoint->address_range[0] != breakpoint->address_range[1])\n        sprintf(addr_string, \"%0*X..%0*X\", bus_size * 2, breakpoint->address_range[0], bus_size * 2, breakpoint->address_range[1]);\n    else\n        sprintf(addr_string, \"%0*X\", bus_size * 2, breakpoint->address_range[0]);\n\n    sprintf(buf, \"%c%d%c %s %-4s  %c%c%c  %-10s  %s\",\n        breakpoint->enabled ? '[' : '(',\n        breakpoint->id,\n        breakpoint->enabled ? ']' : ')',\n        (breakpoint->type == BREAKPOINT_TYPE_BREAK) ? \"Break\" : \"Watch\",\n        bus_info->name,\n        (bus_info->access & (BREAKPOINT_ACCESS_R | BREAKPOINT_ACCESS_E) ?\n            ((breakpoint->access_flags & BREAKPOINT_ACCESS_E) ? ('E') :\n    ((breakpoint->access_flags & BREAKPOINT_ACCESS_R) ? 'R' : '.')) : ' '),\n        (bus_info->access & BREAKPOINT_ACCESS_W ? ((breakpoint->access_flags & BREAKPOINT_ACCESS_W) ? 'W' : '.') : ' '),\n        (bus_info->access & BREAKPOINT_ACCESS_X ? ((breakpoint->access_flags & BREAKPOINT_ACCESS_X) ? 'X' : '.') : ' '),\n        addr_string,\n        (breakpoint->enabled == FALSE) ? \"(disabled) \" : \"\"\n        );\n\n    // Add data compare bytes (if any)\n    if (breakpoint->data_compare_length != 0)\n    {\n        char data_compare_string[1 + (DEBUGGER_DATA_COMPARE_LENGTH_MAX*3) + 2];\n        int pos = 1;\n        int i;\n        strcpy(data_compare_string, \"=\");\n        for (i = 0; i != breakpoint->data_compare_length; i++)\n        {\n            sprintf(&data_compare_string[pos], \"%02X\", breakpoint->data_compare_bytes[i]);\n            pos += 2;\n            if (i + 1 != breakpoint->data_compare_length)\n                data_compare_string[pos++] = ',';\n        }\n        data_compare_string[pos++] = ' ';\n        data_compare_string[pos] = '\\0';\n        strcat(buf, data_compare_string);\n    }\n\n    // Add description (if any)\n    if (breakpoint->desc != NULL)\n        strcat(buf, breakpoint->desc);\n\n    // Trim trailing spaces\n    StrTrimEnd(buf);\n}\n\nbool    Debugger_BreakPoint_ActivatedVerbose(t_debugger_breakpoint *breakpoint, int access, int addr, int value)\n{\n    t_debugger_bus_info *bus_info = &DebuggerBusInfos[breakpoint->location];\n    const char *action;\n    char buf[256];\n\n    // Debugger_Printf(\"Debugger_BreakPoint_ActivatedVerbose() %04x\\n\", addr);\n\n    int rmapped_addr = addr;\n\n    if (breakpoint->location == BREAKPOINT_LOCATION_ROM)\n    {\n        bool is_bios;\n        const int rom_addr = Debugger_ReverseMapFindRomAddress(addr, &is_bios);\n        if (rom_addr == -1)\n            return FALSE;\n        if (rom_addr < breakpoint->address_range[0] || rom_addr > breakpoint->address_range[1])\n            return FALSE;   // False candidate (due to mapping)\n        rmapped_addr = rom_addr;\n    }\n\n    // Data comparer\n    // FIXME\n    if (breakpoint->data_compare_length != 0)\n    {\n        if (breakpoint->data_compare_bytes[0] != value)\n            return false;\n        if (breakpoint->data_compare_length > 1)\n        {\n            int i;\n            for (i = 1; i != breakpoint->data_compare_length; i++)\n            {\n                int value2 = Debugger_Bus_Read(breakpoint->location, rmapped_addr + i);\n                if (value2 != breakpoint->data_compare_bytes[i])\n                    return false;\n            }\n        }\n    }\n\n    // Action\n    if (breakpoint->type == BREAKPOINT_TYPE_BREAK)\n    {\n        // Break\n        sms.R.Trace = 1;\n        Debugger.stepping_out_enable = false;\n        action = \"break\";\n    }\n    else\n    {\n        // Watch\n        if (++Debugger.watch_counter >= DEBUGGER_WATCH_FLOOD_LIMIT)\n        {\n            // Flood?\n            if (Debugger.watch_counter == DEBUGGER_WATCH_FLOOD_LIMIT)\n                Debugger_Printf(\"Maximum number of watch triggered this frame (%d)\\nWill stop displaying more, to prevent flood.\\nConsider removing/tuning your watchpoints.\\n\", DEBUGGER_WATCH_FLOOD_LIMIT);\n            return true;\n        }\n        action = \"watch\";\n    }\n\n    // Verbose to user\n    if (access & BREAKPOINT_ACCESS_R)\n    {\n        sprintf(buf, \"%04X: [%d] %s %s read from %0*X, read value=%02x\",\n            Debugger.pc_last,\n            breakpoint->id,\n            action,\n            bus_info->name,\n            bus_info->bus_addr_size * 2,\n            rmapped_addr,\n            value);\n    }\n    else if (access & BREAKPOINT_ACCESS_W)\n    {\n        sprintf(buf, \"%04X: [%d] %s %s write to %0*X, writing value=%02x\",\n            Debugger.pc_last,\n            breakpoint->id,\n            action,\n            bus_info->name,\n            bus_info->bus_addr_size * 2,\n            rmapped_addr,\n            value);\n    }\n    else if (access & BREAKPOINT_ACCESS_X)\n    {\n        sprintf(buf, \"%04X: [%d] %s %s execution\",\n            Debugger.pc_last,\n            breakpoint->id,\n            action,\n            bus_info->name);\n    }\n    else if (access & BREAKPOINT_ACCESS_E)\n    {\n        sprintf(buf, \"%04X: [%d] %s %s %d event\",\n            Debugger.pc_last,\n            breakpoint->id,\n            action,\n            bus_info->name,\n            rmapped_addr);\n    }\n    else\n    {\n        assert(0);\n    }\n\n    // Print data comparer info\n    if (breakpoint->data_compare_length != 0)\n    {\n        // Only if more than 1 byte or when executed\n        // (because for read/write the byte is already shown on the line)\n        if (breakpoint->data_compare_length >= 2 || (access & (BREAKPOINT_ACCESS_X | BREAKPOINT_ACCESS_E)))\n        {\n            char data_compare_string[8 + (DEBUGGER_DATA_COMPARE_LENGTH_MAX*3) + 2];\n            int pos;\n            int i;\n            strcpy(data_compare_string, \", match \");\n            pos = strlen(data_compare_string);\n            for (i = 0; i != breakpoint->data_compare_length; i++)\n            {\n                sprintf(&data_compare_string[pos], \"%02X\", breakpoint->data_compare_bytes[i]);\n                pos += 2;\n                if (i + 1 != breakpoint->data_compare_length)\n                    data_compare_string[pos++] = ',';\n            }\n            data_compare_string[pos] = '\\0';\n            strcat(buf, data_compare_string);\n        }\n    }\n\n    Debugger_Printf(\"%s\\n\", buf);\n\n    return true;\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - BUS\n//-----------------------------------------------------------------------------\n\nint      Debugger_Bus_Read(int bus, int addr)\n{\n    switch (bus)\n    {\n    case BREAKPOINT_LOCATION_CPU:\n        {\n            addr &= 0xFFFF;\n            return (g_machine_flags & MACHINE_POWER_ON) ? RdZ80_NoHook(addr) : 0x00;\n        }\n    case BREAKPOINT_LOCATION_VRAM:\n        {\n            addr &= 0x3FFF;\n            return VRAM[addr];\n        }\n    case BREAKPOINT_LOCATION_PRAM:\n        {\n            switch (g_machine.driver_id)\n            {\n            case DRV_SMS:   addr &= 31;  break;\n            case DRV_GG:    addr &= 63;  break;\n            default:\n                // FIXME\n                return -1;\n            }\n            return PRAM[addr];\n        }\n    default:\n        {\n            assert(0);\n            return -1;\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - SYMBOLS\n//-----------------------------------------------------------------------------\n\nenum t_debugger_symbol_file_type\n{\n    DEBUGGER_SYMBOL_FILE_TYPE_WLA,\n    DEBUGGER_SYMBOL_FILE_TYPE_SJASM,\n    DEBUGGER_SYMBOL_FILE_TYPE_TASM,\n    DEBUGGER_SYMBOL_FILE_TYPE_MAX_\n};\n\nbool    Debugger_Symbols_TryParseLine(const char* line_original, t_debugger_symbol_file_type symbol_file_type)\n{\n    char line_buf[512];\n    strcpy(line_buf, line_original);\n    char* line = line_buf;\n\n    int bank;\n    u32 addr32;\n    char name[512];\n\n    switch (symbol_file_type)\n    {\n    case DEBUGGER_SYMBOL_FILE_TYPE_WLA:\n        {\n            // NO$GMB/WLA format\n            //  \"0000:c007 VarScanlineMetrics\"\n            if (sscanf(line, \"%X:%X %s\", &bank, &addr32, name) == 3)\n            {\n                Debugger_Symbol_Add(addr32 & 0xFFFF, bank, name);\n                return true;\n            }\n            if (sscanf(line, \"%X %s\", &addr32, name) == 2)\n            {\n                Debugger_Symbol_Add(addr32 & 0xFFFF, -1, name);\n                return true;\n            }\n            break;\n        }\n    case DEBUGGER_SYMBOL_FILE_TYPE_SJASM:\n        {\n            // SJASM format\n            //  \"pause_music: equ 0000074Fh\"\n            if (parse_getword(name, countof(name), &line, \":\\t\\r\\n\", ';', PARSE_FLAGS_NONE))\n            {\n                parse_skip_spaces(&line);\n                if (sscanf(line, \"equ %Xh\", &addr32) == 1)\n                {\n                    Debugger_Symbol_Add(addr32 & 0xFFFF, -1, name);\n                    return true;\n                }\n            }\n            break;\n        }\n    case DEBUGGER_SYMBOL_FILE_TYPE_TASM:\n        {\n            if (parse_getword(name, countof(name), &line, \" \\t\", ';', PARSE_FLAGS_NONE))\n            {\n                parse_skip_spaces(&line);\n                if (sscanf(line, \"%Xh\", &addr32) == 1)\n                {\n                    Debugger_Symbol_Add(addr32 & 0xFFFF, -1, name);\n                    return true;\n                }\n            }\n            break;\n        }\n    default:\n        break;\n    }\n    return false;\n}\n\nbool    Debugger_Symbols_Load()\n{\n    if (!Debugger.enabled)\n        return false;\n\n    // First clear any existing symbol\n    Debugger_Symbols_Clear();\n\n    // Load symbol file\n    // 1. Try \"image.sym\"\n    char symbol_filename[FILENAME_LEN];\n    strcpy(symbol_filename, g_env.Paths.MediaImageFile);\n    StrPath_RemoveExtension(symbol_filename);\n    strcat(symbol_filename, \".sym\");\n    t_tfile* symbol_file = tfile_read(symbol_filename);\n    if (symbol_file == NULL)\n    {\n        // Note: we silently fail on MEKA_ERR_FILE_OPEN (file not found / cannot open)\n        if (meka_errno != MEKA_ERR_FILE_OPEN)\n            Msg(MSGT_USER, \"%s\", meka_strerror());\n\n        // 2. Try \"image.ext.sym\"\n        snprintf(symbol_filename, FILENAME_LEN, \"%s.sym\", g_env.Paths.MediaImageFile);\n        symbol_file = tfile_read(symbol_filename);\n        if (symbol_file == NULL)\n        {\n            if (meka_errno != MEKA_ERR_FILE_OPEN)\n                Msg(MSGT_USER, \"%s\", meka_strerror());\n            return false;\n        }\n    }\n    StrPath_RemoveDirectory(symbol_filename);\n\n    int line_cnt = 0;\n    bool error = false;\n    for (t_list* lines = symbol_file->data_lines; lines; lines = lines->next)\n    {\n        char* line = (char*) lines->elem;\n        line_cnt += 1;\n\n        // Msg(MSGT_DEBUG, \"%s\", line);\n\n        // Strip comments, skip empty lines\n        char* p = strchr(line, ';');\n        if (p != NULL)\n            *p = EOSTR;\n        StrTrim(line);\n        if (StrIsNull(line))\n            continue;\n\n        // Parse\n        bool parse_success = false;\n        for (int symbol_file_type = 0; symbol_file_type != DEBUGGER_SYMBOL_FILE_TYPE_MAX_; symbol_file_type++)\n        {\n            if (Debugger_Symbols_TryParseLine(line, (t_debugger_symbol_file_type)symbol_file_type))\n            {\n                parse_success = true;\n                break;\n            }\n        }\n        if (!parse_success)\n        {\n            if (!error)\n            {\n                error = true;\n                Msg(MSGT_USER, Msg_Get(MSG_Debug_Symbols_Error), symbol_filename);\n            }\n            Msg(MSGT_USER_LOG, Msg_Get(MSG_Debug_Symbols_Error_Line), line_cnt);\n        }\n    }\n\n    // Free symbol file data\n    tfile_free(symbol_file);\n\n    // Sort by address\n    list_sort(&Debugger.symbols, (int (*)(void *, void *))Debugger_Symbol_CompareByRomOrCpuAddress);\n\n    // Verbose\n    char buf[256];\n    sprintf(buf, Msg_Get(MSG_Debug_Symbols_Loaded), Debugger.symbols_count, symbol_filename);\n    Debugger_Printf(\"%s\\n\", buf);\n\n    return (Debugger.symbols_count > 0);\n}\n\nvoid    Debugger_Symbols_Clear()\n{\n    for (t_list* symbols = Debugger.symbols; symbols != NULL; )\n    {\n        t_debugger_symbol *symbol = (t_debugger_symbol *)symbols->elem;\n        symbols = symbols->next;\n        Debugger_Symbol_Remove(symbol);\n    }\n    assert(Debugger.symbols_count == 0);\n}\n\nvoid    Debugger_Symbols_ListByName(char *search_name)\n{\n    if (search_name)\n    {\n        Debugger_Printf(\"Symbols matching \\\"%s\\\":\\n\", search_name);\n        search_name = strdup(search_name);\n        StrUpper(search_name);\n    }\n    else\n    {\n        Debugger_Printf(\"Symbols:\\n\");\n    }\n\n    int count = 0;\n    for (t_list* symbols = Debugger.symbols; symbols != NULL; symbols = symbols->next)\n    {\n        t_debugger_symbol *symbol = (t_debugger_symbol *)symbols->elem;\n\n        // If search_name was specified, skip symbol not matching it\n        if (search_name != NULL)\n            if (strstr(symbol->name_uppercase, search_name) == NULL)\n                continue;\n        count++;\n        Debugger_Printf(\" %04X  %s\\n\", symbol->cpu_addr, symbol->name);\n    }\n    if (count == 0)\n    {\n        Debugger_Printf(\" <None>\\n\");\n    }\n    else\n    {\n        Debugger_Printf(\"%d symbols\\n\", count);\n    }\n    if (search_name != NULL)\n    {\n        // Free the uppercase duplicate we made\n        free(search_name);\n    }\n}\n\nvoid    Debugger_Symbols_ListByAddr(u32 addr_request)\n{\n    addr_request &= 0xFFFF;\n    u32 addr_sym = addr_request;\n    while (addr_sym != (u32)-1)\n    {\n        if (Debugger.symbols_cpu_space[addr_sym] != NULL)\n            break;\n        addr_sym--;\n    }\n\n    if (addr_sym == addr_request || addr_sym == (u32)-1)\n        Debugger_Printf(\"Symbols at address \\\"%04x\\\":\\n\", addr_request);\n    else\n        Debugger_Printf(\"Symbols near address \\\"%04x\\\":\\n\", addr_request);\n\n    if (addr_sym == (u32)-1)\n    {\n        Debugger_Printf(\" <None>\\n\");\n    }\n    else\n    {\n        t_list *symbols;\n        for (symbols = Debugger.symbols_cpu_space[addr_sym]; symbols != NULL; symbols = symbols->next)\n        {\n            t_debugger_symbol *symbol = (t_debugger_symbol *)symbols->elem;\n            if (addr_sym != addr_request)\n                Debugger_Printf(\" %04X  %s + %X = %04X\\n\", symbol->cpu_addr, symbol->name, addr_request - addr_sym, addr_request);\n            else\n                Debugger_Printf(\" %04X  %s\\n\", symbol->cpu_addr, symbol->name);\n        }\n    }\n}\n\nstatic void Debugger_Symbols_Vars_Print(const t_debugger_symbol* symbol, const t_list* next)\n{\n    // Default to 2\n    int var_size = 2;\n    const t_debugger_symbol* symbol_next = next ? (t_debugger_symbol *)next->elem : NULL;\n    if (symbol_next != NULL)\n    {\n        const int offset_to_next_symbol = (int)(symbol_next->cpu_addr - symbol->cpu_addr);\n        if (offset_to_next_symbol < 2)\n            var_size = 1;\n    }\n\n    int var_value = 0;\n    for (int i = 0; i < var_size; i++)\n        var_value |= Debugger_Bus_Read(BREAKPOINT_LOCATION_CPU, (symbol->cpu_addr+i)&0xffff) << (i * 8);\n\n    //char binary_s[2][9];\n    //Write_Bits_Field((var_value >> 0) & 0xFF, 8, binary_s[0]);\n    //Write_Bits_Field((var_value >> 8) & 0xFF, 8, binary_s[1]);\n\n    //if (var_size == 1)\n    Debugger_Printf(\" %04X: %-28s = %-*s$%0*hX  dec: %d\\n\", symbol->cpu_addr, symbol->name, (2-var_size)*2, \"\", var_size*2, var_value, var_value);\n    //else\n    //  Debugger_Printf(\" %04X  %s = $%0*hX  dec: %d, bin: %%%s.%s\\n\", symbol->addr, symbol->name, var_size, var_value, var_value, binary_s[0], binary_s[1]);\n}\n\nvoid    Debugger_Symbols_Vars_ListByName(char *search_name)\n{\n    if (search_name)\n    {\n        Debugger_Printf(\"Variables matching \\\"%s\\\":\\n\", search_name);\n        search_name = strdup(search_name);\n        StrUpper(search_name);\n    }\n    else\n    {\n        Debugger_Printf(\"Variables:\\n\");\n    }\n\n    int ram_len;\n    int ram_start_addr;\n    Mapper_Get_RAM_Infos(&ram_len, &ram_start_addr);\n\n    int count = 0;\n    for (t_list* symbols = Debugger.symbols; symbols != NULL; symbols = symbols->next)\n    {\n        const t_debugger_symbol *symbol = (t_debugger_symbol *)symbols->elem;\n\n        const bool is_in_ram = symbol->cpu_addr >= ram_start_addr && symbol->cpu_addr < ram_start_addr+ram_len;\n        if (!is_in_ram)\n            continue;\n\n        // If search_name was specified, skip symbol not matching it\n        if (search_name != NULL)\n            if (strstr(symbol->name_uppercase, search_name) == NULL)\n                continue;\n        count++;\n\n        Debugger_Symbols_Vars_Print(symbol, symbols->next);\n    }\n\n    if (count == 0)\n    {\n        Debugger_Printf(\" <None>\\n\");\n    }\n    if (search_name != NULL)\n    {\n        // Free the uppercase duplicate we made\n        free(search_name);\n    }\n}\n\nvoid    Debugger_Symbols_Vars_ListByAddr(u32 addr)\n{\n    addr &= 0xFFFF;\n\n    Debugger_Printf(\"Variables at address \\\"%04x\\\":\\n\", addr);\n\n    if (Debugger.symbols_cpu_space[addr] == NULL)\n    {\n        Debugger_Printf(\" <None>\\n\");\n    }\n    else\n    {\n        for (const t_list* symbols = Debugger.symbols_cpu_space[addr]; symbols != NULL; symbols = symbols->next)\n        {\n            t_debugger_symbol *symbol = (t_debugger_symbol*)symbols->elem;\n            Debugger_Symbols_Vars_Print(symbol, symbols->next);\n        }\n    }\n}\n\nconst t_debugger_symbol *     Debugger_Symbols_GetFirstByAddr(u32 cpu_addr)\n{\n    const int rom_addr = Debugger_ReverseMapFindRomAddress((u16)cpu_addr, NULL);\n    for (const t_list* symbols = Debugger.symbols_cpu_space[(u16)cpu_addr]; symbols; symbols = symbols->next)\n    {\n        const t_debugger_symbol* symbol = (const t_debugger_symbol *)symbols->elem;\n        if (rom_addr == -1 || symbol->rom_addr == -1 || rom_addr == symbol->rom_addr)\n            return symbol;\n    }\n    return NULL;\n}\n\n// This function is useful because there's often cases where the programmer sets\n// one 'end' symbol and a following 'start' symbol and they are at the same address.\n// In most of those cases, we want the last one.\nconst t_debugger_symbol *     Debugger_Symbols_GetLastByAddr(u32 cpu_addr)\n{\n    const int rom_addr = Debugger_ReverseMapFindRomAddress((u16)cpu_addr, NULL);\n    const t_debugger_symbol* last_valid_symbol = NULL;\n    for (const t_list* symbols = Debugger.symbols_cpu_space[(u16)cpu_addr]; symbols; symbols = symbols->next)\n    {\n        const t_debugger_symbol* symbol = (const t_debugger_symbol *)symbols->elem;\n        if (rom_addr == -1 || symbol->rom_addr == -1 || rom_addr == symbol->rom_addr)\n            last_valid_symbol = symbol;\n    }\n    return last_valid_symbol;\n}\n\nconst t_debugger_symbol *       Debugger_Symbols_GetClosestPreviousByAddr(u32 addr, int range)\n{\n    while (range >= 0)\n    {\n        const t_debugger_symbol * symbol = Debugger_Symbols_GetLastByAddr(addr);\n        if (symbol != NULL)\n            return symbol;\n        addr--;\n        range--;\n    }\n    return NULL;\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - SYMBOL\n//-----------------------------------------------------------------------------\n\nt_debugger_symbol *     Debugger_Symbol_Add(u16 cpu_addr, int bank, const char *name)\n{\n    // Check parameters\n    assert(name != NULL);\n\n    // Create and setup symbol\n    t_debugger_symbol* symbol = new t_debugger_symbol();\n    symbol->cpu_addr = cpu_addr;\n    symbol->rom_addr = (u32)-1;\n    if (bank == 0)\n        symbol->rom_addr = symbol->cpu_addr;\n    if (bank > 0)\n        symbol->rom_addr = ((bank * 0x4000) + (symbol->cpu_addr & 0x3fff));\n    symbol->bank = bank;\n    symbol->name = strdup(name);\n    symbol->name_uppercase = strdup(name);\n    StrUpper(symbol->name_uppercase);\n\n    // Add to global symbol list and CPU space list\n    list_add(&Debugger.symbols, symbol);\n    list_add_to_end(&Debugger.symbols_cpu_space[symbol->cpu_addr], symbol);\n\n    // Increase global counter\n    Debugger.symbols_count++;\n\n    return (symbol);\n}\n\nvoid    Debugger_Symbol_Remove(t_debugger_symbol *symbol)\n{\n    // Check parameters\n    assert(symbol != NULL);\n    assert(symbol->name);\n    assert(symbol->name_uppercase);\n\n    // Remove from global symbol list and CPU space list\n    list_remove(&Debugger.symbols, symbol);\n    list_remove(&Debugger.symbols_cpu_space[symbol->cpu_addr], symbol);\n\n    // Delete\n    free(symbol->name);\n    free(symbol->name_uppercase);\n    delete symbol;\n\n    // Decrease global counter\n    Debugger.symbols_count--;\n    assert(Debugger.symbols_count >= 0);\n}\n\nint     Debugger_Symbol_CompareByRomOrCpuAddress(const t_debugger_symbol* symbol1, const t_debugger_symbol* symbol2)\n{\n    const u32 addr1 = symbol1->rom_addr == -1 ? symbol1->cpu_addr : symbol1->rom_addr;\n    const u32 addr2 = symbol2->rom_addr == -1 ? symbol2->cpu_addr : symbol2->rom_addr;\n    return (addr1 - addr2);\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - HOOKS\n//-----------------------------------------------------------------------------\n\n// Hook Z80 read/write and I/O\nvoid     Debugger_Hooks_Install()\n{\n    RdZ80 = Debugger_RdZ80_Hook;\n    WrZ80 = Debugger_WrZ80_Hook;\n    InZ80 = Debugger_InZ80_Hook;\n    OutZ80 = Debugger_OutZ80_Hook;\n}\n\n// Unhook Z80 read/write and I/O\nvoid     Debugger_Hooks_Uninstall()\n{\n    RdZ80 = RdZ80_NoHook;\n    WrZ80 = WrZ80_NoHook;\n    InZ80 = InZ80_NoHook;\n    OutZ80 = OutZ80_NoHook;\n}\n\nvoid        Debugger_WrZ80_Hook(register u16 addr, register u8 value)\n{\n    for (t_list* breakpoints = Debugger.breakpoints_cpu_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_W)\n        {\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_W, addr, value);\n        }\n    }\n    WrZ80_NoHook(addr, value);\n}\n\nu8          Debugger_RdZ80_Hook(register u16 addr)\n{\n    const u8 value = RdZ80_NoHook(addr);\n    for (t_list* breakpoints = Debugger.breakpoints_cpu_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_R)\n        {\n            // Special case, if a X handler is installed and we're now executing, ignore R breakpoint\n            // It is not logical but much better for end user, who is likely to use RWX in most cases\n            if (breakpoint->access_flags & BREAKPOINT_ACCESS_X)\n            {\n                if (addr >= Debugger.pc_last && addr <= Debugger.pc_last + 6)   // quick check to 6\n                    if (addr <= Debugger.pc_last + Z80_Disassemble(NULL, Debugger.pc_last, false, false, false))\n                        continue;\n            }\n\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_R, addr, value);\n        }\n    }\n    return (value);\n}\n\nstatic void     Debugger_OutZ80_Hook(register u16 addr, register u8 value)\n{\n    for (t_list* breakpoints = Debugger.breakpoints_io_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_W)\n        {\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_W, addr, value);\n        }\n    }\n    OutZ80_NoHook(addr, value);\n}\n\nstatic u8       Debugger_InZ80_Hook(register u16 addr)\n{\n    const u8 value = InZ80_NoHook(addr);\n    for (t_list* breakpoints = Debugger.breakpoints_io_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_R)\n        {\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_R, addr, value);\n        }\n    }\n    return (value);\n}\n\nvoid            Debugger_RasterLine_Hook(register int line)\n{\n    for (t_list* breakpoints = Debugger.breakpoints_line_space[line]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n\n        // Verbose break/watch point result\n        Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_E, line, 0);\n    }\n}\n\nvoid            Debugger_RdVRAM_Hook(register int addr, register u8 value)\n{\n    for (t_list* breakpoints = Debugger.breakpoints_vram_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_R)\n        {\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_R, addr, value);\n        }\n    }\n}\n\nvoid            Debugger_WrVRAM_Hook(register int addr, register u8 value)\n{\n    for (t_list* breakpoints = Debugger.breakpoints_vram_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_W)\n        {\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_W, addr, value);\n        }\n    }\n}\n\nvoid            Debugger_WrPRAM_Hook(register int addr, register u8 value)\n{\n    for (t_list* breakpoints = Debugger.breakpoints_pram_space[addr]; breakpoints != NULL; breakpoints = breakpoints->next)\n    {\n        t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n        if (breakpoint->access_flags & BREAKPOINT_ACCESS_W)\n        {\n            // Verbose break/watch point result\n            Debugger_BreakPoint_ActivatedVerbose(breakpoint, BREAKPOINT_ACCESS_W, addr, value);\n        }\n    }\n}\n\n// Enable or disable the debugger window and associated processing.\nvoid    Debugger_Switch()\n{\n    // Msg(MSGT_DEBUG, \"Debugger_Switch()\");\n    if (!Debugger.enabled)\n        return;\n\n    Debugger.active ^= 1;\n    gui_box_show(DebuggerApp.box, Debugger.active, true);\n    if (Debugger.active)\n    {\n        gui_menu_check(menus_ID.debug, 0);\n        Machine_Debug_Start();\n        // ??\n        // Meka_Z80_Debugger_SetBreakPoint (Debugger.break_point_address);\n    }\n    else\n    {\n        gui_menu_uncheck_range(menus_ID.debug, 0, 0);\n        Machine_Debug_Stop();\n        sms.R.Trap = 0xFFFF;\n    }\n\n    // Setup/disable hooks\n    if (Debugger.active)\n    {\n        Debugger_Hooks_Install();\n    }\n    else\n    {\n        Debugger_Hooks_Uninstall();\n    }\n\n    // Open log file (if not already open)\n    if (Debugger.active)\n        Debugger_Init_LogFile();\n}\n\nvoid        Debugger_PrintEx(bool debugger, bool log, bool ui, char* buf)\n{\n    // Output to debug console\n    if (debugger)\n    {\n#ifdef ARCH_WIN32\n        OutputDebugString(buf);\n#endif\n    }\n\n    // Log to file\n    if (log)\n    if (Debugger.log_file != NULL)\n    {\n        fprintf(Debugger.log_file, \"%s\", buf);\n        fflush(Debugger.log_file);\n    }\n\n    if (ui)\n    {\n        widget_textbox_print_scroll(DebuggerApp.console, TRUE, buf);\n    }\n}\n\n// Print a formatted line to the debugger console\nvoid        Debugger_Printf(const char *format, ...)\n{\n    char    buf[1024];\n    va_list param_list;\n\n    va_start(param_list, format);\n    vsprintf(buf, format, param_list);\n    va_end(param_list);\n\n    Debugger_PrintEx(true, true, true, buf);\n}\n\n// Initialize the debugger applet\nstatic void Debugger_Applet_Init()\n{\n    t_debugger_app* app = &DebuggerApp;\n\n    t_frame frame;\n\n    // Create box\n    app->font_id = (t_font_id)g_config.font_debugger;\n    app->font_height = Font_Height(app->font_id);\n    frame.pos.x     = 428;\n    frame.pos.y     = 50;\n    frame.size.x    = 380;\n    frame.size.y    = 600;\n\n    app->box = gui_box_new(&frame, DEBUGGER_APP_TITLE);\n    app->box_gfx = app->box->gfx_buffer;\n    app->box->flags |= GUI_BOX_FLAGS_FOCUS_INPUTS_EXCLUSIVE;        // Set exclusive inputs flag to avoid messing with emulation\n    app->box->flags |= GUI_BOX_FLAGS_TAB_STOP;                      // CTRL+TAB stops here\n    app->box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;                  // Can be resized\n    app->box->size_min.x = 220;\n    app->box->size_min.y = 150;\n\n    // Register to desktop (applet is disabled by default)\n    Desktop_Register_Box(\"DEBUGGER\", app->box, FALSE, &Debugger.active);\n\n    // Layout\n    Debugger_Applet_Layout(TRUE);\n}\n\nstatic void     Debugger_Applet_Layout(bool setup)\n{\n    t_debugger_app* app = &DebuggerApp;\n\n    t_frame     frame;\n\n    // Resize\n    int contents_y = app->box->frame.size.y;\n    contents_y -= (1 + 1 + DEBUGGER_APP_CPUSTATE_LINES) * app->font_height;\n    contents_y -= app->font_height + 14; // Shortcut\n    contents_y -= app->font_height + 10; // Input box\n    contents_y -= 2*3;                   // Padding\n\n    // Clear\n    app->box_gfx = app->box->gfx_buffer;\n    al_set_target_bitmap(app->box->gfx_buffer);\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\n\n    // Add closebox widget\n    if (setup)\n        widget_closebox_add(app->box, (t_widget_callback)Debugger_Switch);\n\n    // Add console (textbox widget)\n    frame.pos.x = 6;\n    frame.pos.y = 2;\n    frame.size.x = app->box->frame.size.x - (6*1);\n    frame.size.y = (contents_y * 0.5f);\n    if (setup)\n        app->console = widget_textbox_add(app->box, &frame, app->font_id);\n    else\n        app->console->frame = frame;\n    frame.pos.y += frame.size.y;\n\n    // Add line\n    al_set_target_bitmap(app->box_gfx);\n    al_draw_hline(frame.pos.x, frame.pos.y + app->font_height / 2, frame.pos.x + frame.size.x, COLOR_SKIN_WINDOW_SEPARATORS);\n    frame.pos.y += app->font_height;\n\n    // Setup disassembly frame\n    app->frame_disassembly.pos.x   = frame.pos.x;\n    app->frame_disassembly.pos.y   = frame.pos.y;\n    app->frame_disassembly.size.x  = frame.size.x;\n    app->frame_disassembly.size.y  = contents_y * 0.5f;\n    app->disassembly_lines = MAX(0, (int)floorf(app->frame_disassembly.size.y / (app->font_height+1)));\n    frame.pos.y += app->frame_disassembly.size.y;\n\n    // Add line\n    al_set_target_bitmap(app->box_gfx);\n    al_draw_hline(frame.pos.x, frame.pos.y + app->font_height / 2, frame.pos.x + frame.size.x, COLOR_SKIN_WINDOW_SEPARATORS);\n    frame.pos.y += app->font_height;\n\n    // Shortcuts\n    app->frame_shortcuts.pos.x   = frame.pos.x;\n    app->frame_shortcuts.pos.y   = frame.pos.y;\n    app->frame_shortcuts.size.x  = frame.size.x;\n    app->frame_shortcuts.size.y  = app->font_height + 14;\n    {\n        // FIXME: the code in Debugger_Applet_UpdateShortcuts() is pretty hard-coded for the 5 entries below for now (to update their active state), maybe strcmp the button\n        app->shortcuts_freeze = 0;\n        static const t_debugger_shortcut shortcuts_def[] =\n        {\n            { \"Cont\", \"C\", },\n            { \"Step\", \"STEPINTO\" },\n            { \"Step Over\", \"S\" },\n            { \"Step Out\",  \"SO\" },\n            { \"Stack\", \"STACK\" },\n            //{ \"Breakpoints\", \"B L\" },\n            //{ \"Regs\", \"REGS\" },\n        };\n        int button_w = 0;\n        for (int i = 0; i < countof(shortcuts_def); i++)\n        {\n            const t_debugger_shortcut* sh_def = &shortcuts_def[i];\n            button_w = MAX(button_w, Font_TextWidth(app->font_id, sh_def->name));\n        }\n        button_w += 8;\n\n        if (setup)\n        {\n            assert(app->shortcuts.empty());\n        }\n        DrawCursor dc(app->frame_shortcuts.pos, app->font_id);\n        for (int i = 0; i < countof(shortcuts_def); i++)\n        {\n            const t_debugger_shortcut* sh_def = &shortcuts_def[i];\n\n            t_debugger_shortcut sh;\n            sh.name = sh_def->name;\n            sh.command = sh_def->command;\n\n            //t_frame frame(dc.pos, v2i(Font_TextLength(F_LARGE, sh.name) + 3, Font_Height(F_LARGE) + 3));\n            t_frame frame(dc.pos, v2i(button_w, app->font_height + 10));\n            if (setup)\n            {\n                sh.button = widget_button_add(app->box, &frame, 1, Debugger_ShortcutButton_Callback, app->font_id, (const char *)sh.name, (void*)i);\n                app->shortcuts.push_back(sh);\n            }\n            else\n            {\n                app->shortcuts[i].button->frame = frame;\n            }\n            dc.pos.x += frame.size.x + 2;\n        }\n    }\n    frame.pos.y += app->frame_shortcuts.size.y;\n\n    // Setup CPU state frame\n    app->frame_cpustate.pos.x   = frame.pos.x;\n    app->frame_cpustate.pos.y   = frame.pos.y;\n    app->frame_cpustate.size.x  = frame.size.x;\n    app->frame_cpustate.size.y  = DEBUGGER_APP_CPUSTATE_LINES * app->font_height;\n    frame.pos.y += app->frame_cpustate.size.y;\n\n    // Add input box\n    frame.size.x = app->box->frame.size.x - 16; // Leave room for resize grip\n    frame.size.y = app->font_height + 8;\n    frame.pos.x = 4;\n    frame.pos.y = app->box->frame.size.y - frame.size.y - 2;\n    if (setup)\n    {\n        app->input_box = widget_inputbox_add(app->box, &frame, 56, app->font_id, Debugger_InputBoxCallback);\n        widget_inputbox_set_flags(app->input_box, WIDGET_INPUTBOX_FLAGS_COMPLETION, TRUE);\n        widget_inputbox_set_callback_completion(app->input_box, Debugger_CompletionCallback);\n        widget_inputbox_set_flags(app->input_box, WIDGET_INPUTBOX_FLAGS_HISTORY, TRUE);\n        widget_inputbox_set_callback_history(app->input_box, Debugger_History_Callback);\n    }\n    else\n    {\n        app->input_box->frame = frame;\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_Disassemble_Format(char *dst, u16 addr, bool cursor)\n//-----------------------------------------------------------------------------\n// Disassemble one instruction at given address and produce a formatted\n// string with address, opcode and instruction description.\n// Return instruction length.\n//-----------------------------------------------------------------------------\nint         Debugger_Disassemble_Format(char *dst, u16 addr, bool cursor)\n{\n    char  instr[256];\n    const int len = Z80_Disassemble(instr, addr, true, true, true);\n    if (dst != NULL)\n    {\n        char instr_opcodes[128];\n        for (int i = 0; i < len; i++)\n            sprintf(instr_opcodes + (i*3), \"%02X \", RdZ80_NoHook ((addr + i) & 0xFFFF));\n        sprintf(dst, \"%04X: %-12s%c%s\", addr, instr_opcodes, cursor ? '>' : ' ', instr);\n    }\n\n    return (len);\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_GetZ80SummaryLines(const char ***lines_out, bool simpl)\n// Return array of string pointer containing a Z80 summary\n//-----------------------------------------------------------------------------\n// Note: output array contains reference to static buffers.\n// Be sure to make a copy if you want to reuse later.\n//-----------------------------------------------------------------------------\nstatic int  Debugger_GetZ80SummaryLines(char *** const lines_out, bool simple)\n{\n    static char     line1[256];\n    static char     line2[256];\n    static char     line3[256];\n    static char *   lines[4] = { line1, line2, line3, NULL };\n    char            flags[9];\n    Z80 *           cpu = &sms.R;\n\n    // Compute flags string\n    int i;\n    for (i = 0; i < 8; i++)\n        flags[i] = (cpu->AF.B.l & (1 << (7 - i))) ? \"SZyHxPNC\"[i] : '.';\n    flags[i] = EOSTR;\n\n    *lines_out = &lines[0];\n\n    if (simple)\n    {\n        // Line 1\n        sprintf(line1, \"AF:%04X  BC:%04X  DE:%04X  HL:%04X  IX:%04X  IY:%04X\",\n            cpu->AF.W, cpu->BC.W, cpu->DE.W, cpu->HL.W, cpu->IX.W, cpu->IY.W);\n\n        // Line 2\n        sprintf(line2, \"PC:%04X  SP:%04X  Flags:[%s]  R:%02X  %s%s\",\n            cpu->PC.W, cpu->SP.W, flags, (cpu->R & 0x7F) | (cpu->R7),\n            (cpu->IFF & IFF_1) ? \"EI\" : \"DI\", (cpu->IFF & IFF_HALT) ? \" HALT\" : \"\");\n\n        return (2);\n    }\n    else\n    {\n        // Line 1\n        sprintf(line1, \"AF:%04X  BC:%04X  DE:%04X  HL:%04X  IX:%04X  IY:%04X\",\n            cpu->AF.W, cpu->BC.W, cpu->DE.W, cpu->HL.W, cpu->IX.W, cpu->IY.W);\n\n        // Line 2\n        sprintf(line2, \"AF'%04X  BC'%04X  DE'%04X  HL'%04X\",\n            cpu->AF1.W, cpu->BC1.W, cpu->DE1.W, cpu->HL1.W);\n\n        // Line 3\n        sprintf(line3, \"PC:%04X  SP:%04X  Flags:[%s]  R:%02X  %s%s\",\n            cpu->PC.W, cpu->SP.W, flags, (cpu->R & 0x7F) | (cpu->R7),\n            (cpu->IFF & IFF_1) ? \"EI\" : \"DI\", (cpu->IFF & IFF_HALT) ? \" HALT\" : \"\");\n\n        return (3);\n    }\n}\n\n// Redraw disassembly and CPU state\nvoid    Debugger_Applet_RedrawState()\n{\n    t_debugger_app* app = &DebuggerApp;\n\n    // Mouse wheel scroll disassembly\n    if (!(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)))\n        if (g_machine_flags & MACHINE_POWER_ON)\n            Debugger.trackback_scroll_offset = 0;\n    if (gui_box_has_focus(app->box))\n    {\n        if (gui.mouse.wheel_rel)\n        {\n            const int wheel_speed = (g_keyboard_modifiers & ALLEGRO_KEYMOD_CTRL) ? 5 : 1;\n            Debugger.trackback_scroll_offset += gui.mouse.wheel_rel * wheel_speed;\n        }\n    }\n\n    // Redraw Disassembly\n    if ((g_machine_flags & MACHINE_POWER_ON) && (g_driver->cpu == CPU_Z80))\n    {\n        t_frame frame = app->frame_disassembly;\n\n        u16     pc;\n        int     skip_labels = 0;    // Number of labels to skip on first instruction to be aligned properly\n        int     trackback_lines_base = (app->disassembly_lines / 3) + 1;\n        trackback_lines_base = MIN(trackback_lines_base, 16); // Max 10 because of buffer below\n        //  1 -> 1\n        //  5 -> 2\n        //  9 -> 3, etc.\n        // 13 -> 4\n        // Max = 10 ?\n\n        // Clear disassembly buffer\n        al_set_target_bitmap(app->box_gfx);\n        al_draw_filled_rectangle(frame.pos.x, frame.pos.y, frame.pos.x+frame.size.x+1, frame.pos.y+frame.size.y+1, COLOR_SKIN_WINDOW_BACKGROUND);\n\n        // Figure out where to start disassembly\n        // This is tricky code due to the trackback feature.\n        // Successive PC are logged by the debugging CPU emulator and it helps with the trackback.\n        pc = sms.R.PC.W;\n\n        // Scroll\n        int trackback_lines = trackback_lines_base + Debugger.trackback_scroll_offset;\n\n        if (trackback_lines < 0)\n        {\n            // Forward\n            while (trackback_lines < 0)\n            {\n                int inst_len = Z80_Disassemble(NULL, (u16)pc, false, false, false);\n                if ((int)pc + inst_len <= 0xffff)\n                    pc += inst_len;\n                trackback_lines++;\n            }\n        }\n\n        if (trackback_lines > 0)\n        {\n            while (trackback_lines > 0)\n            {\n                int pc_trackback = pc;\n                for (int b = 1; b < 7; b++)     // ~Maximum 7 bytes per op\n                {\n                    int inst_start = (int)pc - b;\n                    if (inst_start < 0)\n                        break;\n\n                    int inst_len = Debugger.pc_exec_points[inst_start];\n                    if (inst_len == 0)\n                        continue;\n\n                    // lazily convert 0xff stored by CPU convert to opcode len\n                    // zero out following bytes of the same instruction, so that in case of instructions sharing byte, the last executed one will override.\n                    if (inst_len == 0xff)\n                    {\n                        inst_len = Z80_Disassemble(NULL, (u16)(inst_start), false, false, false);\n                        Debugger.pc_exec_points[inst_start] = inst_len;\n                        for (int z = 1; z < inst_len; z++)\n                            Debugger.pc_exec_points[inst_start + z] = 0;\n                    }\n\n                    if (inst_start + inst_len == pc)\n                    {\n                        pc_trackback = inst_start;\n                        trackback_lines--;\n\n                        // account for labels showing in disassembler\n                        if (g_config.debugger_disassembly_display_labels)\n                            if (Debugger.symbols_cpu_space[pc_trackback])\n                                trackback_lines -= list_size(Debugger.symbols_cpu_space[pc_trackback]);\n                    }\n                    break;\n                }\n\n                if (pc == pc_trackback)\n                {\n                    // clamp user scroll offset\n                    if (Debugger.trackback_scroll_offset != 0)\n                        Debugger.trackback_scroll_offset -= trackback_lines;\n                        //MIN(Debugger.trackback_scroll_offset, trackback_lines - (trackback_lines_base + Debugger.trackback_scroll_offset));\n                    break;\n                }\n                pc = pc_trackback;\n            }\n            if (trackback_lines < 0)\n                skip_labels = -trackback_lines;\n        }\n\n        // label_a:\n        //  XOR\n        //  LD\n        //  LD\n        //  LDIR\n        // label_b:\n        //  JP\n        // label_c:\n        // label_d:\n        //  LD\n        //  DEC\n        //  JR NZ\n\n        // Disassemble instructions starting at 'PC'\n        for (int i = 0; i < app->disassembly_lines; i++)\n        {\n            char buf[256];\n            const ALLEGRO_COLOR text_color = (pc == sms.R.PC.W) ? COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT : COLOR_SKIN_WINDOW_TEXT;\n            int opcode_size;\n\n            if (g_config.debugger_disassembly_display_labels)\n            {\n                bool pc_in_bios;\n                const int pc_rom_addr = Debugger_ReverseMapFindRomAddress(pc, &pc_in_bios);\n\n                // Display symbols/labels\n                if (Debugger.symbols_cpu_space[pc] != NULL)\n                {\n                    for (const t_list* symbols = Debugger.symbols_cpu_space[pc]; symbols != NULL; symbols = symbols->next)\n                    {\n                        const t_debugger_symbol* symbol = (t_debugger_symbol*)symbols->elem;\n                        if (skip_labels > 0)\n                        {\n                            skip_labels--;\n                            continue;\n                        }\n\n                        if (pc_rom_addr != -1 && symbol->rom_addr != -1 && symbol->rom_addr != pc_rom_addr)\n                            continue;\n\n                        sprintf(buf, \"%s:\", symbol->name);\n                        Font_Print(app->font_id, buf, frame.pos.x, frame.pos.y + (i * (app->font_height+1)), COLOR_SKIN_WINDOW_TEXT);\n                        i++;\n                        if (i >= app->disassembly_lines)\n                            break;\n                    }\n                    if (i >= app->disassembly_lines)\n                        break;\n                }\n            }\n\n            //// The trick here is to re-add all disassembled instruction into the PC log queue\n            //Debugger_Z80_PC_Log_Queue_Add(pc);\n\n            // Disassemble\n            //if (g_config.debugger_disassembly_display_labels && Debugger.symbols_count != 0)\n            buf[0] = ' ';\n            opcode_size = Debugger_Disassemble_Format(buf + 1, pc, pc == sms.R.PC.W);\n\n            // Breakpoints\n            {\n                bool on_breakpoint = false;\n                for (t_list* breakpoints = Debugger.breakpoints_cpu_space[pc]; breakpoints != NULL; breakpoints = breakpoints->next)\n                {\n                    t_debugger_breakpoint *breakpoint = (t_debugger_breakpoint *)breakpoints->elem;\n                    if (breakpoint->location == BREAKPOINT_LOCATION_ROM)    // FIXME: Support the '!' indicator for ROM breakpoints\n                        continue;\n                    if (breakpoint->type == BREAKPOINT_TYPE_BREAK)\n                        on_breakpoint = true;\n                }\n                if (on_breakpoint)\n                {\n                    buf[0] = '!';\n                }\n            }\n\n            Font_Print(app->font_id, buf, frame.pos.x, frame.pos.y + (i * (app->font_height+1)), text_color);\n\n            pc += opcode_size;\n        }\n    }\n\n    // Redraw CPU State\n    if (g_driver->cpu == CPU_Z80)\n    {\n        // Clear CPU state buffer\n        t_frame frame = app->frame_cpustate;\n        al_set_target_bitmap(app->box_gfx);\n        al_draw_filled_rectangle(frame.pos.x, frame.pos.y, frame.pos.x + frame.size.x+1, frame.pos.y + frame.size.y+1, COLOR_SKIN_WINDOW_BACKGROUND);\n        int y = frame.pos.y;\n\n        // Print Z80 summary lines\n        char ** lines;\n        const int lines_count = Debugger_GetZ80SummaryLines(&lines, TRUE);\n        assert(lines_count >= DEBUGGER_APP_CPUSTATE_LINES); // Display first 2 lines\n        Font_Print(app->font_id, lines[0], frame.pos.x, y, COLOR_SKIN_WINDOW_TEXT);\n        y += app->font_height;\n        Font_Print(app->font_id, lines[1], frame.pos.x, y, COLOR_SKIN_WINDOW_TEXT);\n\n        // Print Z80 running state with nifty ASCII rotating animation\n        if (!(g_machine_flags & (MACHINE_PAUSED | MACHINE_DEBUGGING)))\n        {\n            const char *label = \"OFF\";\n            if (g_machine_flags & MACHINE_POWER_ON)\n            {\n                static int running_counter = 0;\n                switch (running_counter >> 1)\n                {\n                    case 0: label = \"RUNNING |\";  break;\n                    case 1: label = \"RUNNING /\";  break;\n                    case 2: label = \"RUNNING -\";  break;\n                    case 3: label = \"RUNNING \\\\\"; break;\n                }\n                running_counter = (running_counter + 1) % 8;\n            }\n            const int w = Font_TextWidth(app->font_id, lines[1]) + Font_TextWidth(app->font_id, \"  \");\n            Font_Print(app->font_id, label, frame.pos.x + w, y, COLOR_SKIN_WINDOW_TEXT);\n        }\n\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_Help(const char *cmd)\n//-----------------------------------------------------------------------------\n// Print help for debugger or for a given command.\n//-----------------------------------------------------------------------------\nstatic void     Debugger_Help(const char *cmd)\n{\n    if (cmd == NULL)\n    {\n        // Generic help\n        Debugger_Printf(\"Debugger Help:\\n\");\n        Debugger_Printf(\"-- Flow:\\n\");\n        Debugger_Printf(\" <Enter>                : Step into\"                  \"\\n\");\n        Debugger_Printf(\" S                      : Step over\"                  \"\\n\");\n        Debugger_Printf(\" SO                     : Step out (up to next RET)\"   \"\\n\");\n        Debugger_Printf(\" C [addr]               : Continue (up to <addr>)\"    \"\\n\");\n        Debugger_Printf(\" J addr                 : Jump to <addr>\"             \"\\n\");\n        Debugger_Printf(\"-- Breakpoints:\\n\");\n        Debugger_Printf(\" B [access] [bus] addr  : Add breakpoint\"             \"\\n\");\n        Debugger_Printf(\" W [access] [bus] addr  : Add watchpoint\"             \"\\n\");\n        //Debugger_Printf(\" B                      : Detailed breakpoint help\"   \"\\n\");\n        //Debugger_Printf(\" B LIST                 : List breakpoints\"          \"\\n\");\n        //Debugger_Printf(\" B REMOVE n             : Remove breakpoint\"         \"\\n\");\n        //Debugger_Printf(\" B ENABLE/DISABLE n     : Enable/disable breakpoint\" \"\\n\");\n        //Debugger_Printf(\" B CLEAR                : Clear breakpoints\"         \"\\n\");\n        Debugger_Printf(\"-- Inspect/Modify:\\n\");\n        Debugger_Printf(\" R                      : Dump Z80 registers\"         \"\\n\");\n        Debugger_Printf(\" P expr                 : Print evaluated expression\" \"\\n\");\n        Debugger_Printf(\" M [addr] [cnt]         : Memory dump at <addr>\"      \"\\n\");\n        Debugger_Printf(\" D [addr] [cnt]         : Disassembly at <addr>\"      \"\\n\");\n        Debugger_Printf(\" STACK [cnt]            : Stack dump\"                 \"\\n\");\n        Debugger_Printf(\" TRACE [cnt|clear|regs] : Trace past execution\"       \"\\n\");\n        Debugger_Printf(\" RMAP addr              : Reverse map Z80 address\"    \"\\n\");\n        Debugger_Printf(\" VARS [name|@addr]      : Display variables\"          \"\\n\");\n        Debugger_Printf(\" SYM [name|@addr]       : Find symbols\"               \"\\n\");\n        Debugger_Printf(\" SET register=value     : Set Z80 register\"           \"\\n\");\n        Debugger_Printf(\" CLOCK [RESET]          : Display Z80 cycle counter\"  \"\\n\");\n        Debugger_Printf(\"-- Miscellaneous:\\n\");\n        Debugger_Printf(\" MEMEDIT [lines] [cols] : Spawn memory editor\"        \"\\n\");\n        Debugger_Printf(\" HISTORY [word]         : Print/search history\"       \"\\n\");\n        Debugger_Printf(\" H,? [command]          : Help\"                       \"\\n\");\n        Debugger_Printf(\"Use H for detailed help on individual command.\"       \"\\n\");\n    }\n    else\n    {\n        // Search for specific command\n        t_debugger_command_info *command_info = &DebuggerCommandInfos[0];\n        while (command_info->command_long != NULL)\n        {\n            if ((command_info->command_short && !stricmp(cmd, command_info->command_short)) || (command_info->command_long && !stricmp(cmd, command_info->command_long)))\n            {\n                Debugger_Printf(\"%s\\n\", command_info->description);\n                return;\n            }\n            command_info++;\n        }\n        Debugger_Printf(\"Unknown command \\\"%s\\\" !\\n\", cmd);\n    }\n}\n\nvoid        Debugger_InputParseCommand_BreakWatch(char *line, int type)\n{\n    char    arg[256];\n\n    int                 access = 0;\n    int                 location = -1;\n    t_debugger_value    address_start;\n    t_debugger_value    address_end;\n    int                 data_compare_length = 0;\n    u8                  data_compare_bytes[DEBUGGER_DATA_COMPARE_LENGTH_MAX] = { 0 };\n    char *              desc = NULL;\n\n    if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n    {\n        if (type == BREAKPOINT_TYPE_BREAK)\n            Debugger_Help(\"B\");\n        else if (type == BREAKPOINT_TYPE_WATCH)\n            Debugger_Help(\"W\");\n        return;\n    }\n\n    // B NOPNOP -> B x =0,0 \"(NOP NOP)\"\n    // FIXME-WIP: Of course, a generic macro system would be welcome as well.\n    if (!stricmp(arg, \"nopnop\"))\n    {\n        static char break_nopnop_string[] = \"x =0,0 \\\"(NOP NOP)\\\"\";\n        line = break_nopnop_string;\n        parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE);\n    }\n\n    // B LIST\n    if (!stricmp(arg, \"l\") || !stricmp(arg, \"list\"))\n    {\n        Debugger_BreakPoints_List();\n        return;\n    }\n\n    // B CLEAR\n    if (!stricmp(arg, \"clear\"))\n    {\n        if (parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            if (!stricmp(arg, \"disabled\"))\n            {\n                Debugger_BreakPoints_Clear(TRUE);\n                return;\n            }\n            Debugger_Printf(\"Syntax error!\\n\");\n            Debugger_Printf(\"Type HELP B for usage instruction.\\n\");\n            return;\n        }\n        Debugger_BreakPoints_Clear(FALSE);\n        return;\n    }\n\n    // B ENABLE\n    if (!stricmp(arg, \"enable\"))\n    {\n        if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            Debugger_Printf(\"Missing parameter!\\n\");\n        }\n        else\n        {\n            if (!stricmp(arg, \"ALL\"))\n            {\n                for (t_list* breakpoints = Debugger.breakpoints; breakpoints != NULL; breakpoints = breakpoints->next)\n                {\n                    t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n                    Debugger_BreakPoint_Enable(breakpoint);\n                }\n                Debugger_Printf(\"Enabled all breakpoints/watchpoints.\\n\");\n            }\n            else\n            {\n                int id = atoi(arg);\n                t_debugger_breakpoint* breakpoint = Debugger_BreakPoints_SearchById(id);\n                if (breakpoint)\n                {\n                    char buf[256];\n                    if (breakpoint->enabled)\n                    {\n                        Debugger_Printf(\"%s [%d] already enabled.\\n\", Debugger_BreakPoint_GetTypeName(breakpoint), id);\n                    }\n                    else\n                    {\n                        Debugger_BreakPoint_Enable(breakpoint);\n                        Debugger_Printf(\"%s [%d] enabled.\\n\", Debugger_BreakPoint_GetTypeName(breakpoint), id);\n                    }\n                    Debugger_BreakPoint_GetSummaryLine(breakpoint, buf);\n                    Debugger_Printf(\" %s\\n\", buf);\n                }\n                else\n                {\n                    Debugger_Printf(\"Breakpoint [%s] not found!\\n\", arg);\n                }\n            }\n        }\n        return;\n    }\n\n    // B DISABLE\n    if (!stricmp(arg, \"disable\"))\n    {\n        if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            Debugger_Printf(\"Missing parameter!\\n\");\n        }\n        else\n        {\n            if (!stricmp(arg, \"ALL\"))\n            {\n                for (t_list* breakpoints = Debugger.breakpoints; breakpoints != NULL; breakpoints = breakpoints->next)\n                {\n                    t_debugger_breakpoint* breakpoint = (t_debugger_breakpoint*)breakpoints->elem;\n                    Debugger_BreakPoint_Disable(breakpoint);\n                }\n                Debugger_Printf(\"Disabled all breakpoints/watchpoints.\\n\");\n            }\n            else\n            {\n                int id = atoi(arg); // FIXME: no error check\n                t_debugger_breakpoint* breakpoint = Debugger_BreakPoints_SearchById(id);\n                if (breakpoint)\n                {\n                    char buf[256];\n                    if (!breakpoint->enabled)\n                    {\n                        Debugger_Printf(\"%s [%d] already disabled.\\n\", Debugger_BreakPoint_GetTypeName(breakpoint), id);\n                    }\n                    else\n                    {\n                        Debugger_BreakPoint_Disable(breakpoint);\n                        Debugger_Printf(\"%s [%d] disabled.\\n\", Debugger_BreakPoint_GetTypeName(breakpoint), id);\n                    }\n                    Debugger_BreakPoint_GetSummaryLine(breakpoint, buf);\n                    Debugger_Printf(\" %s\\n\", buf);\n                }\n                else\n                {\n                    Debugger_Printf(\"Breakpoint [%s] not found!\\n\", arg);\n                }\n            }\n        }\n        return;\n    }\n\n    // B REMOVE\n    if (!stricmp(arg, \"remove\"))\n    {\n        if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            Debugger_Printf(\"Missing parameter!\\n\");\n        }\n        else\n        {\n            int id = atoi(arg); // FIXME: no error check\n            t_debugger_breakpoint *breakpoint = Debugger_BreakPoints_SearchById(id);\n            if (breakpoint)\n            {\n                Debugger_Printf(\"%s [%d] removed.\\n\", Debugger_BreakPoint_GetTypeName(breakpoint), id);\n                Debugger_BreakPoint_Remove(breakpoint);\n            }\n            else\n            {\n                Debugger_Printf(\"Breakpoint [%s] not found!\\n\", arg);\n            }\n        }\n        return;\n    }\n\n    // If no known argument, revert to adding breakpoint\n\n    // Parse Access\n    {\n        char *p = arg;\n        char  c;\n        while ((c = *p++) != EOSTR)\n        {\n            if (c == 'r' || c == 'R')\n                access |= BREAKPOINT_ACCESS_R;\n            else if (c == 'w' || c == 'W')\n                access |= BREAKPOINT_ACCESS_W;\n            else if (c == 'x' || c == 'X')\n                access |= BREAKPOINT_ACCESS_X;\n            else if (c == 'e' || c == 'E')\n                access |= BREAKPOINT_ACCESS_E;\n            else\n            {\n                access = 0;\n                break;\n            }\n        }\n        if (type == BREAKPOINT_TYPE_WATCH && (access & BREAKPOINT_ACCESS_X)) // Watch\n        {\n            Debugger_Printf(\"Cannot watch execution. Use breakpoints.\\n\");\n            return;\n        }\n    }\n    if (access != 0)\n    {\n        // Get next argument\n        if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            Debugger_Printf(\"Missing parameter!\\n\");\n            Debugger_Printf(\"Type HELP B/W for usage instruction.\\n\");\n            return;\n        }\n    }\n\n    // Parse Bus\n    if (!stricmp(arg, \"CPU\"))\n        location = BREAKPOINT_LOCATION_CPU;\n    else if (!stricmp(arg, \"ROM\"))\n        location = BREAKPOINT_LOCATION_ROM;\n    else if (!stricmp(arg, \"IO\"))\n        location = BREAKPOINT_LOCATION_IO;\n    else if (!stricmp(arg, \"VRAM\"))\n        location = BREAKPOINT_LOCATION_VRAM;\n    else if (!stricmp(arg, \"PAL\") || !stricmp(arg, \"PRAM\"))\n        location = BREAKPOINT_LOCATION_PRAM;\n    else if (!stricmp(arg, \"LINE\"))\n        location = BREAKPOINT_LOCATION_LINE;\n    if (location == -1)\n    {\n        // Default\n        location = BREAKPOINT_LOCATION_CPU;\n    }\n    else\n    {\n        // Get next argument\n        if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            Debugger_Printf(\"Syntax error!\\n\");\n            Debugger_Printf(\"Type HELP B/W for usage instruction.\\n\");\n            return;\n        }\n    }\n\n    // Now that we know the bus, check access validity\n    if (access == 0)\n    {\n        // Default\n        access = DebuggerBusInfos[location].access;\n        if (type == BREAKPOINT_TYPE_WATCH) // Watch, automatically remove X\n            access &= ~BREAKPOINT_ACCESS_X;\n    }\n    else\n    {\n        // Check user-given access rights\n        int access_unpermitted = access & ~DebuggerBusInfos[location].access;\n        if (access_unpermitted != 0)\n        {\n            char buf[5];\n            Debugger_GetAccessString(access_unpermitted, buf);\n            Debugger_Printf(\"Access %s not permitted on this bus.\\n\", buf);\n            return;\n        }\n    }\n\n    // Parse Adress(es)\n    if (strcmp(arg, \"..\") == 0 || arg[0] == '=')\n    {\n        // If given address is '..' or no address but provided a data comparer,\n        // use the bus full range.\n        t_debugger_bus_info *bus_info = &DebuggerBusInfos[location];\n        Debugger_Value_SetDirect(&address_start, (u32)bus_info->addr_min, 16);\n        Debugger_Value_SetDirect(&address_end,   (u32)bus_info->addr_max, 16);\n    }\n    else\n    {\n        t_debugger_bus_info *bus_info = &DebuggerBusInfos[location];\n\n        // Clear out\n        Debugger_Value_SetDirect(&address_start, (u32)-1, 16);\n        Debugger_Value_SetDirect(&address_end,   (u32)-1, 16);\n\n        // Parse different kind of ranges (A, A.., A..B, ..B)\n        char* p = arg;\n        if (Debugger_Eval_ParseExpression(&p, &address_start) > 0)\n        {\n            // Default is no range, so end==start\n            address_start.data = address_start.data;\n            address_end = address_start;\n        }\n        if (strncmp(p, \"..\", 2) == 0)\n        {\n            // Skip range points\n            while (*p == '.')\n                p++;\n\n            // Get second part of the range\n            if (address_start.data == (u32)-1)\n                address_start.data = bus_info->addr_min;\n            if (Debugger_Eval_ParseExpression(&p, &address_end) > 0)\n                address_end.data = address_end.data;\n            else\n                address_end.data = bus_info->addr_max;\n        }\n\n        if (p[0] != '\\0')\n        {\n            Debugger_Printf(\"Syntax error!\\n\");\n            Debugger_Printf(\"Type HELP B for usage instruction.\\n\");\n            return;\n        }\n\n        if (address_start.data == (u32)-1 || address_end.data == (u32)-1)\n        {\n            Debugger_Printf(\"Syntax error!\\n\");\n            Debugger_Printf(\"Type HELP B for usage instruction.\\n\");\n            return;\n        }\n\n        // Check out address range\n        if (address_end.data < address_start.data)\n        {\n            Debugger_Printf(\"Second address in range must be higher.\\n\");\n            return;\n        }\n        if (address_start.data < (u32)bus_info->addr_min || address_start.data > (u32)bus_info->addr_max)\n        {\n            if (bus_info->location == BREAKPOINT_LOCATION_LINE)\n            {\n                Debugger_Printf(\"Address %X is out of %s range (%d..%d).\\n\",\n                    address_start.data,\n                    bus_info->name, bus_info->addr_min, bus_info->addr_max);\n            }\n            else\n            {\n                Debugger_Printf(\"Address %X is out of %s range (%0*X..%0*X).\\n\",\n                    address_start.data,\n                    bus_info->name, bus_info->bus_addr_size * 2, bus_info->addr_min, bus_info->bus_addr_size * 2, bus_info->addr_max);\n            }\n            return;\n        }\n        if (address_end.data < (u32)bus_info->addr_min || address_end.data > (u32)bus_info->addr_max)\n        {\n            if (bus_info->location == BREAKPOINT_LOCATION_LINE)\n            {\n                Debugger_Printf(\"Address %X is out of %s range (%d..%d).\\n\",\n                    address_end.data,\n                    bus_info->name, bus_info->addr_min, bus_info->addr_max);\n            }\n            else\n            {\n                Debugger_Printf(\"Address %X is out of %s range (%0*X..%0*X).\\n\",\n                    address_end.data,\n                    bus_info->name, bus_info->bus_addr_size * 2, bus_info->addr_min, bus_info->bus_addr_size * 2, bus_info->addr_max);\n            }\n            return;\n        }\n\n        // Get next argument\n        if (line[0] == '=')\n            parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE);\n    }\n\n    // Parse Data Comparer\n    if (arg[0] == '=')\n    {\n        char *p;\n        char value_buf[128];\n        const int data_compare_length_max = DebuggerBusInfos[location].data_compare_length_max;\n\n        //parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE);\n        //assert(arg[0] == '=');\n        p = arg + 1;\n\n        while (parse_getword(value_buf, sizeof(value_buf), &p, \",\", 0, PARSE_FLAGS_NONE))\n        {\n            t_debugger_value value;\n            if (data_compare_length >= data_compare_length_max)\n            {\n                if (data_compare_length_max == 0)\n                    Debugger_Printf(\"Error: data comparing on this bus is not allowed!\\n\");\n                else\n                    Debugger_Printf(\"Error: data comparing on this bus is limited to %d bytes!\\n\", data_compare_length_max);\n                return;\n            }\n            if ((access & BREAKPOINT_ACCESS_W) && (data_compare_length >= 1))\n            {\n                Debugger_Printf(\"Error: data comparing for write accesses is limited to 1 byte! Only read/execute accesses can uses more.\\n\");\n                return;\n            }\n            if (!Debugger_Eval_ParseConstant(value_buf, &value))\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                return;\n            }\n            if (value.data & ~0xFF)\n            {\n                Debugger_Printf(\"Error: comparing values must be given in bytes.\\n\\\"%s\\\" doesn't fit in byte.\\n\",\n                    value_buf);\n                return;\n            }\n            data_compare_bytes[data_compare_length++] = value.data;\n        }\n\n        //sscanf(p, \"%02X\",\n\n    }\n\n    // Parse or create description\n    {\n        assert(desc == NULL);\n        StrTrim(line);\n        if (line[0] != '\\0')\n        {\n            if (line[0] == '\\\"')\n            {\n                char *desc_end;\n                line++;\n                desc_end = strchr(line, '\\\"');\n                if (desc_end != NULL)\n                    *desc_end = '\\0';\n                desc = line;\n            }\n            else\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                Debugger_Printf(\"Type HELP B for usage instruction.\\n\");\n                return;\n            }\n        }\n        else\n        {\n            // Create automatic description containing symbol\n            if (address_start.source == DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR || address_start.source == DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR\n             || address_end.source == DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR || address_end.source == DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR)\n            {\n                static char buf[512];\n                if (address_start.source == DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR || address_start.source == DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR)\n                    strcpy(buf, ((t_debugger_symbol *)address_start.source_data)->name);\n                else\n                    sprintf(buf, \"%04hX\", address_start.data);\n                if (address_start.data != address_end.data)\n                {\n                    strcat(buf, \"..\");\n                    if (address_end.source == DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR || address_end.source == DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR)\n                        strcat(buf, ((t_debugger_symbol *)address_end.source_data)->name);\n                    else\n                        sprintf(buf+strlen(buf), \"%04hX\", address_end.data);\n                }\n                desc = buf; // Ok since Debugger_BreakPoint_Add() - called below - does a strcpy\n            }\n        }\n    }\n\n    // Add breakpoint\n    {\n        t_debugger_breakpoint *breakpoint;\n        char buf[256];\n\n        breakpoint = Debugger_BreakPoint_Add(type, location, access, address_start.data, address_end.data, -1, desc);\n        if (data_compare_length != 0)\n        {\n            Debugger_BreakPoint_SetDataCompare(breakpoint, data_compare_length, data_compare_bytes);\n        }\n\n        // Verbose\n        Debugger_Printf(\"%s [%d] added.\\n\", Debugger_BreakPoint_GetTypeName(breakpoint), breakpoint->id);\n        Debugger_BreakPoint_GetSummaryLine(breakpoint, buf);\n        Debugger_Printf(\" %s\\n\", buf);\n    }\n}\n\nvoid        Debugger_StepInto()\n{\n    if (g_machine_flags & MACHINE_POWER_ON)\n    {\n        // If machine is in PAUSE state, consider is the same as in DEBUGGING state\n        // (Allows step during pause)\n        if ((g_machine_flags & MACHINE_DEBUGGING) || (g_machine_flags & MACHINE_PAUSED))\n        {\n            // Step into\n            Debugger.stepping = 1;\n            Debugger.stepping_trace_after = sms.R.Trace = 1;\n            Debugger.stepping_out_enable = false;\n            Machine_Debug_Stop();\n        }\n        else\n        {\n            // Activate debugging\n            Debugger.stepping = 0;\n            Debugger.stepping_out_enable = false;\n            Debugger_Printf(\"Breaking at $%04X\\n\", sms.R.PC.W);\n            //Debugger_Applet_RedrawState();\n            Machine_Debug_Start();\n            //Debugger_Hook (&sms.R);\n            sms.R.Trace = 1;\n        }\n    }\n    else\n    {\n        Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n    }\n}\n\nvoid        Debugger_InputParseCommand(char* line)\n{\n    char    cmd[64];\n    char    arg[256];\n\n    // Process command\n    parse_getword(cmd, sizeof(cmd), &line, \" \", 0, PARSE_FLAGS_NONE);\n    StrUpper(cmd);\n\n    // H - HELP\n    if (!strcmp(cmd, \"H\") || !strcmp(cmd, \"?\") || !strcmp(cmd, \"HELP\"))\n    {\n        if (parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n            Debugger_Help(arg);\n        else\n            Debugger_Help(NULL);\n        return;\n    }\n\n    // HI - HISTORY\n    if (!strcmp(cmd, \"HI\") || !strcmp(cmd, \"HISTORY\"))\n    {\n        if (!StrIsNull(line))\n            Debugger_History_List(line);\n        else\n            Debugger_History_List(NULL);\n        return;\n    }\n\n    // B - BREAKPOINT\n    if (!strcmp(cmd, \"B\") || !strcmp(cmd, \"BR\") || !strcmp(cmd, \"BRK\") || !strcmp(cmd, \"BREAK\"))\n    {\n        Debugger_InputParseCommand_BreakWatch(line, BREAKPOINT_TYPE_BREAK);\n        return;\n    }\n    if (!strcmp(cmd, \"W\") || !strcmp(cmd, \"WATCH\"))\n    {\n        Debugger_InputParseCommand_BreakWatch(line, BREAKPOINT_TYPE_WATCH);\n        return;\n    }\n\n    // STEPINTO (undocumented / for shortcuts)\n    if (!strcmp(cmd, \"STEPINTO\"))\n    {\n        Debugger_StepInto();\n        return;\n    }\n\n    // C - CONTINUE\n    if (!strcmp(cmd, \"C\") || !strcmp(cmd, \"CONT\") || !strcmp(cmd, \"CONTINUE\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n            return;\n        }\n\n        if (!(g_machine_flags & MACHINE_DEBUGGING))\n        {\n            // If running, stop and entering into debugging state\n            Machine_Debug_Start();\n        }\n\n        t_debugger_value value;\n        if (Debugger_Eval_ParseExpression(&line, &value) > 0)\n        {\n            // Continue up to...\n            u16 addr = value.data;\n            Debugger_Printf(\"Continuing up to $%04X\\n\", addr);\n            Debugger_SetTrap(addr);\n        }\n        else\n        {\n            // Continue\n            // Disable one-time trap\n            Debugger_SetTrap(-1);\n        }\n\n        // Stop tracing\n        sms.R.Trace = 0;\n        Machine_Debug_Stop();\n\n        // Setup a single stepping so that the CPU emulator won't break\n        // on the same address right now.\n        Debugger.stepping = 1;\n        Debugger.stepping_trace_after = 0;\n\n        return;\n    }\n\n    // SO - STEPOUT\n    if (!strcmp(cmd, \"SO\") || !strcmp(cmd, \"STEPOUT\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n            return;\n        }\n\n        if (!(g_machine_flags & MACHINE_DEBUGGING))\n        {\n            // If running, stop and entering into debugging state\n            Machine_Debug_Start();\n        }\n\n        // Start tracing\n        sms.R.Trace = 1;\n        Debugger.stepping_out_enable = true;\n        Debugger.stepping_out_stack_ref = sms.R.SP.W;\n        Debugger.stepping = 1;  // to avoid breaking again on current RET instruction\n        Debugger.stepping_trace_after = 1;\n        Machine_Debug_Stop();\n        Debugger_SetTrap(-1);\n\n        return;\n    }\n\n    // J - JUMP\n    if (!strcmp(cmd, \"J\") || !strcmp(cmd, \"JP\") || !strcmp(cmd, \"JUMP\"))\n    {\n        t_debugger_value value;\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n            return;\n        }\n        if (!(g_machine_flags & MACHINE_DEBUGGING))\n        {\n            // If running, stop and entering into debugging state\n            Machine_Debug_Start();\n        }\n        if (Debugger_Eval_ParseExpression(&line, &value) > 0)\n        {\n            sms.R.PC.W = value.data;\n            Debugger_Printf(\"Jump to $%04X\\n\", sms.R.PC.W);\n            //Debugger_Applet_RedrawState();\n        }\n        else\n        {\n            Debugger_Printf(\"Missing parameter!\\n\");\n        }\n        return;\n    }\n\n    // S - STEP OVER\n    if (!strcmp(cmd, \"S\") || !strcmp(cmd, \"STEP\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n        }\n        else\n        {\n            // Get address of following instruction\n            // Do not verbose since this is just a step-over\n            u16 addr = sms.R.PC.W + Z80_Disassemble(NULL, sms.R.PC.W, false, false, false);\n            Debugger_SetTrap (addr);\n            sms.R.Trace = 0;\n            Machine_Debug_Stop();\n        }\n        return;\n    }\n\n    // P - PRINT\n    if (!strcmp(cmd, \"P\") || !strcmp(cmd, \"PRINT\"))\n    {\n        t_debugger_value value;\n        StrTrim(line);\n        if (line[0])\n        {\n            char *p = line;\n            while (*p && Debugger_Eval_ParseExpression(&p, &value) > 0)\n            {\n                const s32 data = value.data;\n                const int data_size_bytes = Clamp<int>(value.data_size/8, 2, 4); //data & 0xFFFF0000) ? ((data & 0xFF000000) ? 4 : 3) : (2);\n\n                // Write binary buffer\n                char binary_s[32+4+1];\n                StrWriteBitfield(data, data_size_bytes*8, binary_s);\n\n                // Write ascii buffer\n                char ascii_s[16];\n                if (data_size_bytes == 1)\n                {\n                    if (isprint(data & 0xFF))\n                        sprintf(ascii_s, \"  asc: '%c'\", data & 0xFF);\n                    else\n                        sprintf(ascii_s, \"  asc: N/A \");\n                }\n                else\n                    ascii_s[0] = '\\0';\n                Debugger_Printf(\" $%0*hX  bin: %%%s%s  dec: %d\\n\", data_size_bytes * 2, data, binary_s, ascii_s, data);\n\n                // Skip comma to get to next expression, if any\n                if (*p == ',')\n                    p++;\n            }\n        }\n        else\n        {\n            Debugger_Help(\"P\");\n        }\n        return;\n    }\n\n    // CLOCK\n    if (!strcmp(cmd, \"CLOCK\"))\n    {\n        if (!parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            // Display clock\n            Debugger_Printf(\"Clock: %lld cycles\\n\", Debugger.cycle_counter);\n            return;\n        }\n\n        if (!stricmp(arg, \"r\") || !stricmp(arg, \"reset\"))\n        {\n            // Reset clock\n            Debugger.cycle_counter = 0;\n            Debugger_Printf(\"Clock reset\\n\");\n            Debugger_Printf(\"Clock: %lld cycles\\n\", Debugger.cycle_counter);\n            return;\n        }\n\n        Debugger_Help(\"CLOCK\");\n        return;\n    }\n\n    // SET\n    if (!strcmp(cmd, \"SET\"))\n    {\n        if (!(g_machine_flags & MACHINE_DEBUGGING))\n        {\n            // If running, stop and entering into debugging state\n            Machine_Debug_Start();\n        }\n\n        StrTrim(line);\n        if (line[0])\n        {\n            char *p = line;\n            while (*p)\n            {\n                t_list *vars;\n                t_debugger_value *lvalue;\n\n                // Get variable name to assign too\n                if (!parse_getword(arg, sizeof(arg), &p, \"=\", 0, PARSE_FLAGS_NONE))\n                {\n                    Debugger_Printf(\"Missing parameter!\\n\");\n                    Debugger_Help(\"SET\");\n                    return;\n                }\n\n                // Search variable\n                // (currently only support CPU registers)\n                lvalue = NULL;\n                for (vars = Debugger.variables_cpu_registers; vars != NULL; vars = vars->next)\n                {\n                    t_debugger_value *var = (t_debugger_value *)vars->elem;\n                    if (!stricmp(var->name, arg))\n                    {\n                        if (!(var->flags & DEBUGGER_VALUE_FLAGS_ACCESS_WRITE))\n                        {\n                            Debugger_Printf(\"Variable \\\"%s\\\" is read-only!\\n\", var->name);\n                            lvalue = NULL;\n                        }\n                        else\n                        {\n                            lvalue = var;\n                        }\n                        break;\n                    }\n                }\n                if (lvalue != NULL)\n                {\n                    // Get right value\n                    t_debugger_value rvalue;\n                    if (Debugger_Eval_ParseExpression(&p, &rvalue) > 0)\n                    {\n                        // Assign\n                        if (rvalue.data_size > lvalue->data_size)\n                            if (rvalue.data & ~((1 << lvalue->data_size) - 1))\n                                Debugger_Printf(\"Warning: value truncated from %d to %d bits.\\n\", rvalue.data_size, lvalue->data_size);\n                        Debugger_Value_Write(lvalue, rvalue.data);\n                    }\n                    else\n                    {\n                        // Abort\n                        return;\n                    }\n                }\n                else\n                {\n                    Debugger_Printf(\"Unknown variable: %s\\n\", arg);\n                }\n\n                // Skip comma to get to next expression, if any\n                if (*p == ',')\n                    p++;\n            }\n       }\n        else\n        {\n            Debugger_Help(\"SET\");\n        }\n        return;\n    }\n\n    // R - REGS\n    if (!strcmp(cmd, \"R\") || !strcmp(cmd, \"REGS\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n        }\n        else\n        {\n            char **lines;\n            const int lines_count = Debugger_GetZ80SummaryLines(&lines, FALSE);\n            int i;\n            for (i = 0; i != lines_count; i++)\n                Debugger_Printf(\"%s\\n\", lines[i]);\n        }\n        return;\n    }\n\n    // D - DISASSEMBLE\n    if (!strcmp(cmd, \"D\") || !strcmp(cmd, \"DASM\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n        }\n        else\n        {\n            u16 addr = sms.R.PC.W;\n            int len  = 10;\n            t_debugger_value value;\n            int expr_error;\n            if ((expr_error = Debugger_Eval_ParseExpression(&line, &value)) < 0)\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                return;\n            }\n            if (expr_error > 0)\n            {\n                addr = value.data;\n                parse_skip_spaces(&line);\n                if ((expr_error = Debugger_Eval_ParseExpression(&line, &value)) < 0)\n                {\n                    Debugger_Printf(\"Syntax error!\\n\");\n                    return;\n                }\n                if (expr_error > 0)\n                {\n                    len = value.data;\n                }\n            }\n\n            {\n                int i;\n                for (i = 0; i < len; i++)\n                {\n                    char buf[256];\n                    const int opcode_size = Debugger_Disassemble_Format(buf, addr, addr == sms.R.PC.W);\n\n                    // Display symbols/labels (if any)\n                    const int rom_addr = Debugger_ReverseMapFindRomAddress(addr, NULL);\n                    for (t_list* symbols = Debugger.symbols_cpu_space[addr]; symbols != NULL; symbols = symbols->next)\n                    {\n                        const t_debugger_symbol* symbol = (const t_debugger_symbol*)symbols->elem;\n                        if (rom_addr != -1 && symbol->rom_addr != -1 && symbol->rom_addr != rom_addr)\n                            continue;\n                        Debugger_Printf(\"%s:\\n\", symbol->name);\n                    }\n\n                    // Display instruction\n                    Debugger_Printf(\" %s\\n\", buf);\n\n                    addr += opcode_size;\n                }\n            }\n        }\n        return;\n    }\n\n    // RMAP\n    if (!strcmp(cmd, \"RMAP\"))\n    {\n        StrTrim(line);\n        if (line[0])\n        {\n            if (!(g_machine_flags & MACHINE_POWER_ON))\n            {\n                Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n            }\n            else\n            {\n                t_debugger_value value;\n                char *p = line;\n                while (*p && Debugger_Eval_ParseExpression(&p, &value) > 0)\n                {\n                    const s16 addr = value.data;\n                    Debugger_ReverseMap(addr);\n\n                    // Skip comma to get to next expression, if any\n                    if (*p == ',')\n                        p++;\n                }\n            }\n        }\n        else\n        {\n            Debugger_Help(\"RMAP\");\n        }\n        return;\n    }\n\n    // SYMBOLS - SYMBOLS\n    if (!strcmp(cmd, \"SYM\") || !strcmp(cmd, \"SYMBOL\") || !strcmp(cmd, \"SYMBOLS\"))\n    {\n        StrTrim(line);\n        if (line[0] == '@')\n        {\n            t_debugger_value value;\n            line++;\n            if (Debugger_Eval_ParseExpression(&line, &value) < 0)\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                return;\n            }\n            else\n            {\n                Debugger_Symbols_ListByAddr(value.data);\n            }\n        }\n        else\n        {\n            Debugger_Symbols_ListByName(!StrIsNull(line) ? line : NULL);\n        }\n        return;\n    }\n\n    // VARS\n    if (!strcmp(cmd, \"VAR\") || !strcmp(cmd, \"VARS\"))\n    {\n        StrTrim(line);\n        if (line[0] == '@')\n        {\n            t_debugger_value value;\n            line++;\n            if (Debugger_Eval_ParseExpression(&line, &value) < 0)\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                return;\n            }\n            else\n            {\n                Debugger_Symbols_Vars_ListByAddr(value.data);\n            }\n        }\n        else\n        {\n            Debugger_Symbols_Vars_ListByName(!StrIsNull(line) ? line : NULL);\n        }\n        return;\n    }\n\n    // M - MEMORY DUMP\n    if (!strcmp(cmd, \"M\") || !strcmp(cmd, \"MEM\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n        }\n        else\n        {\n            u16 addr = sms.R.PC.W;\n            int len  = 16*8;\n            t_debugger_value value;\n            if (Debugger_Eval_ParseExpression(&line, &value) > 0)\n            {\n                addr = value.data;\n                parse_skip_spaces(&line);\n                if (Debugger_Eval_ParseExpression(&line, &value) > 0)\n                {\n                    len = value.data;\n                }\n            }\n            while (len > 0)\n            {\n                char buf[256];\n                u8   data[8];\n                char *p;\n                int  line_len = (len >= 8) ? 8 : len;\n                sprintf(buf, \"%04X-%04X | \", addr, (addr + line_len - 1) & 0xFFFF);\n                p = buf + strlen(buf);\n                int i;\n                for (i = 0; i < line_len; i++)\n                {\n                    data[i] = RdZ80_NoHook((addr + i) & 0xFFFF);\n                    sprintf(p, \"%02X \", data[i]);\n                    p += 3;\n                }\n                if (i < 8)\n                {\n                    p += sprintf(p, \"%-*s\", (8 - line_len) * 3, \"\");\n                }\n                sprintf(p, \"| \");\n                p += 2;\n                for (i = 0; i < line_len; i++)\n                    *p++ = (isprint(data[i]) ? data[i] : '.');\n                *p++ = '\\n';\n                *p = EOSTR;\n                Debugger_Printf(\"%s\", buf);\n                addr += 8;\n                len -= line_len;\n            }\n        }\n        return;\n    }\n\n    // ST - STACK DUMP\n    if (!strcmp(cmd, \"ST\") || !strcmp(cmd, \"STACK\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n        }\n        else\n        {\n            u16 addr = sms.R.SP.W;\n            int len  = 8;\n            t_debugger_value value;\n            if (Debugger_Eval_ParseExpression(&line, &value) > 0)\n                len = value.data;\n\n            const t_debugger_symbol* symbol = Debugger_Symbols_GetClosestPreviousByAddr(sms.R.PC.W, 256); // be generous\n            if (symbol != NULL)\n                Debugger_Printf(\" Current PC:     %04X      %s+%X\\n\", sms.R.PC.W, symbol->name, sms.R.PC.W-symbol->cpu_addr);\n            else\n                Debugger_Printf(\" Current PC:     %04X\\n\", sms.R.PC.W);\n            Debugger_Printf(\"------------------------\\n\");\n            Debugger_Printf(\" Stack   8-bit   16-bit\\n\");\n            Debugger_Printf(\"------------------------\\n\");\n            while (len > 0)\n            {\n                const u8 v8 = RdZ80_NoHook(addr & 0xFFFF);\n                const u16 v16 = (RdZ80_NoHook((addr+1) & 0xFFFF) << 8) | v8;\n\n                symbol = Debugger_Symbols_GetClosestPreviousByAddr(v16, 256);\n                if (symbol != NULL)\n                    Debugger_Printf(\" %04X:   %02X      %04X      %s+%X\\n\", addr, v8, v16, symbol->name, v16-symbol->cpu_addr);\n                else\n                    Debugger_Printf(\" %04X:   %02X      %04X\\n\", addr, v8, v16);\n                addr++;\n                len--;\n            }\n        }\n        return;\n    }\n\n    // TR - TRACE\n    if (!strcmp(cmd, \"TR\") || !strcmp(cmd, \"TRACE\"))\n    {\n        if (!(g_machine_flags & MACHINE_POWER_ON))\n        {\n            Debugger_Printf(\"Command unavailable while machine is not running!\\n\");\n        }\n        else\n        {\n            int cnt = MIN(16, Debugger.pc_detail_log_count);\n\n            parse_skip_spaces(&line);\n\n            char* line_start = line;\n            if (parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n            {\n                StrUpper(arg);\n                if (strcmp(arg, \"REGS\") == 0)\n                {\n                    Debugger.pc_detail_log_show_extra_registers = !Debugger.pc_detail_log_show_extra_registers;\n                    if (Debugger.pc_detail_log_show_extra_registers)\n                        Debugger_Printf(\"Trace will show: PC, AF, BC, DE, HL, IX, IY, SP\\n\");\n                    else\n                        Debugger_Printf(\"Trace will show: PC, AF, BC, DE, HL\\n\");\n                    return;\n                }\n                else if (strcmp(arg, \"CLEAR\") == 0)\n                {\n                    Debugger.pc_detail_log_head = 0;\n                    Debugger.pc_detail_log_count = 0;\n                    Debugger.pc_detail_log_data[Debugger.pc_detail_log_data.size()-1].pc = 0xffff;\n                    Debugger_Printf(\"Trace log cleared.\\n\");\n                    return;\n                }\n                else if (strcmp(arg, \"ALL\") == 0)\n                {\n                    cnt = Debugger.pc_detail_log_count;\n                }\n                else\n                {\n                    t_debugger_value value;\n                    line = line_start;\n                    if (Debugger_Eval_ParseExpression(&line, &value) > 0)\n                    {\n                        cnt = value.data;\n                    }\n                    else\n                    {\n                        Debugger_Printf(\"Syntax error!\\n\");\n                        Debugger_Help(\"TRACE\");\n                        return;\n                    }\n                }\n            }\n\n            cnt = MIN(cnt, (int)Debugger.pc_detail_log_count);\n\n            Debugger_Printf(\"Tracing %d instruction%s (of total %d recorded)\\n\", cnt, cnt>1?\"s\":\"\", Debugger.pc_detail_log_count);\n            for (int i = cnt; i > 0; i--)\n            {\n                int n = (Debugger.pc_detail_log_head - i + Debugger.pc_detail_log_data.size()) % Debugger.pc_detail_log_data.size();\n                const t_debugger_exec_log_entry* e = &Debugger.pc_detail_log_data[n];\n\n                char instr[128];\n                if (int len = Z80_Disassemble(instr, e->pc, false, false, true))\n                {\n                    char buf[256];\n\n                    //char instr_opcodes[128];\n                    //for (int i = 0; i < len; i++)\n                    //  sprintf(instr_opcodes + (i*3), \"%02X \", RdZ80_NoHook((e->pc + i) & 0xFFFF));\n                    if (Debugger.pc_detail_log_show_extra_registers)\n                        sprintf(buf, \"%04X: %-18s ; AF:%04X BC:%04X DE:%04X HL:%04X IX:%04X IY:%04X SP:%04X\\n\",\n                            e->pc, instr, e->af, e->bc, e->de, e->hl, e->ix, e->iy, e->sp);\n                    else\n                        sprintf(buf, \"%04X: %-18s ; AF:%04X BC:%04X DE:%04X HL:%04X\\n\",\n                            e->pc, instr, e->af, e->bc, e->de, e->hl);\n\n                    if (cnt > 256)\n                        Debugger_PrintEx(false, true, false, buf);\n                    else\n                        Debugger_PrintEx(true, true, true, buf);\n                }\n            }\n            if (cnt > 256)\n            {\n                char buf[256];\n                strcpy(buf, \"(output in file Debug/debuglog.txt)\");\n                Debugger_PrintEx(true, false, true, buf);\n            }\n        }\n        return;\n    }\n\n    // MEMEDIT - MEMORY EDITOR SPAWN\n    if (!strcmp(cmd, \"MEMEDIT\") || !strcmp(cmd, \"MEMEDITOR\"))\n    {\n        int size_x = -1;\n        int size_y = -1;\n        if (parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            if (sscanf(arg, \"%d\", &size_y) < 1)\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                Debugger_Help(\"MEMEDIT\");\n                return;\n            }\n        }\n        if (parse_getword(arg, sizeof(arg), &line, \" \", 0, PARSE_FLAGS_NONE))\n        {\n            if (sscanf(arg, \"%d\", &size_x) < 1)\n            {\n                Debugger_Printf(\"Syntax error!\\n\");\n                Debugger_Help(\"MEMEDIT\");\n                return;\n            }\n        }\n        if (size_x < 1 && size_x != -1)\n            size_x = -1;\n        if (size_y < 1 && size_y != -1)\n            size_y = -1;\n        MemoryViewer_New(FALSE, size_x, size_y);\n        return;\n    }\n\n    // Unknown command\n    Debugger_Printf(\"Syntax error!\\n\");\n}\n\nvoid        Debugger_ShortcutButton_Callback(t_widget* w)\n{\n    t_debugger_app* app = &DebuggerApp;\n\n    t_debugger_shortcut* sh = &app->shortcuts[(int)(intptr_t)w->user_data];\n\n    char* command = strdup(sh->command);\n    Debugger_InputParseCommand(command);        // non-const input\n    free(command);\n\n    app->shortcuts_freeze = 1;\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_InputBoxCallback(t_widget *w)\n//-----------------------------------------------------------------------------\n// Input box widget callback. Called when the user validate a line with ENTER.\n// Perform command-line processing.\n//-----------------------------------------------------------------------------\nvoid        Debugger_InputBoxCallback(t_widget *w)\n{\n    char    line_buf[512];\n\n    strcpy(line_buf, widget_inputbox_get_value(DebuggerApp.input_box));\n    StrTrim(line_buf);\n\n    // Clear input box\n    widget_inputbox_set_value(DebuggerApp.input_box, \"\");\n\n    // An empty line means step into or activate debugging\n    if (line_buf[0] == EOSTR)\n    {\n        if (g_machine_flags & MACHINE_POWER_ON)\n            Debugger_StepInto();\n        return;\n    }\n\n    // Add input to history\n    //// Note: add after executing command, so that HISTORY doesn't show itself\n    Debugger_History_AddLine(line_buf);\n\n    // Print line to the console, as a user command log\n    // Note: passing address of the color because we need a theme switch to be reflected on this\n    widget_textbox_set_current_color(DebuggerApp.console, &COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT);\n    Debugger_Printf(\"# %s\\n\", line_buf);\n    widget_textbox_set_current_color(DebuggerApp.console, &COLOR_SKIN_WINDOW_TEXT);\n\n    // Parse command\n    Debugger_InputParseCommand(line_buf);\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - Values/Variables\n//-----------------------------------------------------------------------------\n\nvoid     Debugger_Value_SetCpuRegister(t_debugger_value *value, const char *name, void *data, int data_size)\n{\n    value->data         = 0;\n    value->data_size    = data_size;\n    value->flags        = DEBUGGER_VALUE_FLAGS_ACCESS_READ | DEBUGGER_VALUE_FLAGS_ACCESS_WRITE;\n    value->source       = DEBUGGER_VALUE_SOURCE_CPU_REG;\n    value->source_data  = data;\n    value->name         = name;\n    Debugger_Value_Read(value);\n}\n\nvoid     Debugger_Value_SetSymbol(t_debugger_value *value, t_debugger_symbol *symbol, bool rom_addr)\n{\n    value->data         = 0;\n    value->data_size    = 16;\n    value->flags        = DEBUGGER_VALUE_FLAGS_ACCESS_READ;\n    value->source       = rom_addr ? DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR : DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR;\n    value->source_data  = symbol;\n    value->name         = symbol->name;\n    Debugger_Value_Read(value);\n}\n\nvoid    Debugger_Value_Read(t_debugger_value *value)\n{\n    assert(value->flags & DEBUGGER_VALUE_FLAGS_ACCESS_READ);\n    switch (value->source)\n    {\n    case DEBUGGER_VALUE_SOURCE_CPU_REG:\n        {\n            if (value->data_size == 8)\n                value->data = *(u8 *)value->source_data;\n            else if (value->data_size == 16)\n                value->data = *(u16 *)value->source_data;\n            else\n                assert(0);\n        }\n        break;\n    case DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR:\n        {\n            t_debugger_symbol* symbol = (t_debugger_symbol *)value->source_data;\n            value->data = symbol->cpu_addr;\n        }\n        break;\n    case DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR:\n        {\n            t_debugger_symbol* symbol = (t_debugger_symbol *)value->source_data;\n            value->data = symbol->rom_addr;\n            value->data_size = 24;\n        }\n        break;\n    default:\n        assert(0);\n    }\n}\n\nvoid    Debugger_Value_Write(t_debugger_value *value, u32 data)\n{\n    assert(value->flags & DEBUGGER_VALUE_FLAGS_ACCESS_WRITE);\n\n    value->data = data;\n    switch (value->source)\n    {\n    case DEBUGGER_VALUE_SOURCE_CPU_REG:\n        if (value->data_size == 8)\n            *(u8 *)value->source_data = value->data;\n        else if (value->data_size == 16)\n            *(u16 *)value->source_data = value->data;\n        else\n            assert(0);\n        break;\n    default:\n        assert(0);\n    }\n}\n\n//..update below\n\nvoid     Debugger_Value_SetComputed(t_debugger_value *value, u32 data, int data_size)\n{\n    value->data         = data;\n    value->data_size    = data_size;\n    value->flags        = DEBUGGER_VALUE_FLAGS_ACCESS_READ;\n    value->source       = DEBUGGER_VALUE_SOURCE_COMPUTED;\n    value->source_data  = NULL;\n    value->name         = NULL;\n}\n\nvoid     Debugger_Value_SetDirect(t_debugger_value *value, u32 data, int data_size)\n{\n    value->data         = data;\n    value->data_size    = data_size;\n    value->flags        = DEBUGGER_VALUE_FLAGS_ACCESS_READ;\n    value->source       = DEBUGGER_VALUE_SOURCE_DIRECT;\n    value->source_data  = NULL;\n    value->name         = NULL;\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - Expression Evaluator\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Debugger_Eval_GetVariable(int variable_replacement_flags, const char *var, t_debugger_value *result)\n//-----------------------------------------------------------------------------\n// Replace given variable by looking for corresponding CPU register/symbol name.\n// Return TRUE on success and fill result, else return FALSE.\n//-----------------------------------------------------------------------------\n// FIXME:\n// - Should do something better in the future.\n//   Generalized abstraction to access system components?\n//   Anyway - this is quick and dirty but it suffise now.\n//-----------------------------------------------------------------------------\nbool    Debugger_Eval_ParseVariable(int variable_replacement_flags, const char *var, t_debugger_value *result)\n{\n    // CPU registers\n    if (variable_replacement_flags & DEBUGGER_VARIABLE_REPLACEMENT_CPU_REGS)\n    {\n        t_list *vars;\n        for (vars = Debugger.variables_cpu_registers; vars != NULL; vars = vars->next)\n        {\n            t_debugger_value *value = (t_debugger_value *)vars->elem;\n            if (!stricmp(value->name, var))\n            {\n                *result = *value;\n                Debugger_Value_Read(result);\n                return true;\n            }\n        }\n    }\n\n    // Symbols\n    if (variable_replacement_flags & DEBUGGER_VARIABLE_REPLACEMENT_SYMBOLS)\n    {\n        // Go thru all symbols\n        const bool is_rom_addr = (*var == ':');\n        for (t_list *symbols = Debugger.symbols; symbols != NULL; symbols = symbols->next)\n        {\n            t_debugger_symbol *symbol = (t_debugger_symbol *)symbols->elem;\n            if (!stricmp(is_rom_addr ? var+1 : var, symbol->name))\n            {\n                Debugger_Value_SetSymbol(result, symbol, is_rom_addr);\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\nint  Debugger_Eval_ParseIntegerHex(const char* s, const char** out_end)\n{\n    int         result = 0;\n    char        c;\n\n    while ((c = *s) != '\\0')\n    {\n        int digit;\n        if (c >= '0' && c <= '9')\n            digit = c - '0';\n        else if (c >= 'a' && c <= 'f')\n            digit = c + 10 - 'a';\n        else if (c >= 'A' && c <= 'F')\n            digit = c + 10 - 'A';\n        else\n            break;\n        assert(digit >= 0x00 && digit <= 0x0F);\n        result = (result << 4) | digit;\n        s++;\n    }\n    if (out_end)\n        *out_end = s;\n    return (result);\n}\n\nstatic int  Debugger_Eval_ParseInteger(const char *s, const char *base, const char **end)\n{\n    int         result = 0;\n    const int   len_base = strlen(base);\n    char        c;\n\n    while ((c = *s) != '\\0')\n    {\n        const char *digit = strchr(base, *s); // Note: this is not exactly the fastest thing to do...\n        if (digit == NULL)\n            break;\n        result = (result * len_base) + (digit - base);\n        s++;\n    }\n    *end = s;\n    return (result);\n}\n\nbool    Debugger_Eval_ParseConstant(const char *value, t_debugger_value *result, t_debugger_eval_value_format default_format)\n{\n    // Debugger_Printf(\" - token = %s\\n\", token);\n\n    // Assume default hexadecimal\n    t_debugger_eval_value_format value_format = default_format;\n    if (*value == '$')\n    {\n        value_format = DEBUGGER_EVAL_VALUE_FORMAT_INT_HEX;\n        value++;\n    }\n    else\n    if (*value == '%')\n    {\n        value_format = DEBUGGER_EVAL_VALUE_FORMAT_INT_BIN;\n        value++;\n    }\n    else\n    if (*value == '#')\n    {\n        value_format = DEBUGGER_EVAL_VALUE_FORMAT_INT_DEC;\n        value++;\n    }\n    else\n    if (*value == '0' && (value[1] == 'x' || value[1] == 'X'))\n    {\n        value_format = DEBUGGER_EVAL_VALUE_FORMAT_INT_HEX;\n        value += 2;\n    }\n\n    {\n        const char *  parse_end;\n        int data;\n        switch (value_format)\n        {\n        case DEBUGGER_EVAL_VALUE_FORMAT_INT_HEX:\n            data = Debugger_Eval_ParseIntegerHex(value, &parse_end);\n            break;\n        case DEBUGGER_EVAL_VALUE_FORMAT_INT_BIN:\n            data = Debugger_Eval_ParseInteger(value, \"01\", &parse_end);\n            break;\n        case DEBUGGER_EVAL_VALUE_FORMAT_INT_DEC:\n            data = Debugger_Eval_ParseInteger(value, \"0123456789\", &parse_end);\n            break;\n        default:\n            assert(0);\n            return false;\n        }\n\n        //if (data > (1<<15)-1 || data < -(1<<5))\n        if (data > 0xffff || data < -0x7fff)\n            Debugger_Value_SetDirect(result, data, 24);\n        else\n            Debugger_Value_SetDirect(result, data, 16);\n\n        if (*parse_end != '\\0')\n        {\n            // Syntax error\n            // Note: 'src' pointer not advanced, this is what we want here\n            return false;\n        }\n    }\n\n    return true;\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_Eval_GetValue(char **src_result, t_debugger_value *result)\n//-----------------------------------------------------------------------------\n// Parse a single value out of given string.\n// Advance string pointer.\n// Return:\n//  > 0 : success\n//    0 : no value found\n//  < 0 : parsing error\n//-----------------------------------------------------------------------------\nint    Debugger_Eval_GetValue(char **src_result, t_debugger_value *result)\n{\n    //t_debugger_eval_value_format value_format;\n    char    token_buf[256];\n    char *  token = token_buf;\n    char *  src = *src_result;\n    int     expr_error;\n\n    // Debugger_Printf(\"Debugger_Eval_GetValue(\\\"%s\\\")\\n\", src);\n    parse_skip_spaces(&src);\n\n    // Parenthesis open a sub expression\n    if (*src == '(')\n    {\n        src++;\n        expr_error = Debugger_Eval_ParseExpression(&src, result);\n        if (expr_error <= 0)\n            return (expr_error);\n        if (*src != ')')\n        {\n            // Unterminated parenthesis\n            Debugger_Printf(\"Syntax Error - Missing closing parenthesis!\\n\");\n            *src_result = src;\n            return (-1);\n        }\n        src++;\n        *src_result = src;\n        return (expr_error);\n    }\n\n    // Get token\n    if (!parse_getword(token_buf, sizeof(token_buf), &src, \" \\t\\n+-*/&|^(),.\", 0, PARSE_FLAGS_DONT_EAT_SEPARATORS))\n        return (0);\n    if (token[0] == '\\0')\n        return (0);\n\n    // Attempt to see if it's a variable\n    if (Debugger_Eval_ParseVariable(DEBUGGER_VARIABLE_REPLACEMENT_ALL, token, result))\n    {\n        *src_result = src;\n        return (1);\n    }\n\n    // Else a direct value\n    if (Debugger_Eval_ParseConstant(token, result))\n    {\n        *src_result = src;\n        return (1);\n    }\n\n    return (-1);\n}\n\nstatic int  Debugger_Eval_GetExpression_Block(char **expr, t_debugger_value *result)\n{\n    t_debugger_value value1;\n    t_debugger_value value2;\n\n    char* p = (char *)*expr;\n    // Debugger_Printf(\"Debugger_Eval_GetExpression_Block(\\\"%s\\\")\\n\", p);\n\n    parse_skip_spaces(&p);\n    if (p[0] == '\\0')\n    {\n        // Empty expression\n        return (0);\n    }\n\n    // Get first value\n    int expr_error = Debugger_Eval_GetValue(&p, &value1);\n    if (expr_error <= 0)\n    {\n        Debugger_Printf(\"Syntax error at \\\"%s\\\"!\\n\", p);\n        Debugger_Printf(\"                 ^ invalid value or label\\n\");\n        return (expr_error);\n    }\n    for (;;)\n    {\n        //parse_skip_spaces(&p);\n\n        // Get operator\n        const char op = *p;\n\n        if (op == ',' || op == '.' || op == ' ')\n            break;\n\n        // Chain of addition/subtraction are handled by Debugger_Eval_GetExpression()\n        if (op == '+' || op == '-')\n            break;\n\n        // Stop parsing here on end-of-string or parenthesis closure\n        if (op == '\\0' || op == ')')\n            break;\n\n        // Verify that we have a valid operator\n        if (!strchr(\"*/&|^\", op))\n        {\n            Debugger_Printf(\"Syntax error at \\\"%s\\\"!\\n\", p);\n            Debugger_Printf(\"                 ^ unexpected operator\\n\");\n            return (-1);\n        }\n        p++;\n\n        // Get a second value (since all our operator are binary operator now)\n        expr_error = Debugger_Eval_GetValue(&p, &value2);\n        if (expr_error <= 0)\n        {\n            Debugger_Printf(\"Syntax error at \\\"%s\\\"!\\n\", p);\n            Debugger_Printf(\"                 ^ invalid value or label\\n\");\n            return (expr_error);\n        }\n\n        {\n            // Process operator\n            int data_size = MAX(value1.data_size, value2.data_size);\n            switch (op)\n            {\n            case '&':\n                Debugger_Value_SetComputed(&value1, value1.data & value2.data, data_size);\n                break;\n            case '|':\n                Debugger_Value_SetComputed(&value1, value1.data | value2.data, data_size);\n                break;\n            case '^':\n                Debugger_Value_SetComputed(&value1, value1.data ^ value2.data, data_size);\n                break;\n            case '*':\n                Debugger_Value_SetComputed(&value1, value1.data * value2.data, data_size);\n                break;\n            case '/':\n                Debugger_Value_SetComputed(&value1, value1.data / value2.data, data_size);\n                break;\n            default:\n                assert(0);\n                break;\n            }\n        }\n    }\n\n    // Ok\n    *result = value1;\n    *expr = p;\n    return (1);\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_Eval_GetExpression(char **expr, t_debugger_value *result)\n//-----------------------------------------------------------------------------\n// Parse and evaluate expression from given string.\n// Advance string pointer.\n// Return:\n//  > 0 : success\n//    0 : no value found\n//  < 0 : parsing error\n//-----------------------------------------------------------------------------\n// Expression exemples:\n//  A\n//  (A)\n//  A+B\n//  A+B*C\n//  A+(B*C)\n//  ((0xFF^0x10)&%11110000)\n//-----------------------------------------------------------------------------\nint     Debugger_Eval_ParseExpression(char **expr, t_debugger_value *result)\n{\n    char *  p;\n    char    op;\n    int     expr_error;\n    t_debugger_value value1;\n    t_debugger_value value2;\n\n    p = (char *)*expr;\n    // Debugger_Printf(\"Debugger_Eval_GetExpression(\\\"%s\\\")\\n\", p);\n\n    parse_skip_spaces(&p);\n    if (p[0] == '\\0')\n    {\n        // Empty expression\n        return (0);\n    }\n\n    // Get first expression block\n    expr_error = Debugger_Eval_GetExpression_Block(&p, &value1);\n    if (expr_error <= 0)\n        return (expr_error);\n\n    for (;;)\n    {\n        //parse_skip_spaces(&p);\n\n        // Get operator\n        op = *p;\n\n        if (op == ',' || op == '.' || op == ' ')\n            break;\n\n        // Stop parsing here on end-of-string or parenthesis closure\n        if (op == '\\0' || op == ')')\n            break;\n\n        // Verify that we have a valid operator\n        if (!strchr(\"+-\", op))\n        {\n            Debugger_Printf(\"Syntax error at \\\"%s\\\"!\\n\", p);\n            Debugger_Printf(\"                 ^ unexpected operator\\n\");\n            return (-1);\n        }\n        p++;\n\n        // Get a second expression block (since all our operator are binary operator now)\n        expr_error = Debugger_Eval_GetExpression_Block(&p, &value2);\n        if (expr_error < 0)\n            return (expr_error);\n        if (expr_error == 0)\n        {\n            Debugger_Printf(\"Syntax error at \\\"%s\\\"!\\n\", p);\n            Debugger_Printf(\"                 ^ invalid value or label\\n\");\n            return (-1);\n        }\n\n        {\n            // Process operator\n            int data_size = MAX(value1.data_size, value2.data_size);\n            switch (op)\n            {\n            case '+':\n                Debugger_Value_SetComputed(&value1, value1.data + value2.data, data_size);\n                break;\n            case '-':\n                Debugger_Value_SetComputed(&value1, value1.data - value2.data, data_size);\n                break;\n            default:\n                assert(0);\n                break;\n            }\n        }\n    }\n\n    // Ok\n    *result = value1;\n    *expr = p;\n    return (1);\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - COMPLETION\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Debugger_CompletionCallback(t_widget *w)\n// Called by the input widget. Add completion string, if any.\n//-----------------------------------------------------------------------------\nbool        Debugger_CompletionCallback(t_widget *w)\n{\n    char *  current_word;\n    int     current_word_len;\n    bool    first_word;\n    t_list *matching_words;\n    int     matching_words_count = 0;\n    char *  result;\n\n    const char* word_delimiters = \" \\t\\r\\n,:;\";\n\n    // Get current word\n    int pos = widget_inputbox_get_cursor_pos(w);\n    const char *s = widget_inputbox_get_value(w) + pos;\n    current_word_len = 0;\n    while (pos-- > 0 && !strchr(word_delimiters, s[-1]))\n    {\n        s--;\n        current_word_len++;\n    }\n    // if (current_word_len == 0)\n    //    return false;\n    current_word = StrNDup(s, current_word_len);\n\n    // Attempt to find if there's a word before this\n    // We need this to contextually complete with commands (1st word) or symbols (subsequent words)\n    // This is kinda hacky (should split the string by token)\n    first_word = TRUE;\n    while (pos-- > 0)\n    {\n        if (!isspace(s[0]))\n        {\n            first_word = FALSE;\n            break;\n        }\n        s--;\n    }\n\n    // Build a list of matching words\n    matching_words = NULL;\n    matching_words_count = 0;\n\n    if (first_word)\n    {\n        // Complete with command\n        t_debugger_command_info *command_info = &DebuggerCommandInfos[0];\n        while (command_info->command_long != NULL)\n        {\n            if (!strnicmp(current_word, command_info->command_long, current_word_len))\n            {\n                list_add(&matching_words, (char *)command_info->command_long);\n                matching_words_count++;\n            }\n            command_info++;\n        }\n    }\n    else\n    {\n        // Complete with symbols\n        t_list *symbols;\n        for (symbols = Debugger.symbols; symbols != NULL; symbols = symbols->next)\n        {\n            t_debugger_symbol *symbol = (t_debugger_symbol *)symbols->elem;\n            if (!strnicmp(current_word, symbol->name, current_word_len))\n            {\n                list_add(&matching_words, symbol->name);\n                matching_words_count++;\n            }\n        }\n    }\n\n    if (matching_words_count == 0)\n    {\n        // No match\n        Debugger_Printf(\"No match for \\\"%s\\\"\\n\", current_word);\n        result = NULL;\n    }\n    else if (matching_words_count == 1)\n    {\n        // Single match, no ambiguity :)\n        const char *complete_word = (const char *)matching_words->elem;\n        result = strdup(complete_word);\n    }\n    else\n    {\n        // Multiple matches\n        int common_prefix_size;\n        t_list *matches;\n\n        // Sort matches by name\n        list_sort(&matching_words, (t_list_cmp_handler)stricmp);\n\n        // Print them\n        if (current_word_len > 0)\n            Debugger_Printf(\"%d matches for \\\"%s\\\":\\n\", matching_words_count, current_word);\n        else\n            Debugger_Printf(\"%d matches:\\n\", matching_words_count);\n        for (matches = matching_words; matches != NULL; matches = matches->next)\n        {\n            const char *complete_word = (const char *)matches->elem;\n            Debugger_Printf(\" - %s\\n\", complete_word);\n        }\n\n        // Find common prefix, if any\n        // FIXME: There's probably better algorithm to perform this.\n        common_prefix_size = current_word_len;\n        for (;;)\n        {\n            // Get current character of first match\n            char c;\n            matches = matching_words;\n            c = ((char *)matches->elem)[common_prefix_size];\n            if (c == '\\0')\n                break;\n\n            // Compare it with following matches\n            for (matches = matches->next; matches != NULL; matches = matches->next)\n            {\n                char c2 = ((char *)matches->elem)[common_prefix_size];\n                if (c != c2)\n                    break;\n            }\n            // Haven't got thru all the list means there was a difference, break\n            // Note: might want to use goto in this kind of case\n            if (matches != NULL)\n                break;\n            common_prefix_size++;\n        }\n\n        if (common_prefix_size > 0)\n        {\n            result = StrNDup((char *)matching_words->elem, common_prefix_size);\n        }\n        else\n        {\n            result = NULL;\n        }\n    }\n\n    // Free temporary work data\n    free(current_word);\n    list_free_custom(&matching_words, NULL);\n\n    // Complete\n    if (result != NULL)\n    {\n        // We want the full word to be replaced (this makes things prettier :)\n        // So we delete the beginning of the word\n        while (current_word_len-- > 0)\n            widget_inputbox_delete_current_char(w);\n\n        // Then, re-add the full word\n        widget_inputbox_insert_chars(w, result);\n        free(result);\n\n        // If we had only one match, add a space\n        if (matching_words_count == 1)\n            widget_inputbox_insert_chars(w, \" \");\n\n        return true;\n    }\n    else\n    {\n        return false;\n    }\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - HISTORY\n//-----------------------------------------------------------------------------\n\n// FIXME-OPT: Absolutely lame implementation, because we don't have decent data structure libraries.\nvoid    Debugger_History_AddLine(const char *line_to_add)\n{\n    t_debugger_history_item *item;\n    char *line;\n    char *line_uppercase;\n    bool item_added;\n    int n;\n\n    // Shift all history entries by one up to matching one which is moved back to front (entry 1).\n    // Entry 0 is current input line and is fixed.\n    // 3 bye        3 hello\n    // 2 hello  --> 2 sega\n    // 1 sega       1 <line>\n    // 0            0\n\n    // Duplicate line and convert to uppercase\n    // Even when we find a matching entry, we will replace it by was what typed to keep last character casing.\n    // It's a rather useless detail, meaning it is indispensable.\n    line = strdup(line_to_add);\n    line_uppercase = strdup(line_to_add);\n    StrUpper(line_uppercase);\n\n    // Search for duplicate entry in history\n    for (n = 1; n < Debugger.history_count; n++)\n    {\n        if (strcmp(Debugger.history[n].line_uppercase, line_uppercase) == 0)\n            break;\n    }\n\n    //Msg(MSGT_USER, \"n = %d, h_count = %d, h_max = %d\", n, Debugger.history_count, Debugger.history_max);\n\n    if (n < Debugger.history_count || n == Debugger.history_max - 1)\n    {\n        // Delete last or matching entry\n        free(Debugger.history[n].line);\n        free(Debugger.history[n].line_uppercase);\n        item_added = FALSE;\n    }\n    else\n    {\n        item_added = TRUE;\n    }\n\n    // Shift\n    while (n > 1)\n    {\n        Debugger.history[n] = Debugger.history[n - 1];\n        n--;\n    }\n\n    // Duplicate and add new entry\n    item = &Debugger.history[1];\n    item->line = line;\n    item->line_uppercase = line_uppercase;\n    item->cursor_pos = -1;\n\n    // Increase counter\n    if (item_added)\n        if (Debugger.history_count < Debugger.history_max)\n            Debugger.history_count++;\n\n    // Reset current index every time a new line is typed\n    Debugger.history_current_index = 0;\n}\n\n//-----------------------------------------------------------------------------\n// Debugger_History_Callback(t_widget *w)\n// Called by the input widget. Handle history.\n//-----------------------------------------------------------------------------\nbool        Debugger_History_Callback(t_widget *w, int level)\n{\n    if (level != -1 && level != 1)\n        return false;\n\n    // Bound check\n    const int new_index = Debugger.history_current_index + level;\n    if (new_index < 0 || new_index >= Debugger.history_count)\n        return false;\n\n    // If leaving index 0 (current line), save current line to item 0\n    if (Debugger.history_current_index == 0)\n    {\n        free(Debugger.history[0].line);\n        free(Debugger.history[0].line_uppercase);\n        Debugger.history[0].line = strdup(widget_inputbox_get_value(w));\n        Debugger.history[0].line_uppercase = strdup(Debugger.history[0].line);\n        Debugger.history[0].cursor_pos = widget_inputbox_get_cursor_pos(w);\n        StrUpper(Debugger.history[0].line_uppercase);\n    }\n\n    // Restore new item\n    widget_inputbox_set_value(w, Debugger.history[new_index].line);\n    if (Debugger.history[new_index].cursor_pos != -1)\n        widget_inputbox_set_cursor_pos(w, Debugger.history[new_index].cursor_pos);\n    Debugger.history_current_index = new_index;\n\n    return true;\n}\n\nvoid        Debugger_History_List(const char *search_term_arg)\n{\n    int     index;\n    char   *search_term;\n\n    if (search_term_arg)\n    {\n        Debugger_Printf(\"History lines matching \\\"%s\\\":\\n\", search_term_arg);\n        search_term = strdup(search_term_arg);\n        StrUpper(search_term);\n    }\n    else\n    {\n        Debugger_Printf(\"History:\\n\");\n        search_term = NULL;\n    }\n    //if (n <= 1)  // It's always 1 as current command was already pushed into history\n    //{\n    //    Debugger_Printf(\" <None>\\n\");\n    //    return;\n    //}\n\n    for (index = Debugger.history_count - 1; index >= 1; index--)\n    {\n        t_debugger_history_item *item = &Debugger.history[index];\n\n        // If search term was specified, skip history line not matching it\n        if (search_term != NULL)\n            if (strstr(item->line_uppercase, search_term) == NULL)\n                continue;\n\n        // Print\n        Debugger_Printf(\" %*s[%d] %s\\n\",\n            (Debugger.history_count >= 10 && index < 10) ? 1 : 0, \"\",\n            index, Debugger.history[index]);\n    }\n\n    if (search_term != NULL)\n    {\n        // Free the uppercase duplicate we made\n        free(search_term);\n    }\n}\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS - REVERSE MAP\n//-----------------------------------------------------------------------------\n\nint         Debugger_ReverseMapFindRomAddress(u16 addr, bool* is_bios)\n{\n    const int mem_pages_index = (addr >> 13);\n    const u8 *mem_pages_base = Mem_Pages[mem_pages_index] + (mem_pages_index << 13);\n\n    int offset;\n\n    // - ROM\n    offset = (mem_pages_base - ROM) + (addr & 0x1FFF);\n    if (offset >= 0 && offset < tsms.Size_ROM)\n    {\n        if (is_bios) *is_bios = false;\n        return offset;\n    }\n\n    // - ROM (special hack for first 1 KB)\n    // FIXME: Report ROM instead of SMS BIOS in those cases. Anyway SMS BIOS is poorly emulated.\n    offset = (mem_pages_base - Game_ROM_Computed_Page_0) + (addr & 0x1FFF);\n    if (offset >= 0 && offset < 0x4000)\n    {\n        if (is_bios) *is_bios = false;\n        return offset;\n    }\n\n    // - BIOSes\n    offset = (mem_pages_base - BIOS_ROM) + (addr & 0x1fff);\n    if (offset >= 0 && offset < 0x2000)\n    {\n        if (is_bios) *is_bios = true;\n        return offset;\n    }\n    offset = (mem_pages_base - BIOS_ROM_Jap) + (addr & 0x1fff);\n    if (offset >= 0 && offset < 0x2000)\n    {\n        if (is_bios) *is_bios = true;\n        return offset;\n    }\n    offset = (mem_pages_base - BIOS_ROM_Coleco) + (addr & 0x1fff);\n    if (offset >= 0 && offset < 0x2000)\n    {\n        if (is_bios) *is_bios = true;\n        return offset;\n    }\n    offset = (mem_pages_base - BIOS_ROM_SF7000) + (addr & 0x1fff);\n    if (offset >= 0 && offset < 0x4000)\n    {\n        if (is_bios) *is_bios = true;\n        return offset;\n    }\n\n    return -1;\n}\n\n//-----------------------------------------------------------------------------\n// Note: this is completely hard-coded to handle the most common cases.\n// The reason is that this feature was planned since a long time using a more\n// generic approach, but since I could not get myself to code that version, I'd\n// rather code the simple one so it is immediately useful.\n//-----------------------------------------------------------------------------\n// FIXME: Could support mappers registers, although it's not super useful.\n// FIXME: Not great at supporting mirrored ranges.\n//-----------------------------------------------------------------------------\nvoid        Debugger_ReverseMap(u16 addr)\n{\n    int     ram_len;\n    int     ram_start_addr;\n    Mapper_Get_RAM_Infos(&ram_len, &ram_start_addr);\n\n    int     sram_len;\n    u8 *    sram_buf;\n    BMemory_Get_Infos((void**)&sram_buf, &sram_len);\n\n    //if (addr < 0x400)\n    //  Debugger_Printf(\" Z80 $%04X = ROM $%05X (Page %d, Offset %d)\", addr, addr, 0, addr & 0x3FFF);\n\n    const int mem_pages_index = (addr >> 13);\n    const u8 *mem_pages_base = Mem_Pages[mem_pages_index] + (mem_pages_index << 13);\n\n    // Pages can be pointing to:\n    // - ROM\n    // - Game_ROM_Computed_Page_0\n    // - RAM\n    // - SRAM\n    // - BIOS_ROM\n    // - BIOS_ROM_Jap\n    // - BIOS_ROM_Coleco\n    // - BIOS_ROM_SF7000\n    // Using direct pointer arithmetic comparisons.\n    int offset;\n\n    // - ROM, Game_ROM_Computed_Page_0, BIOS_ROM*\n    bool is_bios;\n    offset = Debugger_ReverseMapFindRomAddress(addr, &is_bios);\n    if (offset != -1)\n    {\n        if (is_bios)\n            Debugger_Printf(\" Z80 $%04X = BIOS $%04X\", addr, offset);\n        else\n            Debugger_Printf(\" Z80 $%04X = ROM $%05X (Page %X +%04X)\", addr, offset, offset >> 14, addr & 0x3FFF);\n    }\n\n    // - RAM\n    offset = (mem_pages_base - RAM) + (addr & MIN(0x1fff, ram_len - 1));\n    if (offset >= 0 && offset < ram_len)\n        Debugger_Printf(\" Z80 $%04X = RAM $%04X\", addr, ram_start_addr + offset);\n        //Debugger_Printf(\" Z80 $%04X = RAM $%04X = RAM $%04X\", addr, ram_start_addr + offset, ram_start_addr + ram_len + offset);\n\n    // - SRAM\n    offset = (mem_pages_base - SRAM) + (addr & MIN(0x1fff, sram_len - 1));\n    if (offset >= 0 && offset < sram_len)\n        Debugger_Printf(\" Z80 $%04X = SRAM $%04X\", addr, offset);\n\n    //break;\n}\n\n//-----------------------------------------------------------------------------\n\n#endif // ifdef MEKA_Z80_DEBUGGER\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/debugger.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - debugger.h\r\n// Z80 Debugger - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef MEKA_Z80_DEBUGGER\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n#define DEBUGGER_VARIABLE_REPLACEMENT_CPU_REGS  (0x0001)\r\n#define DEBUGGER_VARIABLE_REPLACEMENT_SYMBOLS   (0x0002)\r\n#define DEBUGGER_VARIABLE_REPLACEMENT_ALL       (DEBUGGER_VARIABLE_REPLACEMENT_CPU_REGS | DEBUGGER_VARIABLE_REPLACEMENT_SYMBOLS)\r\n\r\n#define DEBUGGER_DATA_COMPARE_LENGTH_MAX        (8)\r\n\r\n#define BREAKPOINT_ACCESS_R                     (0x01)\r\n#define BREAKPOINT_ACCESS_W                     (0x02)\r\n#define BREAKPOINT_ACCESS_X                     (0x04)\r\n#define BREAKPOINT_ACCESS_RW                    (BREAKPOINT_ACCESS_R | BREAKPOINT_ACCESS_W)\r\n#define BREAKPOINT_ACCESS_RWX                   (BREAKPOINT_ACCESS_R | BREAKPOINT_ACCESS_W | BREAKPOINT_ACCESS_X)\r\n#define BREAKPOINT_ACCESS_E                     (0x08)\r\n\r\n#define BREAKPOINT_LOCATION_CPU                 (0)\r\n#define BREAKPOINT_LOCATION_ROM                 (1)\r\n#define BREAKPOINT_LOCATION_IO                  (2)\r\n#define BREAKPOINT_LOCATION_VRAM                (3)\r\n#define BREAKPOINT_LOCATION_PRAM                (4)\r\n#define BREAKPOINT_LOCATION_LINE                (5)\r\n#define BREAKPOINT_LOCATION_MAX_                (6)\r\n\r\n#define BREAKPOINT_TYPE_BREAK                   (0)\r\n#define BREAKPOINT_TYPE_WATCH                   (1)\r\n\r\nstruct t_debugger_breakpoint\r\n{\r\n    int         enabled;\r\n    int         id;\r\n    int         type;\r\n    int         location;\r\n    int         access_flags;\r\n    int         address_range[2];               // If single address, both values are equal\r\n    int         auto_delete;                    // If -1, decrement on each break, delete when 0\r\n    int         data_compare_length;\r\n    u8          data_compare_bytes[DEBUGGER_DATA_COMPARE_LENGTH_MAX];\r\n    char *      desc;\r\n};\r\n\r\nstruct t_debugger_bus_info\r\n{\r\n    int         location;\r\n    const char* name;\r\n    int         bus_addr_size;  // in bytes\r\n    int         addr_min;\r\n    int         addr_max;\r\n    int         access;\r\n    int         data_compare_length_max;\r\n};\r\n\r\nstruct t_debugger_symbol\r\n{\r\n    u16         cpu_addr;\r\n    u32         rom_addr;\r\n    int         bank;                           // Currently unsupported, set to -1\r\n    char *      name;\r\n    char *      name_uppercase;                 // For grep\r\n};\r\n\r\nstruct t_debugger_history_item\r\n{\r\n    char *      line;\r\n    char *      line_uppercase;                 // For grep\r\n    int         cursor_pos;                     // -1 = end\r\n};\r\n\r\nenum t_debugger_value_flags\r\n{\r\n    DEBUGGER_VALUE_FLAGS_ACCESS_READ    = 0x01,\r\n    DEBUGGER_VALUE_FLAGS_ACCESS_WRITE   = 0x02,\r\n};\r\n\r\nenum t_debugger_value_source\r\n{\r\n    DEBUGGER_VALUE_SOURCE_COMPUTED,             // Computed\r\n    DEBUGGER_VALUE_SOURCE_DIRECT,               // Direct input value\r\n    DEBUGGER_VALUE_SOURCE_CPU_REG,              // From CPU\r\n    DEBUGGER_VALUE_SOURCE_SYMBOL_CPU_ADDR,      // From symbol\r\n    DEBUGGER_VALUE_SOURCE_SYMBOL_ROM_ADDR,      //\r\n};\r\n\r\n// 'value' also refered as 'variables'\r\nstruct t_debugger_value\r\n{\r\n    u32                     data;               // Value data\r\n    u16                     data_size;          // Value size in bits\r\n    int                     flags;              // Value flags (enum t_debugger_value_flags) // FIXME-ENUM\r\n    t_debugger_value_source source;             // Value source type\r\n    void *                  source_data;        // Value source (if applicable)\r\n    const char *            name;               // Value name\r\n};\r\n\r\nenum t_debugger_eval_value_format\r\n{\r\n    DEBUGGER_EVAL_VALUE_FORMAT_UNKNOWN,\r\n    DEBUGGER_EVAL_VALUE_FORMAT_INT_HEX,\r\n    DEBUGGER_EVAL_VALUE_FORMAT_INT_BIN,\r\n    DEBUGGER_EVAL_VALUE_FORMAT_INT_DEC,\r\n    DEBUGGER_EVAL_VALUE_FORMAT_STRING,\r\n};\r\n\r\n// 16 bytes per entry\r\n// same order as in Z80 structure so we can memcpy() the whole thing\r\nstruct t_debugger_exec_log_entry\r\n{\r\n    u16 af, bc, de, hl, ix, iy, pc, sp;\r\n};\r\n\r\nstruct t_debugger\r\n{\r\n    int                         enabled;                        // Enabled and initialized\r\n    bool                        active;                         // Currently showing on GUI\r\n    bool                        trap_set;\r\n    u16                         trap_address;\r\n    int                         stepping;                       // Set when we are doing a single step\r\n    int                         stepping_trace_after;\r\n    bool                        stepping_out_enable;            // Run until RET && SP >= step_out_stack_ref\r\n    u16                         stepping_out_stack_ref;\r\n\r\n    t_list *                    breakpoints;\r\n    t_list *                    breakpoints_cpu_space[0x10000]; // 0000-FFFF : each Z80 address has its list of applicable breakpoints\r\n    t_list *                    breakpoints_io_space[0x100];\r\n    t_list *                    breakpoints_vram_space[0x4000];\r\n    t_list *                    breakpoints_pram_space[0x40];\r\n    t_list *                    breakpoints_line_space[313];\r\n\r\n    // This is like with breakpoints_cpu_space but with direct access to merged CPU read breakpoints. \r\n    // The Z80 emulator use that to trap CPU read of first opcode byte *BEFORE* execution started.\r\n    // Whereas normal breakpoints are stopping the CPU after the event happened.\r\n    int                         cpu_exec_traps[0x10000];\r\n\r\n    t_list *                    symbols;\r\n    int                         symbols_count;\r\n    t_list *                    symbols_cpu_space[0x10000];\r\n\r\n    int                         history_max;\r\n    int                         history_count;\r\n    t_debugger_history_item *   history;\r\n    int                         history_current_index;          // 0: new/current edit line, 1+: history lines items\r\n\r\n    t_list *                    variables_cpu_registers;\r\n    FILE *                      log_file;\r\n    const char *                log_filename;\r\n    int                         watch_counter;                  // For current frame\r\n    long long                   cycle_counter;                  // Cycle counting accumulator. Only increment in RunZ80_Debugging(), not RunZ80(). \r\n\r\n    // PC logging/trackbacking\r\n    u16                         pc_last;\r\n    u8                          pc_exec_points[0x10000];\r\n    std::vector<t_debugger_exec_log_entry>  pc_detail_log_data;\r\n    size_t                      pc_detail_log_head;\r\n    size_t                      pc_detail_log_count;\r\n    bool                        pc_detail_log_show_extra_registers;\r\n    int                         trackback_scroll_offset;        // Mouse wheel to scroll disassembly\r\n};\r\n\r\nextern t_debugger   Debugger;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Init\r\nvoid                        Debugger_Init_Values(void);\r\nvoid                        Debugger_Init(void);\r\nvoid                        Debugger_Close(void);\r\n\r\n// Main\r\nvoid                        Debugger_MachineReset(void);\r\nvoid                        Debugger_MediaReload(void);\r\nvoid                        Debugger_Enable(void);\r\nvoid                        Debugger_Update(void);\r\nvoid                        Debugger_Switch(void);\r\nvoid                        Debugger_Printf(const char *format, ...);\r\nvoid                        Debugger_InputParseCommand(char* line);\r\n\r\n// Symbols\r\nbool                        Debugger_Symbols_Load();\r\nconst t_debugger_symbol *   Debugger_Symbols_GetFirstByAddr(u32 cpu_addr);\r\nconst t_debugger_symbol *   Debugger_Symbols_GetLastByAddr(u32 cpu_addr);\r\nconst t_debugger_symbol *   Debugger_Symbols_GetClosestPreviousByAddr(u32 cpu_addr, int range);\r\n\r\n// Hooks\r\nint                         Debugger_Hook(Z80 *R);\r\nvoid                        Debugger_RasterLine_Hook(register int line);\r\nvoid                        Debugger_RdVRAM_Hook(register int addr, register u8 value);\r\nvoid                        Debugger_WrVRAM_Hook(register int addr, register u8 value);\r\nvoid                        Debugger_WrPRAM_Hook(register int addr, register u8 value);\r\n\r\n// Parser\r\nbool                        Debugger_Eval_ParseConstant(const char *value, t_debugger_value *result, t_debugger_eval_value_format default_format = DEBUGGER_EVAL_VALUE_FORMAT_INT_HEX);\r\nint                         Debugger_Eval_ParseIntegerHex(const char* s, const char** out_end = NULL);\r\n\r\n// Bus Data Access Helpers\r\nint                         Debugger_Bus_Read(int bus, int addr);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n#endif\r\n"
  },
  {
    "path": "meka/srcs/desktop.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - desktop.c\r\n// Desktop Manager - Code\r\n//-----------------------------------------------------------------------------\r\n// Save position and size of windows on the desktop.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"desktop.h\"\r\n#include \"libparse.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_desktop Desktop;\r\n\r\nstruct t_desktop_item\r\n{\r\n    const char *    name;\r\n    t_gui_box *     box;\r\n    v2i             pos;\r\n    v2i             size;\r\n    int             z;\r\n    bool            active;\r\n    bool *          active_org;\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declarations\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     Desktop_GetStateFromBoxes();\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Desktop_Init()\r\n{\r\n    Desktop.items = NULL;\r\n    Desktop_Load();\r\n}\r\n\r\nvoid    Desktop_Close()\r\n{\r\n    Desktop_GetStateFromBoxes();\r\n    Desktop_Save();\r\n}\r\n\r\nstatic t_desktop_item * Desktop_Item_New(const char *name, t_gui_box *box)\r\n{\r\n    t_desktop_item* item = (t_desktop_item*)Memory_Alloc(sizeof(t_desktop_item));\r\n\r\n    item->name  = strdup(name);\r\n    item->box   = box;  // Note: can be NULL at this stage\r\n    item->pos.x = 0;\r\n    item->pos.y = 0;\r\n    item->size.x = 0;\r\n    item->size.y = 0;\r\n    item->z      = 0;\r\n    item->active = true;\r\n    item->active_org = NULL;\r\n\r\n    return item;\r\n}\r\n\r\n// FIXME: Desktop_Item_Delete()\r\n\r\nvoid    Desktop_Register_Box(const char *name, t_gui_box *box, int default_active, bool *active_org)\r\n{\r\n    for (t_list* list = Desktop.items; list != NULL; list = list->next)\r\n    {\r\n        t_desktop_item* item = (t_desktop_item*)list->elem;\r\n        if (strcmp(item->name, name) == 0)\r\n        {\r\n            // ConsolePrintf (\"found old %s\\n\", name);\r\n            item->box = box;\r\n            item->active_org = active_org;\r\n            box->frame.pos = item->pos;\r\n            if ((box->flags & GUI_BOX_FLAGS_ALLOW_RESIZE) && (box->type != GUI_BOX_TYPE_GAME))\r\n                if (item->size.x > 0 && item->size.y > 0)\r\n                    gui_box_resize(box, item->size.x, item->size.y, false);\r\n            *(active_org) = item->active;\r\n            //gui_box_clip_position (b);\r\n            //gui_box_show (b, item->active, FALSE); // FIXME: Focus\r\n            return;\r\n        }\r\n    }\r\n\r\n    // ConsolePrintf (\"make new %s\\n\", name);\r\n    // Make new item, retrieve current data from box (unnecessary?)\r\n    t_desktop_item* item = (t_desktop_item*)Desktop_Item_New(name, box);\r\n    item->pos           = box->frame.pos;\r\n    item->size          = box->frame.size;\r\n    item->active_org    = active_org;\r\n    item->active        = default_active;\r\n    *(item->active_org) = default_active;\r\n    gui_box_show(box, item->active, FALSE); // FIXME: Focus\r\n\r\n    // Add new item to list\r\n    list_add(&Desktop.items, item);\r\n}\r\n\r\nstatic void Desktop_GetStateFromBoxes()\r\n{\r\n    for (t_list* list = Desktop.items; list != NULL; list = list->next)\r\n    {\r\n        t_desktop_item* item = (t_desktop_item*)list->elem;\r\n        if (item->box != NULL)\r\n        {\r\n            item->pos = item->box->frame.pos;\r\n            item->size = item->box->frame.size;\r\n            item->active = *item->active_org;\r\n        }\r\n    }\r\n}\r\n\r\nstatic int  Desktop_ItemCmpByZ(void* lhs, void* rhs)\r\n{\r\n    return ((t_desktop_item*)rhs)->z - ((t_desktop_item*)lhs)->z;\r\n}\r\n\r\nvoid    Desktop_SetStateToBoxes()\r\n{\r\n    // Goes thru all boxes to set their position/active state\r\n    //list_sort(&Desktop.items, (t_list_cmp_handler)Desktop_ItemCmpByZ);\r\n    for (t_list* list = Desktop.items; list != NULL; list = list->next)\r\n    {\r\n        t_desktop_item* item = (t_desktop_item*)list->elem;\r\n        if (item->box != NULL)\r\n        {\r\n            // Set state for this box\r\n            t_gui_box *b = item->box;\r\n            //b->frame.pos.x = item->pos_x;\r\n            //b->frame.pos.y = item->pos_y;\r\n            *item->active_org = item->active;\r\n            gui_box_clip_position(b);\r\n            gui_box_show(b, item->active, FALSE);\r\n            if (item->active)\r\n                gui_box_set_focus(b);\r\n        }\r\n    }\r\n}\r\n\r\nstatic t_desktop_item*  item_current = NULL;\r\n\r\nstatic int  Desktop_Load_Line(char *line)\r\n{\r\n    if (line[0] == '[')\r\n    {\r\n        line++;\r\n\r\n        char name[256];\r\n        if (!parse_getword(name, sizeof(name), &line, \"]\", ';', PARSE_FLAGS_DONT_EAT_SEPARATORS))\r\n            return MEKA_ERR_SYNTAX;\r\n        if (*line != ']')\r\n            return MEKA_ERR_SYNTAX;\r\n\r\n        // Create new skin\r\n        t_desktop_item* item = Desktop_Item_New(name, NULL);\r\n        list_add_to_end(&Desktop.items, item);\r\n        item_current = item;\r\n        return MEKA_ERR_OK;\r\n    }\r\n    else\r\n    {\r\n        t_desktop_item* item = item_current;\r\n\r\n        // Read line\r\n        char var[256];\r\n        if (!parse_getword(var, sizeof(var), &line, \"=\", ';', PARSE_FLAGS_NONE))\r\n            return MEKA_ERR_OK;\r\n        parse_skip_spaces(&line);\r\n\r\n        if (!item)\r\n            return MEKA_ERR_MISSING;\r\n\r\n        if (strcmp(var, \"active\") == 0)\r\n        {\r\n            int a;\r\n            if (sscanf(line, \"%d\", &a) == 1)\r\n                item->active = a != 0;\r\n            return MEKA_ERR_OK;\r\n        }\r\n        if (strcmp(var, \"pos\") == 0)\r\n        {\r\n            int x, y;\r\n            if (sscanf(line, \"%d,%d\", &x, &y) == 2)\r\n            {\r\n                item->pos.x = x;\r\n                item->pos.y = y;\r\n            }\r\n            return MEKA_ERR_OK;\r\n        }\r\n        if (strcmp(var, \"size\") == 0)\r\n        {\r\n            int x, y;\r\n            if (sscanf(line, \"%d,%d\", &x, &y) == 2)\r\n            {\r\n                item->size.x = x;\r\n                item->size.y = y;\r\n            }\r\n            return MEKA_ERR_OK;\r\n        }\r\n    }\r\n\r\n    return MEKA_ERR_OK;\r\n}\r\n\r\nvoid    Desktop_Load()\r\n{\r\n    // Open and read file\r\n    t_tfile* tf;\r\n    if ((tf = tfile_read(Desktop.filename)) == NULL)\r\n        return;\r\n\r\n    // Parse each line\r\n    int line_cnt = 0;\r\n    item_current = NULL;\r\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        line_cnt += 1;\r\n        char* line = (char*)lines->elem;\r\n        Desktop_Load_Line(line);\r\n    }\r\n    item_current = NULL;\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n}\r\n\r\nstatic void    Desktop_Save_Item(t_desktop_item *item, FILE *f)\r\n{\r\n    fprintf(f, \"[%s]\\n\", item->name);\r\n    fprintf(f, \"active=%d\\n\", item->active);\r\n    fprintf(f, \"pos=%d,%d\\n\", item->pos.x, item->pos.y);\r\n    if (item->box->flags & GUI_BOX_FLAGS_ALLOW_RESIZE)\r\n        fprintf(f, \"size=%d,%d\\n\", item->size.x, item->size.y);\r\n    fprintf(f, \"\\n\");\r\n}\r\n\r\nvoid    Desktop_Save()\r\n{\r\n    FILE * f;\r\n    if ((f = fopen(Desktop.filename, \"wt\")) == 0)\r\n        return; // FIXME: report that somewhere ?\r\n\r\n    // Write header\r\n    fprintf(f, \";-----------------------------------------------------------------------------\\n\");\r\n    fprintf(f, \"; \" MEKA_NAME \" \" MEKA_VERSION \" - Desktop State\\n\");\r\n    fprintf(f, \"; This file is automatically updated and rewritten by the emulator\\n\");\r\n    fprintf(f, \";-----------------------------------------------------------------------------\\n\\n\");\r\n\r\n    // Write all entries\r\n    for (t_list* list = Desktop.items; list != NULL; list = list->next)\r\n    {\r\n        t_desktop_item* item = (t_desktop_item*)list->elem;\r\n        item->z = gui_box_find_z(item->box);\r\n    }\r\n    list_sort(&Desktop.items, (t_list_cmp_handler)Desktop_ItemCmpByZ);\r\n    for (t_list* list = Desktop.items; list != NULL; list = list->next)\r\n        Desktop_Save_Item((t_desktop_item*)list->elem, f);\r\n\r\n    fprintf(f, \";-----------------------------------------------------------------------------\\n\\n\");\r\n\r\n    // Close write\r\n    fclose (f);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/desktop.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - desktop.h\n// Desktop Manager - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// DATA\n//-----------------------------------------------------------------------------\n\nstruct t_desktop\n{\n    t_list *        items;\n    char            filename[FILENAME_LEN];\n};\n\nextern t_desktop    Desktop;\n\n//-----------------------------------------------------------------------------\n// FUNCTIONS\n//-----------------------------------------------------------------------------\n\nvoid    Desktop_Init();\nvoid    Desktop_Close();\nvoid    Desktop_SetStateToBoxes();\n\nvoid    Desktop_Register_Box(const char *name, t_gui_box* box, int default_active, bool* active_org);\n\nvoid    Desktop_Load();\nvoid    Desktop_Save();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/drivers.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - drivers.c\r\n// Machine Drivers - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_palview.h\"\r\n#include \"app_tileview.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nts_driver * g_driver = NULL;\r\n\r\nstatic ts_driver drivers [DRV_MAX] =\r\n{\r\n  // Note: the \"colors\" field is the number of colors to be shown in the Palette applet                                      (work)\r\n  // Driver ----- Name ------- Full Name ------------ CPU ----- VDP Chip --- SND Chip ------ X -- Y -- XS - YS - XE - YSS/SE/INT - C - RAM -----\r\n  {  DRV_SMS,    \"SMS\",      \"Sega Master System\",    CPU_Z80,  VDP_SMSGG,   SND_SN76489,    256, 192,  0,  0,   255, 0,  0,  0,  32,  0x02000 },\r\n  {  DRV_GG,     \"GG\",       \"Sega Game Gear\",        CPU_Z80,  VDP_SMSGG,   SND_SN76489,    160, 144, 48, 24,   207, 0,  0,  0,  32,  0x02000 },\r\n  {  DRV_SG1000, \"SG-1000\",  \"Sega Game 1000\",        CPU_Z80,  VDP_TMS9918, SND_SN76489AN,  256, 192,  0,  0,   255, 0,  0,  0,  16,  0x01000 },\r\n  {  DRV_SC3000, \"SC-3000\",  \"Sega Computer 3000\",    CPU_Z80,  VDP_TMS9918, SND_SN76489AN,  256, 192,  0,  0,   255, 0,  0,  0,  16,  0x08000 },\r\n  {  DRV_COLECO, \"COLECO\",   \"Coleco Vision\",         CPU_Z80,  VDP_TMS9918, SND_SN76489AN,  256, 192,  0,  0,   255, 0,  0,  0,  16,  0x00400 },\r\n  {  DRV_MSX___, \"MSX\",      \"MSX-1\",                 CPU_Z80,  VDP_TMS9918, SND_SN76489AN,  256, 192,  0,  0,   255, 0,  0,  0,  16,  0 /*?*/ },\r\n  {  DRV_NES___, \"NES\",      \"Nintendo\",              0,    0,       0,        256, 240,  0,  0,   255, 0,  0,  0,  32,  0x00800 },\r\n  {  DRV_SF7000, \"SF-7000\",  \"Super Control Station\", CPU_Z80,  VDP_TMS9918, SND_SN76489AN,  256, 192,  0,  0,   255, 0,  0,  0,  16,  0x10000 }\r\n  // Driver ----- Name ------- Full Name ------------ CPU ----- VDP Chip --- SND Chip ------ X -- Y -- XS - YS - XE - YSS/SE/INT - C - RAM -----\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic const ts_driver_filename_extension   drivers_ext [] =\r\n{\r\n    { \"SMS\",      DRV_SMS         },\r\n    { \"MK3\",      DRV_SMS         },\r\n    { \"GG\",       DRV_GG          },\r\n    { \"SG\",       DRV_SG1000      },\r\n    { \"SC\",       DRV_SC3000      },\r\n    { \"SF7\",      DRV_SF7000      },\r\n    { \"DSK\",      DRV_SF7000      },\r\n    { \"OMV\",      DRV_SG1000      }, // Othello Multivision\r\n    { \"COL\",      DRV_COLECO      },\r\n    { \"ROM\",      DRV_COLECO      },\r\n    { \"BIN\",      DRV_COLECO      },\r\n    { 0,          DRV_SMS         }\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    drv_init()\r\n{\r\n    drv_set (DRV_SMS);\r\n}\r\n\r\nvoid    drv_set(int num)\r\n{\r\n    if (num < 0 || num >= DRV_MAX)\r\n    {\r\n        Quit_Msg(\"%s\", Msg_Get(MSG_Driver_Unknown));\r\n    }\r\n    else\r\n    {\r\n        g_driver = &drivers[num];\r\n        if (opt.GUI_Inited == TRUE)\r\n        {\r\n            int palette_max = 2;\r\n            switch (g_driver->vdp)\r\n            {\r\n                case VDP_SMSGG:     palette_max = 2;  break;\r\n                case VDP_TMS9918:   palette_max = 15; break;\r\n            }\r\n            TileViewer_Configure_PaletteMax(palette_max);\r\n            PaletteViewer_SetPaletteSize(&PaletteViewer, g_driver->colors);\r\n        }\r\n    }\r\n}\r\n\r\nint         drv_get_from_filename_extension(const char *filename_extension)\r\n{\r\n  int i = 0;\r\n    while (drivers_ext [i].filename_extension != NULL)\r\n    {\r\n        if (stricmp(filename_extension, drivers_ext [i].filename_extension) == 0)\r\n            return (drivers_ext [i].driver);\r\n        i++;\r\n    }\r\n    return (drivers_ext [i].driver);\r\n}\r\n\r\nint     drv_is_known_filename_extension(const char *filename_extension)\r\n{\r\n  for (const ts_driver_filename_extension* p = drivers_ext; p->filename_extension != NULL; ++p)\r\n  {\r\n    if (stricmp(filename_extension, p->filename_extension) == 0)\r\n    {\r\n      return true;\r\n    }\r\n  }\r\n  return false;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// drv_id_to_mode(int id)\r\n// Convert driver ID to the old kind of ID\r\n// (used by the savestate loader, when MSV version is < 0x05\r\n//-----------------------------------------------------------------------------\r\nint     drv_id_to_mode(int id)\r\n{\r\n  switch (id)\r\n  {\r\n  case DRV_GG:        return (1);\r\n  case DRV_SG1000:    return (2);\r\n  case DRV_SC3000:    return (2 | 8);\r\n  case DRV_COLECO:    return (2 | 4);\r\n  case DRV_SF7000:    return (-1); // Was not existing, then\r\n  }\r\n  return (0);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/drivers.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - drivers.h\n// Machine Drivers - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n// Note: this field is saved into savestate so we have to maintain its binary compatibility.\nenum t_machine_driver\n{\n  DRV_SMS   = 0,\n  DRV_GG      = 1,\n  DRV_SG1000  = 2,\n  DRV_SC3000  = 3,\n  DRV_COLECO  = 4,\n  DRV_MSX___  = 5,\n  DRV_NES___  = 6,\n  DRV_SF7000  = 7,\n  DRV_MAX   = 8,\n};\n\n// CPU Type\n#define CPU_Z80         (0)\n\n// VDP Type\n#define VDP_SMSGG       (0)\n#define VDP_TMS9918     (1)\n\n// Sound Type\n#define SND_SN76489AN   (0)\n#define SND_SN76489     (1)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct ts_driver\n{\n  u8      id;\n  const char *  short_name;\n  const char *  full_name;\n  int   cpu;\n  int   vdp;\n  int   snd;\n  int   x_res;\n  int   y_res;\n  int   x_start;\n  int   y_start;\n  int   x_end;\n  int   y_show_start; // Working variable\n  int   y_show_end;   // Working variable\n  int   y_int;        // Working variable\n  int   colors;\n  int   ram;\n};\n\nextern ts_driver * g_driver;\n\nstruct ts_driver_filename_extension\n{\n    const char *  filename_extension;\n    int       driver;\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid                    drv_init();\nvoid                    drv_set(int);\nint                     drv_get_from_filename_extension(const char* filename_extension);\nint                     drv_is_known_filename_extension(const char* filename_extension);\nint                     drv_id_to_mode(int);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/eagle.asm",
    "content": ";\r\n; Eagle.asm\r\n;\r\n; Eagle version 0.41 for NASM\r\n;\r\n; Written by Dirk Stevens\r\n;\r\n; compile with : nasm -f coff eagle.asm for use with DJGPP\r\n; Using optimization with DJGPP and coff objects could result in\r\n; erronous behaviour!\r\n;\r\n; History :\r\n; Date      Version     Comments\r\n;\r\n; 30-Sep-1998     0.41          - Minor modification in 16bit MMX code\r\n;\r\n; 20-Jun-1998   0.40            -Added 16bit color support for MMX\r\n;                       -Incorporated Larry Bank's suggestions\r\n;\r\n; 29-March-1998   0.31          -eagle_bmp for use in plain bmps\r\n;\r\n; 28-March-1998 0.30            -Handle buffer internally\r\n;                       -Added optimised MMX copying (fast!)\r\n;                       -Everything is done in one routine\r\n;\r\n; 15-March-1998 0.20            -First NASM version\r\n;                       -Added parameter for Eagle_Lines\r\n;                       -Added support for MMX\r\n;                       -Optimised further for non-MMX\r\n;\r\n;------------------------------------------------------------\r\n\r\n      BITS 32\r\n\r\n\r\n%IFDEF ASM_SYMBOLS_REQUIRE_UNDERSCORE\r\n%DEFINE _eagle          eagle\r\n%DEFINE _eagle_mmx16    eagle_mmx16\r\n%DEFINE _eagle_bmp      eagle_bmp\r\n%ENDIF ; ASM_SYMBOLS_REQUIRE_UNDERSCORE\r\n    \r\nGLOBAL _eagle\r\nGLOBAL _eagle_mmx16\r\nGLOBAL _eagle_bmp\r\nSECTION .text\r\n\r\n;eagle       (  unsigned long *lb,\r\n;               unsigned long *lb2,\r\n;               int width,\r\n;           int destination_segment,\r\n;           screen_address1,\r\n;           screen_address2 )\r\n\r\n_eagle:\r\n\r\n    pushad\r\n\r\n    ; test for mmx\r\n    mov eax,1\r\n    cpuid\r\n    test edx, 0x00800000\r\n    jnz near _eagle_mmx\r\n\r\n    push ebp\r\n\r\n    mov ebp, esp\r\n\r\n    add ebp, 32\r\n\r\n      mov esi,[ebp+8]\r\n    mov ebx,[ebp+12]\r\n    mov ecx,[ebp+16]\r\n\r\n    mov edi, _eagle_buffer\r\n    mov eax, _eagle_buffer+2048\r\n    and edi, 0xFFFFFFE0\r\n    and eax, 0xFFFFFFE0\r\n\r\n    mov ebp, ebx\r\n\r\n    shr ecx,2\r\n\r\n    xor dx,dx\r\n\r\n.L0\r\n\r\n    push ecx\r\n\r\n    xchg eax,ecx\r\n\r\n    mov eax, [esi]\r\n    add esi,4\r\n\r\n    mov ebx,[ebp]\r\n    add ebp,4\r\n    push ebp\r\n\r\n\r\n    cmp eax,ebx\r\n    jne near .L999\r\n\r\n    rol eax, 8\r\n    cmp eax,ebx\r\n    jne .L998\r\n    jmp .L997\r\n\r\n.L998\r\n    ror eax,8\r\n    jmp .L999\r\n\r\n.L997\r\n    ror eax,8\r\n    cmp dl, dh\r\n    jne near .L999\r\n    cmp dl, al\r\n    jne near .L999\r\n\r\n    mov [edi],eax\r\n    mov [ecx],ebx\r\n    mov [edi+4],eax\r\n    mov [ecx+4],ebx\r\n    add edi,8\r\n    add ecx,8\r\n\r\n    pop eax\r\n    mov ebp,eax\r\n\r\n    pop eax\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    cmp ecx, 0\r\n    je near .L333\r\n\r\n    push ecx\r\n    xchg eax,ecx\r\n\r\n    mov eax, [esi]\r\n    add esi,4\r\n\r\n    cmp ebx, eax\r\n    jne .L888\r\n\r\n    mov ebx,[ebp]\r\n    add ebp,4\r\n\r\n    cmp ebx, eax\r\n    jne .L889\r\n\r\n    mov [edi],eax\r\n    mov [ecx],ebx\r\n    mov [edi+4],eax\r\n\r\n    pop eax\r\n\r\n    mov [ecx+4],ebx\r\n    add edi,8\r\n    add ecx,8\r\n\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    jnz near .L0\r\n\r\n    jmp .L333\r\n\r\n.L888\r\n    mov ebx,[ebp]\r\n    add ebp, 4\r\n.L889\r\n    push ebp\r\n.L999\r\n\r\n    cmp dh, bl\r\n    jne .L6001\r\n.L1001\r\n    cmp bl, al\r\n    jne .L3001\r\n.L2001\r\n    mov [edi],al\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L3001\r\n    cmp dh, dl\r\n    jne .L5001\r\n.L4001\r\n    mov [edi], dx\r\n    mov [ecx], dx\r\n    jmp .L11\r\n.L5001\r\n    mov [edi],dl\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L6001\r\n    cmp dl, al\r\n    jne .L12001\r\n.L7001\r\n    cmp dl, dh\r\n    jne .L9001\r\n.L8001\r\n    mov [edi], dx\r\n    mov [ecx], dx\r\n    jmp .L11\r\n.L9001\r\n    cmp al,bl\r\n    jne .L11001\r\n.L10001\r\n    mov [edi],dl\r\n    mov [ecx],bl\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L11001\r\n.L12001\r\n    mov [edi],dl\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n\r\n.L11\r\n    cmp bl, bh\r\n    jne .L6002\r\n.L1002\r\n    cmp bh, ah\r\n    jne .L3002\r\n.L2002\r\n    mov [edi+2],bx\r\n    mov [ecx+2],bx\r\n    jmp .L12\r\n.L3002\r\n    cmp bl, al\r\n    jne .L5002\r\n.L4002\r\n    mov [edi+2],bx\r\n    mov [ecx+2],bx\r\n    jmp .L12\r\n.L5002\r\n    mov [edi+2],ax\r\n    mov [ecx+2],bx\r\n    jmp .L12\r\n.L6002\r\n    cmp al, ah\r\n    jne .L12002\r\n.L7002\r\n    cmp al, bl\r\n    jne .L9002\r\n.L8002\r\n    mov [ecx+2],ax\r\n    mov [edi+2],ax\r\n    jmp .L12\r\n.L9002\r\n    cmp ah,bh\r\n    jne .L11002\r\n.L10002\r\n    mov [ecx+2],ax\r\n    mov [edi+2],ax\r\n    jmp .L12\r\n.L11002\r\n.L12002\r\n    mov [edi+2], ax\r\n    mov [ecx+2], bx\r\n\r\n.L12\r\n    ror ebx, 8\r\n    ror eax, 8\r\n\r\n    cmp bl, bh\r\n    jne .L6003\r\n.L1003\r\n    cmp bh, ah\r\n    jne .L3003\r\n.L2003\r\n    mov [edi+4],bx\r\n    mov [ecx+4],bx\r\n    jmp .L13\r\n.L3003\r\n    cmp bl, al\r\n    jne .L5003\r\n.L4003\r\n    mov [edi+4],bx\r\n    mov [ecx+4],bx\r\n    jmp .L13\r\n.L5003\r\n    mov [edi+4], ax\r\n    mov [ecx+4], bx\r\n    jmp .L13\r\n.L6003\r\n    cmp al, ah\r\n    jne .L12003\r\n.L7003\r\n    cmp al, bl\r\n    jne .L9003\r\n.L8003\r\n    mov [ecx+4], ax\r\n    mov [edi+4], ax\r\n    jmp .L13\r\n.L9003\r\n    cmp ah,bh\r\n    jne .L11003\r\n.L10003\r\n    mov [ecx+4], ax\r\n    mov [edi+4], ax\r\n    jmp .L13\r\n.L11003\r\n.L12003\r\n    mov [edi+4],ax\r\n    mov [ecx+4],bx\r\n.L13\r\n    ror ebx, 8\r\n    ror eax, 8\r\n\r\n    cmp bl, bh\r\n    jne .L6004\r\n.L1004\r\n    cmp bh, ah\r\n    jne .L3004\r\n.L2004\r\n    mov [edi+6], bx\r\n    mov [ecx+6], bx\r\n    jmp .L14\r\n.L3004\r\n    cmp bl, al\r\n    jne .L5004\r\n.L4004\r\n    mov [edi+6], bx\r\n    mov [ecx+6], bx\r\n    jmp .L14\r\n.L5004\r\n    mov [edi+6], ax\r\n    mov [ecx+6], bx\r\n    jmp .L14\r\n.L6004\r\n    cmp al, ah\r\n    jne .L12004\r\n.L7004\r\n    cmp al, bl\r\n    jne .L9004\r\n.L8004\r\n    mov [ecx+6], ax\r\n    mov [edi+6], ax\r\n    jmp .L14\r\n.L9004\r\n    cmp ah,bh\r\n    jne .L11004\r\n.L10004\r\n    mov [ecx+6], ax\r\n    mov [edi+6], ax\r\n    jmp .L14\r\n.L11004\r\n.L12004\r\n    mov [edi+6], ax\r\n    mov [ecx+6], bx\r\n\r\n.L14\r\n\r\n    add edi, 8\r\n\r\n    mov dl, ah\r\n\r\n    add ecx, 8\r\n\r\n    mov dh, bh\r\n\r\n    pop eax\r\n;   mov eax, ebp    Was this an unnoticed error ?\r\n    mov ebp, eax\r\n\r\n    pop eax\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    jnz near .L0\r\n\r\n.L333\r\n    mov esi, _eagle_buffer\r\n    mov ebx, _eagle_buffer+2048\r\n    and esi, 0xFFFFFFE0\r\n    and ebx, 0xFFFFFFE0\r\n\r\n    mov ecx,[esp+16+32]\r\n    mov edx,[esp+20+32]\r\n\r\n    mov ax, es\r\n    push ax\r\n    mov es, dx\r\n\r\n    mov edi,[esp+26+32]\r\n    mov eax,[esp+30+32]\r\n\r\n    cld\r\n\r\n    push ecx\r\n\r\n    rep\r\n    movsd\r\n\r\n    pop ecx\r\n\r\n    mov edi, eax\r\n    mov esi, ebx\r\n\r\n    rep\r\n    movsd\r\n\r\n    pop ax\r\n    mov es, ax\r\n\r\n    pop eax\r\n    mov ebp, eax\r\n\r\n    popad\r\n\r\n    ret\r\n\r\n\r\n_eagle_mmx:\r\n\r\n    push ebp\r\n\r\n\r\n      mov esi,[esp+8+32]\r\n    mov ebx,[esp+12+32]\r\n    mov ecx,[esp+16+32]\r\n    mov edi, _eagle_buffer\r\n    mov eax, _eagle_buffer+2048\r\n    and edi, 0xFFFFFFE0\r\n    and eax, 0xFFFFFFE0\r\n\r\n\r\n    mov ebp, ebx\r\n\r\n    shr ecx, 3              ; divide by eight because mmx registers are 8 bytes\r\n\r\n    xor dx,dx\r\n\r\n.L0\r\n    push ecx\r\n    xchg eax,ecx\r\n\r\n    movq mm0,[esi]\r\n    movq mm1,[ebp]\r\n    add esi,8\r\n    add ebp,8\r\n\r\n    movd eax, mm0\r\n    movd ebx, mm1\r\n\r\n    cmp dh, bl\r\n    jne .L6001\r\n.L1001\r\n    cmp bl, al\r\n    jne .L3001\r\n.L2001\r\n    mov [edi],al\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L3001\r\n    cmp dh, dl\r\n    jne .L5001\r\n.L4001\r\n    mov [edi],dx\r\n    mov [ecx],dx\r\n    jmp .L11\r\n.L5001\r\n    mov [edi],dl\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L6001\r\n    cmp dl, al\r\n    jne .L12001\r\n.L7001\r\n    cmp dl, dh\r\n    jne .L9001\r\n.L8001\r\n    mov [edi],dx\r\n    mov [ecx],dx\r\n    jmp .L11\r\n.L9001\r\n    cmp al,bl\r\n    jne .L11001\r\n.L10001\r\n    mov [edi],dl\r\n    mov [ecx],bl\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L11001\r\n.L12001\r\n    mov [edi],dl\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n.L11\r\n\r\n    movq mm4, mm1\r\n\r\n    movq mm2, mm0\r\n\r\n      pcmpeqd mm7, mm7      ; set mm7 to FFFFFFFFFFFFFFFF\r\n\r\n    pcmpeqb mm4, mm0        ; byte compare equal mm0 with mm1 and store in mm4\r\n\r\n    psllq mm2, 8        ; shift mm0 left one byte and store in mm2\r\n\r\n    movq mm3, mm0\r\n\r\n    movq mm5, mm4       ; store byte compare mm0 with mm1 in mm5\r\n\r\n    pcmpeqb mm2, mm0        ; byte compare mm0 with mm2 and store in mm2\r\n\r\n    psrlq mm3, 8        ; shift mm0 right one byte and store in mm3\r\n\r\n    pand mm2, mm5\r\n\r\n      movq mm6, mm1     ; and mm5 with mm1\r\n\r\n    movq mm5, mm2       ; not mm2 and store in mm5\r\n\r\n      pxor mm5, mm7\r\n\r\n      psllq mm6, 8\r\n\r\n    pand mm2, mm0       ; and mm0 with mm2\r\n\r\n      pand mm5, mm6\r\n\r\n    por mm2, mm5            ; mm2 now contains right-bottom of quad\r\n\r\n    pcmpeqb mm3, mm0        ; byte compare mm3 with mm0 and store in mm3\r\n\r\n    movq mm5, mm4       ; byte compare of mm0 with mm1 store in mm5\r\n\r\n    pand mm3, mm4\r\n\r\n    movq mm5, mm3       ; not mm3 store in mm5\r\n\r\n    movq mm6, mm1\r\n\r\n      pxor mm5, mm7\r\n\r\n    pand mm3, mm0\r\n\r\n      psrlq mm6, 8\r\n\r\n    pand mm5, mm6\r\n\r\n      psrlq mm2, 8\r\n\r\n    por mm3, mm5\r\n\r\n; now write the 16 bytes of the bottom line\r\n\r\n      movq mm4, mm2\r\n\r\n    movq mm6, mm2\r\n\r\n      punpcklbw mm4, mm3\r\n\r\n    punpckhbw mm6, mm3\r\n\r\n    movq [ecx+2],mm4\r\n\r\n    movq [ecx+10],mm6\r\n\r\n\r\n; start with top line\r\n\r\n    movq mm2, mm1\r\n    movq mm3, mm1\r\n    movq mm4, mm0\r\n\r\n      pcmpeqd mm7, mm7      ; set mm7 to FFFFFFFFFFFFFFFF\r\n\r\n    pcmpeqb mm4, mm1        ; byte compare equal mm0 with mm1 and store in mm4\r\n\r\n    psllq mm2, 8        ; shift mm0 left one byte and store in mm2\r\n\r\n    psrlq mm3, 8        ; shift mm0 right one byte and store in mm3\r\n\r\n    movq mm5, mm4       ; store byte compare mm0 with mm1 in mm5\r\n\r\n    pcmpeqb mm2, mm1        ; byte compare mm0 with mm2 and store in mm2\r\n\r\n    pand mm2, mm5\r\n\r\n    movq mm5, mm2       ; not mm2 and store in mm5\r\n      pxor mm5, mm7\r\n\r\n    pand mm2, mm1       ; and mm0 with mm2\r\n\r\n      movq mm6, mm0     ; and mm5 with mm1\r\n      psllq mm6, 8\r\n      pand mm5, mm6\r\n\r\n    por mm2, mm5            ; mm2 now contains right-bottom of quad\r\n\r\n\r\n    movq mm5, mm4       ; byte compare of mm0 with mm1 store in mm5\r\n\r\n    pcmpeqb mm3, mm1        ; byte compare mm3 with mm0 and store in mm3\r\n\r\n    pand mm3, mm5\r\n\r\n    movq mm5, mm3       ; not mm3 store in mm5\r\n      pxor mm5, mm7\r\n\r\n    pand mm3, mm1\r\n\r\n    movq mm6, mm0\r\n      psrlq mm6, 8\r\n    pand mm5, mm6\r\n\r\n    por mm3, mm5\r\n\r\n; now write the 16 bytes of the top line\r\n\r\n      psrlq mm2, 8\r\n\r\n      movq mm4, mm2\r\n\r\n      movq mm6, mm2\r\n\r\n      punpcklbw mm4, mm3\r\n\r\n      punpckhbw mm6, mm3\r\n\r\n    movq [edi+2],mm4\r\n      psrlq mm0, 56\r\n    movq [edi+10],mm6\r\n      psrlq mm1, 56\r\n\r\n      add ecx, 16\r\n      add edi, 16\r\n\r\n    movd edx, mm0\r\n    movd ebx, mm1\r\n    mov  dh, bl\r\n\r\n    pop eax\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    jnz near .L0\r\n\r\n.L333\r\n\r\n    mov esi, _eagle_buffer\r\n    mov ebx, _eagle_buffer+2048\r\n    and esi, 0xFFFFFFE0\r\n    and ebx, 0xFFFFFFE0\r\n\r\n    mov ecx,[esp+16+32]\r\n    mov edx,[esp+20+32]\r\n\r\n    mov ax, es\r\n    push ax\r\n    mov es, dx\r\n\r\n    mov edi,[esp+26+32]\r\n    mov eax,[esp+30+32]\r\n\r\n    shr ecx, 5\r\n\r\n    push ecx\r\n\r\n.first_loop:\r\n    movq mm0, [ esi ]\r\n    movq mm1, [ esi + 8 ]\r\n    movq mm2, [ esi + 16]\r\n    movq mm3, [ esi + 24]\r\n    movq mm4, [ esi + 32]\r\n    movq mm5, [ esi + 40]\r\n    movq mm6, [ esi + 48]\r\n    movq mm7, [ esi + 56]\r\n\r\n    movq [es:edi], mm0\r\n    movq [es:edi + 8], mm1\r\n    movq [es:edi + 16], mm2\r\n    movq [es:edi + 24], mm3\r\n    movq [es:edi + 32], mm4\r\n    movq [es:edi + 40], mm5\r\n    movq [es:edi + 48], mm6\r\n    movq [es:edi + 56], mm7\r\n\r\n    add edi, 64\r\n    add esi, 64\r\n\r\n    dec ecx\r\n    jnz .first_loop\r\n\r\n    pop ecx\r\n\r\n    mov edi, eax\r\n    mov esi, ebx\r\n\r\n.second_loop:\r\n\r\n    movq mm0, [ esi ]\r\n    movq mm1, [ esi + 8 ]\r\n    movq mm2, [ esi + 16]\r\n    movq mm3, [ esi + 24]\r\n    movq mm4, [ esi + 32]\r\n    movq mm5, [ esi + 40]\r\n    movq mm6, [ esi + 48]\r\n    movq mm7, [ esi + 56]\r\n\r\n    movq [es:edi], mm0\r\n    movq [es:edi + 8], mm1\r\n    movq [es:edi + 16], mm2\r\n    movq [es:edi + 24], mm3\r\n    movq [es:edi + 32], mm4\r\n    movq [es:edi + 40], mm5\r\n    movq [es:edi + 48], mm6\r\n    movq [es:edi + 56], mm7\r\n\r\n    add edi, 64\r\n    add esi, 64\r\n\r\n    dec ecx\r\n    jnz .second_loop\r\n\r\n    pop ax\r\n    mov es, ax\r\n\r\n    pop eax\r\n    mov ebp, eax\r\n\r\n    emms\r\n\r\n    popad\r\n\r\n    ret\r\n\r\n;\r\n; Eagle for 16bit color\r\n; Supported for MMX *only*\r\n;\r\n\r\n_eagle_mmx16:\r\n\r\n    pushad\r\n\r\n    push ebp\r\n\r\n      mov esi,[esp+8+32]\r\n    mov ebx,[esp+12+32]\r\n    mov ecx,[esp+16+32]\r\n    mov edi, _eagle_buffer\r\n    mov eax, _eagle_buffer+4096\r\n    and edi, 0xFFFFFFE0\r\n    and eax, 0xFFFFFFE0\r\n\r\n\r\n    mov ebp, ebx\r\n\r\n    shr ecx, 3              ; divide by 8 because mmx registers / 16 bit color\r\n\r\n    xor dx,dx\r\n\r\n.L0\r\n    push ecx\r\n    xchg eax,ecx\r\n\r\n    movq mm1,[ebp]\r\n    movq mm0,[esi]\r\n    add ebp,8\r\n    add esi,8\r\n\r\n    ; added for mmx16\r\n\r\n    push ebp\r\n    push ecx\r\n    mov ebp, ecx\r\n\r\n    mov word cx, [_dlx]\r\n\r\n    ; end of added\r\n\r\n    movd eax, mm0\r\n    movd ebx, mm1\r\n\r\n;   cmp dhx, bx\r\n    cmp dx, bx\r\n    jne .L6001\r\n.L1001\r\n    cmp bx, ax\r\n    jne .L3001\r\n.L2001\r\n    mov [edi],ax\r\n;   mov [ecx],dhx\r\n    mov [ebp],dx\r\n    mov [edi+2],ax\r\n    mov [ebp+2],bx\r\n    jmp .L11\r\n.L3001\r\n;   cmp dhx, dlx\r\n        cmp dx, cx\r\n    jne .L5001\r\n.L4001\r\n;   mov [edi],dx  ; mmmh\r\n;   mov [ecx],dx  ; mmmh\r\n;   mov [edi],dl\r\n;   mov [ecx],dl\r\n;   mov [edi+1],dh\r\n;   mov [ecx+1],dh\r\n      mov [edi],cx\r\n      mov [ebp],cx\r\n    mov [edi+2],dx\r\n    mov [ebp+2],dx\r\n\r\n    jmp .L11\r\n.L5001\r\n      mov [edi],cx\r\n;   mov [ecx],dhx\r\n    mov [ebp],dx\r\n    mov [edi+2],ax\r\n    mov [ebp+2],bx\r\n    jmp .L11\r\n.L6001\r\n;   cmp dlx, ax\r\n      cmp cx, ax\r\n    jne .L12001\r\n.L7001\r\n;   cmp dlx, dhx\r\n      cmp cx, dx\r\n    jne .L9001\r\n.L8001\r\n;   mov [edi],dx  ; mmmh\r\n;   mov [ecx],dx  ; mmmh\r\n;   mov [edi],dl\r\n;   mov [ecx],dl\r\n;   mov [edi+1],dh\r\n;   mov [ecx+1],dh\r\n;   mov [edi],dlx\r\n;   mov [ecx],dlx\r\n      mov [edi],cx\r\n      mov [ebp],cx\r\n;   mov [edi+2],dhx\r\n;   mov [ecx+2],dhx\r\n    mov [edi+2],dx\r\n    mov [ebp+2],dx\r\n\r\n    jmp .L11\r\n.L9001\r\n    cmp ax,bx\r\n    jne .L11001\r\n.L10001\r\n;   mov [edi],dlx\r\n      mov [edi],cx\r\n    mov [ebp],bx\r\n    mov [edi+2],ax\r\n    mov [ebp+2],bx\r\n    jmp .L11\r\n.L11001\r\n.L12001\r\n;   mov [edi],dlx\r\n;   mov [ecx],dhx\r\n      mov [edi],cx\r\n    mov [ebp],dx\r\n    mov [edi+2],ax\r\n    mov [ebp+2],bx\r\n\r\n.L11\r\n\r\n    movq mm4, mm1\r\n\r\n    movq mm2, mm0\r\n\r\n      pcmpeqd mm7, mm7      ; set mm7 to FFFFFFFFFFFFFFFF\r\n\r\n    ;pcmpeqb mm4, mm0       ; byte compare equal mm0 with mm1 and store in mm4\r\n    pcmpeqw mm4, mm0        ; word compare equal mm0 with mm1 and store in mm4\r\n\r\n    ;psllq mm2, 8       ; shift mm0 left one byte and store in mm2\r\n    psllq mm2, 16       ; shift mm0 left one word and store in mm2\r\n\r\n    movq mm3, mm0\r\n\r\n    movq mm5, mm4       ; store byte compare mm0 with mm1 in mm5\r\n\r\n    ;pcmpeqb mm2, mm0       ; byte compare mm0 with mm2 and store in mm2\r\n    pcmpeqw mm2, mm0        ; word compare mm0 with mm2 and store in mm2\r\n\r\n    ;psrlq mm3, 8       ; shift mm0 right one byte and store in mm3\r\n    psrlq mm3, 16       ; shift mm0 right one word and store in mm3\r\n\r\n    pand mm2, mm5\r\n\r\n      movq mm6, mm1     ; and mm5 with mm1\r\n\r\n    movq mm5, mm2       ; not mm2 and store in mm5\r\n\r\n      pxor mm5, mm7\r\n\r\n;      psllq mm6, 8\r\n      psllq mm6, 16\r\n\r\n    pand mm2, mm0       ; and mm0 with mm2\r\n\r\n      pand mm5, mm6\r\n\r\n    por mm2, mm5            ; mm2 now contains right-bottom of quad\r\n\r\n    ;pcmpeqb mm3, mm0       ; byte compare mm3 with mm0 and store in mm3\r\n    pcmpeqw mm3, mm0        ; word compare mm3 with mm0 and store in mm3\r\n\r\n    movq mm5, mm4       ; word compare of mm0 with mm1 store in mm5\r\n\r\n    pand mm3, mm4\r\n\r\n    movq mm5, mm3       ; not mm3 store in mm5\r\n\r\n    movq mm6, mm1\r\n\r\n      pxor mm5, mm7\r\n\r\n    pand mm3, mm0\r\n\r\n      ;psrlq mm6, 8\r\n      psrlq mm6, 16\r\n\r\n    pand mm5, mm6\r\n\r\n      ;psrlq mm2, 8\r\n      psrlq mm2, 16\r\n\r\n    por mm3, mm5\r\n\r\n; now write the 16 bytes of the bottom line\r\n\r\n      movq mm4, mm2\r\n\r\n    movq mm6, mm2\r\n\r\n;      punpcklbw mm4, mm3\r\n\r\n;   punpckhbw mm6, mm3\r\n\r\n        punpcklwd mm4, mm3\r\n\r\n        punpckhwd mm6, mm3\r\n\r\n;   movq [ecx+2],mm4\r\n    movq [ebp+4],mm4\r\n\r\n;   movq [ecx+10],mm6\r\n    movq [ebp+12],mm6\r\n\r\n\r\n; start with top line\r\n\r\n    movq mm2, mm1\r\n    movq mm3, mm1\r\n    movq mm4, mm0\r\n\r\n      pcmpeqd mm7, mm7      ; set mm7 to FFFFFFFFFFFFFFFF\r\n\r\n    ;pcmpeqb mm4, mm1       ; byte compare equal mm0 with mm1 and store in mm4\r\n    pcmpeqw mm4, mm1        ; word compare equal mm0 with mm1 and store in mm4\r\n\r\n    ;psllq mm2, 8       ; shift mm0 left one byte and store in mm2\r\n    psllq mm2, 16       ; shift mm0 left one word and store in mm2\r\n\r\n    ;psrlq mm3, 8       ; shift mm0 right one byte and store in mm3\r\n    psrlq mm3, 16       ; shift mm0 right one word and store in mm3\r\n\r\n    movq mm5, mm4       ; store byte compare mm0 with mm1 in mm5\r\n\r\n    ;pcmpeqb mm2, mm1       ; byte compare mm0 with mm2 and store in mm2\r\n    pcmpeqw mm2, mm1        ; word compare mm0 with mm2 and store in mm2\r\n\r\n    pand mm2, mm5\r\n\r\n    movq mm5, mm2       ; not mm2 and store in mm5\r\n      pxor mm5, mm7\r\n\r\n    pand mm2, mm1       ; and mm0 with mm2\r\n\r\n      movq mm6, mm0     ; and mm5 with mm1\r\n      ;psllq mm6, 8\r\n      psllq mm6, 16\r\n      pand mm5, mm6\r\n\r\n    por mm2, mm5            ; mm2 now contains right-bottom of quad\r\n\r\n\r\n    movq mm5, mm4       ; byte compare of mm0 with mm1 store in mm5\r\n\r\n    ;pcmpeqb mm3, mm1       ; byte compare mm3 with mm0 and store in mm3\r\n    pcmpeqw mm3, mm1        ; word compare mm3 with mm0 and store in mm3\r\n\r\n    pand mm3, mm5\r\n\r\n    movq mm5, mm3       ; not mm3 store in mm5\r\n      pxor mm5, mm7\r\n\r\n    pand mm3, mm1\r\n\r\n    movq mm6, mm0\r\n      ;psrlq mm6, 8\r\n      psrlq mm6, 16\r\n    pand mm5, mm6\r\n\r\n    por mm3, mm5\r\n\r\n; now write the 16 bytes of the top line\r\n\r\n      ;psrlq mm2, 8\r\n      psrlq mm2, 16\r\n\r\n      movq mm4, mm2\r\n\r\n      movq mm6, mm2\r\n\r\n;      punpcklbw mm4, mm3\r\n\r\n;      punpckhbw mm6, mm3\r\n\r\n      punpcklwd mm4, mm3\r\n\r\n      punpckhwd mm6, mm3\r\n\r\n;   movq [edi+2],mm4\r\n    movq [edi+4],mm4\r\n;      psrlq mm0, 56            ; 64-8 = 56\r\n      psrlq mm0, 48         ; 64-16 = 48\r\n;   movq [edi+10],mm6\r\n    movq [edi+12],mm6\r\n      ;psrlq mm1, 56\r\n      psrlq mm1, 48\r\n\r\n\r\n;\r\n; restore ebp and ecx\r\n;\r\n\r\n    pop ecx\r\n    pop ebp\r\n\r\n;\r\n; End of restore\r\n;\r\n\r\n      add edi, 16\r\n      add ecx, 16\r\n\r\n    movd edx, mm0\r\n    mov word [_dlx], dx\r\n    movd ebx, mm1\r\n    mov  dx, bx\r\n\r\n    pop eax\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    jnz near .L0\r\n\r\n.L333\r\n\r\n    mov esi, _eagle_buffer\r\n    mov ebx, _eagle_buffer+4096\r\n    and esi, 0xFFFFFFE0\r\n    and ebx, 0xFFFFFFE0\r\n\r\n    mov ecx,[esp+16+32]\r\n    mov edx,[esp+20+32]\r\n\r\n    mov ax, es\r\n    push ax\r\n    mov es, dx\r\n\r\n    mov edi,[esp+26+32]\r\n    mov eax,[esp+30+32]\r\n\r\n    ;shr ecx, 5\r\n    shr ecx, 4\r\n\r\n    push ecx\r\n\r\n.first_loop:\r\n    movq mm0, [ esi ]\r\n    movq mm1, [ esi + 8 ]\r\n    movq mm2, [ esi + 16]\r\n    movq mm3, [ esi + 24]\r\n    movq mm4, [ esi + 32]\r\n    movq mm5, [ esi + 40]\r\n    movq mm6, [ esi + 48]\r\n    movq mm7, [ esi + 56]\r\n\r\n    movq [es:edi], mm0\r\n    movq [es:edi + 8], mm1\r\n    movq [es:edi + 16], mm2\r\n    movq [es:edi + 24], mm3\r\n    movq [es:edi + 32], mm4\r\n    movq [es:edi + 40], mm5\r\n    movq [es:edi + 48], mm6\r\n    movq [es:edi + 56], mm7\r\n\r\n    add edi, 64\r\n    add esi, 64\r\n\r\n    dec ecx\r\n    jnz .first_loop\r\n\r\n    pop ecx\r\n\r\n    mov edi, eax\r\n    mov esi, ebx\r\n\r\n\r\n.second_loop:\r\n    movq mm0, [ esi ]\r\n    movq mm1, [ esi + 8 ]\r\n    movq mm2, [ esi + 16]\r\n    movq mm3, [ esi + 24]\r\n    movq mm4, [ esi + 32]\r\n    movq mm5, [ esi + 40]\r\n    movq mm6, [ esi + 48]\r\n    movq mm7, [ esi + 56]\r\n\r\n    movq [es:edi], mm0\r\n    movq [es:edi + 8], mm1\r\n    movq [es:edi + 16], mm2\r\n    movq [es:edi + 24], mm3\r\n    movq [es:edi + 32], mm4\r\n    movq [es:edi + 40], mm5\r\n    movq [es:edi + 48], mm6\r\n    movq [es:edi + 56], mm7\r\n\r\n    add edi, 64\r\n    add esi, 64\r\n\r\n    dec ecx\r\n    jz .continue_here\r\n    jmp .second_loop\r\n\r\n.continue_here\r\n    pop ax\r\n    mov es, ax\r\n\r\n    pop eax\r\n    mov ebp, eax\r\n\r\n    emms\r\n\r\n    popad\r\n\r\n    ret\r\n\r\n\r\n;\r\n;eagle_bmp   (  unsigned long *lb,\r\n;               unsigned long *lb2,\r\n;               int width,\r\n;           screen_address1,\r\n;           screen_address2 )\r\n\r\n\r\n_eagle_bmp:\r\n\r\n    push ebp\r\n\r\n    mov ebp, esp\r\n      mov esi,[ebp+8]\r\n    mov ebx,[ebp+12]\r\n    mov ecx,[ebp+16]\r\n\r\n    mov edi, _eagle_buffer\r\n    mov eax, _eagle_buffer+2048\r\n    and edi, 0xFFFFFFE0\r\n    and eax, 0xFFFFFFE0\r\n\r\n    mov ebp, ebx\r\n\r\n    shr ecx,2\r\n\r\n    xor dx,dx\r\n\r\n.L0\r\n\r\n    push ecx\r\n\r\n    xchg eax,ecx\r\n\r\n    mov eax, [esi]\r\n    add esi,4\r\n\r\n    mov ebx,[ebp]\r\n    add ebp,4\r\n    push ebp\r\n\r\n\r\n    cmp eax,ebx\r\n    jne near .L999\r\n\r\n    rol eax, 8\r\n    cmp eax,ebx\r\n    jne .L998\r\n    jmp .L997\r\n\r\n.L998\r\n    ror eax,8\r\n    jmp .L999\r\n\r\n.L997\r\n    ror eax,8\r\n    cmp dl, dh\r\n    jne near .L999\r\n    cmp dl, al\r\n    jne near .L999\r\n\r\n    mov [edi],eax\r\n    mov [ecx],ebx\r\n    mov [edi+4],eax\r\n    mov [ecx+4],ebx\r\n    add edi,8\r\n    add ecx,8\r\n\r\n    pop eax\r\n    mov ebp,eax\r\n\r\n    pop eax\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    cmp ecx, 0\r\n    je near .L333\r\n\r\n    push ecx\r\n    xchg eax,ecx\r\n\r\n    mov eax, [esi]\r\n    add esi,4\r\n\r\n    cmp ebx, eax\r\n    jne .L888\r\n\r\n    mov ebx,[ebp]\r\n    add ebp,4\r\n\r\n    cmp ebx, eax\r\n    jne .L889\r\n\r\n    mov [edi],eax\r\n    mov [ecx],ebx\r\n    mov [edi+4],eax\r\n\r\n    pop eax\r\n\r\n    mov [ecx+4],ebx\r\n    add edi,8\r\n    add ecx,8\r\n\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    jnz near .L0\r\n\r\n    jmp .L333\r\n\r\n.L888\r\n    mov ebx,[ebp]\r\n    add ebp, 4\r\n.L889\r\n    push ebp\r\n.L999\r\n\r\n    cmp dh, bl\r\n    jne .L6001\r\n.L1001\r\n    cmp bl, al\r\n    jne .L3001\r\n.L2001\r\n    mov [edi],al\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L3001\r\n    cmp dh, dl\r\n    jne .L5001\r\n.L4001\r\n    mov [edi], dx\r\n    mov [ecx], dx\r\n    jmp .L11\r\n.L5001\r\n    mov [edi],dl\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L6001\r\n    cmp dl, al\r\n    jne .L12001\r\n.L7001\r\n    cmp dl, dh\r\n    jne .L9001\r\n.L8001\r\n    mov [edi], dx\r\n    mov [ecx], dx\r\n    jmp .L11\r\n.L9001\r\n    cmp al,bl\r\n    jne .L11001\r\n.L10001\r\n    mov [edi],dl\r\n    mov [ecx],bl\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n    jmp .L11\r\n.L11001\r\n.L12001\r\n    mov [edi],dl\r\n    mov [ecx],dh\r\n    mov [edi+1],al\r\n    mov [ecx+1],bl\r\n\r\n.L11\r\n    cmp bl, bh\r\n    jne .L6002\r\n.L1002\r\n    cmp bh, ah\r\n    jne .L3002\r\n.L2002\r\n    mov [edi+2],bx\r\n    mov [ecx+2],bx\r\n    jmp .L12\r\n.L3002\r\n    cmp bl, al\r\n    jne .L5002\r\n.L4002\r\n    mov [edi+2],bx\r\n    mov [ecx+2],bx\r\n    jmp .L12\r\n.L5002\r\n    mov [edi+2],ax\r\n    mov [ecx+2],bx\r\n    jmp .L12\r\n.L6002\r\n    cmp al, ah\r\n    jne .L12002\r\n.L7002\r\n    cmp al, bl\r\n    jne .L9002\r\n.L8002\r\n    mov [ecx+2],ax\r\n    mov [edi+2],ax\r\n    jmp .L12\r\n.L9002\r\n    cmp ah,bh\r\n    jne .L11002\r\n.L10002\r\n    mov [ecx+2],ax\r\n    mov [edi+2],ax\r\n    jmp .L12\r\n.L11002\r\n.L12002\r\n    mov [edi+2], ax\r\n    mov [ecx+2], bx\r\n\r\n.L12\r\n    ror ebx, 8\r\n    ror eax, 8\r\n\r\n    cmp bl, bh\r\n    jne .L6003\r\n.L1003\r\n    cmp bh, ah\r\n    jne .L3003\r\n.L2003\r\n    mov [edi+4],bx\r\n    mov [ecx+4],bx\r\n    jmp .L13\r\n.L3003\r\n    cmp bl, al\r\n    jne .L5003\r\n.L4003\r\n    mov [edi+4],bx\r\n    mov [ecx+4],bx\r\n    jmp .L13\r\n.L5003\r\n    mov [edi+4], ax\r\n    mov [ecx+4], bx\r\n    jmp .L13\r\n.L6003\r\n    cmp al, ah\r\n    jne .L12003\r\n.L7003\r\n    cmp al, bl\r\n    jne .L9003\r\n.L8003\r\n    mov [ecx+4], ax\r\n    mov [edi+4], ax\r\n    jmp .L13\r\n.L9003\r\n    cmp ah,bh\r\n    jne .L11003\r\n.L10003\r\n    mov [ecx+4], ax\r\n    mov [edi+4], ax\r\n    jmp .L13\r\n.L11003\r\n.L12003\r\n    mov [edi+4],ax\r\n    mov [ecx+4],bx\r\n.L13\r\n    ror ebx, 8\r\n    ror eax, 8\r\n\r\n    cmp bl, bh\r\n    jne .L6004\r\n.L1004\r\n    cmp bh, ah\r\n    jne .L3004\r\n.L2004\r\n    mov [edi+6], bx\r\n    mov [ecx+6], bx\r\n    jmp .L14\r\n.L3004\r\n    cmp bl, al\r\n    jne .L5004\r\n.L4004\r\n    mov [edi+6], bx\r\n    mov [ecx+6], bx\r\n    jmp .L14\r\n.L5004\r\n    mov [edi+6], ax\r\n    mov [ecx+6], bx\r\n    jmp .L14\r\n.L6004\r\n    cmp al, ah\r\n    jne .L12004\r\n.L7004\r\n    cmp al, bl\r\n    jne .L9004\r\n.L8004\r\n    mov [ecx+6], ax\r\n    mov [edi+6], ax\r\n    jmp .L14\r\n.L9004\r\n    cmp ah,bh\r\n    jne .L11004\r\n.L10004\r\n    mov [ecx+6], ax\r\n    mov [edi+6], ax\r\n    jmp .L14\r\n.L11004\r\n.L12004\r\n    mov [edi+6], ax\r\n    mov [ecx+6], bx\r\n\r\n.L14\r\n\r\n    add edi, 8\r\n\r\n    mov dl, ah\r\n\r\n    add ecx, 8\r\n\r\n    mov dh, bh\r\n\r\n    pop eax\r\n;   mov eax, ebp    Was this an unnoticed error ?\r\n    mov ebp, eax\r\n\r\n    pop eax\r\n    xchg eax,ecx\r\n\r\n    dec ecx\r\n    jnz near .L0\r\n\r\n.L333\r\n    mov esi, _eagle_buffer\r\n    mov ebx, _eagle_buffer+2048\r\n    and esi, 0xFFFFFFE0\r\n    and ebx, 0xFFFFFFE0\r\n\r\n    mov ecx,[esp+16]\r\n;   mov edx,[esp+20]\r\n\r\n;   mov ax, es\r\n;   push ax\r\n;   mov es, dx\r\n\r\n    mov edi,[esp+20]\r\n    mov eax,[esp+24]\r\n\r\n    cld\r\n\r\n    push ecx\r\n\r\n    rep\r\n    movsd\r\n\r\n    pop ecx\r\n\r\n    mov edi, eax\r\n    mov esi, ebx\r\n\r\n    rep\r\n    movsd\r\n\r\n;   pop ax\r\n;   mov es, ax\r\n\r\n    pop eax\r\n    mov ebp, eax\r\n    ret\r\n\r\n    SECTION .bss\r\n_offset32       resb 32\r\n_eagle_buffer   resb 16384\r\n_tripline1      resb 8\r\n_tripline2      resb 8\r\n_tripline3      resb 8\r\n_dlx            resb 32\r\n\r\n%ifidn __OUTPUT_FORMAT__,elf\r\nsection .note.GNU-stack noalloc noexec nowrite progbits\r\n%endif\r\n"
  },
  {
    "path": "meka/srcs/eagle.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - eagle.h\n// Eagle Graphic Filter - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nextern void eagle       (unsigned long *lb,\n                         unsigned long *lb2,\n                         short width,\n                         int destination_segment,\n                         void *screen_address1,  // int\n                         void *screen_address2); // int\n\nextern void eagle_mmx16 (unsigned long *lb,\n                         unsigned long *lb2,\n                         short width,\n                         int destination_segment,\n                         void *screen_address1,\n                         void *screen_address2);\n\nextern void eagle_bmp   (unsigned long *lb,\n                         unsigned long *lb2,\n                         short width,\n                         int destination_segment,\n                         void *screen_address1,\n                         void *screen_address2);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/eeprom.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - eeprom.c\n// EEPROM Emulation (model 93c46) - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n// #define DEBUG_EEPROM\n#include \"eeprom.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_93c46  EEPROM_93c46;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    BMemory_93c46_Load(FILE *f)\n{\n  if (fread (EEPROM_93c46.Data, EEPROM_93C46_DATA_SIZE, 1, f) == 1)\n     Msg(MSGT_USER, Msg_Get(MSG_93c46_Loaded), EEPROM_93C46_DATA_SIZE);\n  else\n     Msg(MSGT_USER, \"%s\", Msg_Get(MSG_93c46_Load_Unable));\n}\n\nvoid    BMemory_93c46_Save(FILE *f)\n{\n  if (f && fwrite (EEPROM_93c46.Data, EEPROM_93C46_DATA_SIZE, 1, f) == 1)\n     Msg(MSGT_USER, Msg_Get(MSG_93c46_Wrote), EEPROM_93C46_DATA_SIZE);\n  else\n     Msg(MSGT_USER, Msg_Get(MSG_93c46_Write_Unable), EEPROM_93C46_DATA_SIZE);\n}\n\nvoid    BMemory_93c46_Load_State(FILE *f)\n{\n  fread (&EEPROM_93c46, sizeof (EEPROM_93c46), 1, f);\n}\n\nvoid    BMemory_93c46_Save_State(FILE *f)\n{\n  fwrite (&EEPROM_93c46, sizeof (EEPROM_93c46), 1, f);\n}\n\nvoid    BMemory_93c46_Get_Infos(void **data, int *len)\n{\n  (*data) = EEPROM_93c46.Data;\n  (*len)  = EEPROM_93C46_DATA_SIZE;\n}\n\n//-----------------------------------------------------------------------------\n\n// Write to 0xFFFC\nvoid    EEPROM_93c46_Control(byte v)\n{\n  if (v & 0x80)\n     {\n     #ifdef DEBUG_EEPROM\n        Msg(MSGT_DEBUG, Msg_Get(MSG_93c46_Reset));\n     #endif\n     EEPROM_93c46_Init (EEPROM_93C46_INIT_ALL);\n     return;\n     }\n  EEPROM_93c46.Enabled = (v & 0x08) ? TRUE : FALSE;\n  #ifdef DEBUG_EEPROM\n     Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: Enabled=%02X\", CPU_GetPC, v);\n  #endif\n}\n\n// Clear 93c46 EEPROM data\nvoid    EEPROM_93c46_Clear()\n{\n  memset (EEPROM_93c46.Data, 0xFF, EEPROM_93C46_DATA_SIZE);\n}\n\n// Initialize 93c46 EEPROM - do NOT clear its data!\nvoid    EEPROM_93c46_Init(int Init)\n{\n  if (Init == EEPROM_93C46_INIT_ALL)\n     {\n     EEPROM_93c46.Enabled = FALSE;\n     EEPROM_93c46.Lines = 0x00 | EEPROM_93C46_LINE_DATA_OUT;\n     EEPROM_93c46.Read_Only = TRUE;\n     }\n  EEPROM_93c46.Status = EEPROM_93C46_STATUS_START;\n  EEPROM_93c46.Opcode = 0x0000;\n  EEPROM_93c46.Position = 0;\n}\n\n// Write to 0x8000 when 93c46 EEPROM is enabled\nvoid    EEPROM_93c46_Set_Lines(byte lines)\n{\n  #ifdef DEBUG_EEPROM\n    {\n    char * lines_desc = \"0\";\n    switch (lines & 7)\n      {\n      case 1: lines_desc = \"DATA\";            break;\n      case 2: lines_desc = \"CLK\";             break;\n      case 3: lines_desc = \"DATA | CLK\";      break;\n      case 4: lines_desc = \"CS\";              break;\n      case 5: lines_desc = \"DATA | CS\";       break;\n      case 6: lines_desc = \"CLK | CS\";        break;\n      case 7: lines_desc = \"DATA | CLK | CS\"; break;\n      }\n    Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: Set Lines %s\", CPU_GetPC, lines_desc);\n    }\n  #endif\n\n  /* CS Line (Reset), 1->0 edge */\n  if (!(lines & EEPROM_93C46_LINE_CS))\n     {\n     if (EEPROM_93c46.Lines & EEPROM_93C46_LINE_CS)\n        {\n        EEPROM_93c46_Init (EEPROM_93C46_INIT_NORMAL);\n        }\n     EEPROM_93c46.Lines = (EEPROM_93c46.Lines & ~0x07) | (lines & 0x07)\n                        | EEPROM_93C46_LINE_DATA_OUT;\n     return;\n     }\n\n  /* Clock Line, 0->1 edge */\n  /* (This is the big part) */\n  if ((lines & EEPROM_93C46_LINE_CLOCK) && !(EEPROM_93c46.Lines & EEPROM_93C46_LINE_CLOCK))\n     {\n     byte   data = lines & EEPROM_93C46_LINE_DATA_IN;\n     EEPROM_93c46.Lines = (EEPROM_93c46.Lines & ~0x07) | (lines & 0x07);\n     switch (EEPROM_93c46.Status)\n       {\n       // Start Bit ------------------------------------------------------------\n       case EEPROM_93C46_STATUS_START:\n            if (data)\n               {\n               #ifdef DEBUG_EEPROM\n                  Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: START\", CPU_GetPC);\n               #endif\n               EEPROM_93c46.Status = EEPROM_93C46_STATUS_OPCODE;\n               EEPROM_93c46.Opcode = 0x0000;\n               EEPROM_93c46.Position = 0;\n               }\n            return;\n       // Opcode (2 Bits) + Address (6 Bits) Read ------------------------------\n       case EEPROM_93C46_STATUS_OPCODE:\n            EEPROM_93c46.Opcode = (EEPROM_93c46.Opcode << 1) | data;\n            if (++EEPROM_93c46.Position == 8)\n               {\n               #ifdef DEBUG_EEPROM\n                  char bitfield[9];\n                  StrWriteBitfield (EEPROM_93c46.Opcode, 8, bitfield);\n                  Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: OPCODE = %s\", CPU_GetPC, bitfield);\n               #endif\n               switch (EEPROM_93c46.Opcode & 0xC0)\n                 {\n                 case 0x00: // 00: EXTENDED ------------------------------------\n                      switch (EEPROM_93c46.Opcode & 0x30)\n                        {\n                        case 0x00: // 00: ERASE/WRITE DISABLE ------------------\n                             #ifdef DEBUG_EEPROM\n                                Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: E/W DISABLE\", CPU_GetPC);\n                             #endif\n                             EEPROM_93c46.Read_Only = TRUE;\n                             EEPROM_93c46.Status = EEPROM_93C46_STATUS_START;\n                             return;\n                        case 0x10: // 00: WRITE ALL ----------------------------\n                             #ifdef DEBUG_EEPROM\n                                Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: WRITE ALL\", CPU_GetPC);\n                             #endif\n                             EEPROM_93c46.Position = 0;\n                             EEPROM_93c46.Latch = 0x0000;\n                             EEPROM_93c46.Status = EEPROM_93C46_STATUS_WRITING;\n                             return;\n                        case 0x20: // 00: ERASE ALL ----------------------------\n                             if (EEPROM_93c46.Read_Only == FALSE)\n                                {\n                                #ifdef DEBUG_EEPROM\n                                   Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: ERASE ALL\", CPU_GetPC());\n                                #endif\n                                memset (EEPROM_93c46.Data, 0xFF, EEPROM_93C46_DATA_SIZE);\n                                }\n                             else\n                                {\n                                Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: ERASE ALL attempt, but E/W is Disabled!\", CPU_GetPC());\n                                }\n                             EEPROM_93c46.Lines |= EEPROM_93C46_LINE_DATA_OUT; // Ready\n                             EEPROM_93c46.Status = EEPROM_93C46_STATUS_START;\n                             return;\n                        case 0x30: // 00: ERASE/WRITE ENABLE -------------------\n                             #ifdef DEBUG_EEPROM\n                                Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: E/W ENABLE\", CPU_GetPC);\n                             #endif\n                             EEPROM_93c46.Read_Only = FALSE;\n                             EEPROM_93c46.Status = EEPROM_93C46_STATUS_START;\n                             return;\n                        }\n                      return;\n                 case 0x40: // 01: WRITE ---------------------------------------\n                      #ifdef DEBUG_EEPROM\n                         Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: WRITE %02X\", CPU_GetPC, EEPROM_93c46.Opcode & 0x3F);\n                      #endif\n                      EEPROM_93c46.Position = 0;\n                      EEPROM_93c46.Latch = 0x0000;\n                      EEPROM_93c46.Status = EEPROM_93C46_STATUS_WRITING;\n                      return;\n                 case 0x80: // 10: READ ----------------------------------------\n                      #ifdef DEBUG_EEPROM\n                         Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: READ %02X\", CPU_GetPC, EEPROM_93c46.Opcode & 0x3F);\n                      #endif\n                      EEPROM_93c46.Position = 0;\n                      //EEPROM_93c46.Latch = (EEPROM_93c46.Opcode & 0x3F); // Address\n                      EEPROM_93c46.Status = EEPROM_93C46_STATUS_READING;\n                      EEPROM_93c46.Lines &= ~EEPROM_93C46_LINE_DATA_OUT; // Dummy Zero\n                      return;\n                 case 0xC0: // 11: ERASE ---------------------------------------\n                      if (EEPROM_93c46.Read_Only == FALSE)\n                         {\n                         #ifdef DEBUG_EEPROM\n                            Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: ERASE %02X\", CPU_GetPC, EEPROM_93c46.Opcode & 0x3F);\n                         #endif\n                         EEPROM_93c46.Data[EEPROM_93c46.Opcode & 0x3F] = 0xFFFF;\n                         EEPROM_93c46.Lines |= EEPROM_93C46_LINE_DATA_OUT; // Ready\n                         EEPROM_93c46.Status = EEPROM_93C46_STATUS_START;\n                         }\n                      else\n                         {\n                         Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: ERASE attempt, but E/W is Disabled!\", CPU_GetPC());\n                         }\n                      return;\n                 }\n               }\n            return;\n       // Reading --------------------------------------------------------------\n       case EEPROM_93C46_STATUS_READING:\n            if (EEPROM_93c46.Data [EEPROM_93c46.Opcode & 0x3F] & (0x8000 >> EEPROM_93c46.Position))\n                 EEPROM_93c46.Lines |=  EEPROM_93C46_LINE_DATA_OUT; // Bit 1\n            else EEPROM_93c46.Lines &= ~EEPROM_93C46_LINE_DATA_OUT; // Bit 0\n            #ifdef DEBUG_EEPROM\n               Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: READ BIT %d = %02X\", CPU_GetPC, EEPROM_93c46.Position, EEPROM_93c46.Lines & EEPROM_93C46_LINE_DATA_OUT);\n            #endif\n            if (++EEPROM_93c46.Position == 16)\n               {\n               EEPROM_93c46.Position = 0;\n               EEPROM_93c46.Opcode = 0x80 | ((EEPROM_93c46.Opcode + 1) & 0x3F);\n               }\n            return;\n       // Writing --------------------------------------------------------------\n       case EEPROM_93C46_STATUS_WRITING:\n            EEPROM_93c46.Latch = (EEPROM_93c46.Latch << 1) | data;\n            if (++EEPROM_93c46.Position == 16)\n               {\n               if (EEPROM_93c46.Read_Only == FALSE)\n                  {\n                  if ((EEPROM_93c46.Opcode & 0x40) == 0x40)\n                     { // 01: WRITE -----------------------------------------------\n                     #ifdef DEBUG_EEPROM\n                        Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: WRITE %02X = %04X\", CPU_GetPC, EEPROM_93c46.Opcode & 0x3F, EEPROM_93c46.Latch);\n                     #endif\n                     EEPROM_93c46.Data [EEPROM_93c46.Opcode & 0x3F] = EEPROM_93c46.Latch;\n                     }\n                  else\n                     { // 00.01: WRITE ALL ----------------------------------------\n                     int i;\n                     #ifdef DEBUG_EEPROM\n                        Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: WRITE ALL = %04X\", CPU_GetPC, EEPROM_93c46.Latch);\n                     #endif\n                     for (i = 0; i < 64; i++)\n                         {\n                         EEPROM_93c46.Data [i] = EEPROM_93c46.Latch;\n                         }\n                     }\n                  }\n               else\n                  {\n                  Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: WRITE [ALL] attempt = %04X, but E/W is Disabled!\", CPU_GetPC(), EEPROM_93c46.Latch);\n                  }\n               EEPROM_93c46.Lines |= EEPROM_93C46_LINE_DATA_OUT; // Ready\n               EEPROM_93c46.Status = EEPROM_93C46_STATUS_START;\n               }\n            return;\n       }\n     Msg(MSGT_DEBUG, \"Error #8190, EEPROM 93c46, CLK raising edge: undefined status.\");\n     return;\n     }\n\n  /* Data Line */\n  EEPROM_93c46.Lines = (EEPROM_93c46.Lines & ~0x07) | (lines & 0x07);\n}\n\n/* Read from 0x8000 when 93c46 is enabled */\nbyte    EEPROM_93c46_Read()\n{\n  int   ret;\n\n  ret = (EEPROM_93c46.Lines & EEPROM_93C46_LINE_CS)\n      | ((EEPROM_93c46.Lines & EEPROM_93C46_LINE_DATA_OUT) >> EEPROM_93C46_LINE_DATA_OUT_POS)\n      | EEPROM_93C46_LINE_CLOCK;\n  #ifdef DEBUG_EEPROM\n     Msg(MSGT_DEBUG, \"At PC=%04X: 93c46: Read %d (Lines %d)\", CPU_GetPC, ret, EEPROM_93c46.Lines);\n  #endif\n  return (ret);\n}\n\n// For Nomo's World Series Baseball\nvoid    EEPROM_93c46_Direct_Write(int Addr, byte Data)\n{\n  EEPROM_93c46.Data[Addr] = Data;\n}\n\n// For Nomo's World Series Baseball\nbyte    EEPROM_93c46_Direct_Read(int Addr)\n{\n  return EEPROM_93c46.Data[Addr];\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/eeprom.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - eeprom.h\n// EEPROM Emulation (model 93c46) - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    BMemory_93c46_Load              (FILE *f);\nvoid    BMemory_93c46_Save              (FILE *f);\nvoid    BMemory_93c46_Load_State        (FILE *f);\nvoid    BMemory_93c46_Save_State        (FILE *f);\nvoid    BMemory_93c46_Get_Infos         (void **data, int *len);\n\n//-----------------------------------------------------------------------------\n\nvoid    EEPROM_93c46_Init               (int Init);\nvoid    EEPROM_93c46_Clear              ();\nvoid    EEPROM_93c46_Control            (byte v);\n\nvoid    EEPROM_93c46_Set_Lines          (byte lines);\nbyte    EEPROM_93c46_Read               ();\n\nvoid    EEPROM_93c46_Direct_Write       (int Addr, byte Data);\nbyte    EEPROM_93c46_Direct_Read        (int Addr);\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define EEPROM_93C46_LINE_DATA_IN       (0x01)\n#define EEPROM_93C46_LINE_CLOCK         (0x02)\n#define EEPROM_93C46_LINE_CS            (0x04)\n#define EEPROM_93C46_LINE_DATA_OUT      (0x08)\n#define EEPROM_93C46_LINE_DATA_OUT_POS  (3)\n\n#define EEPROM_93C46_INIT_NORMAL        (0)\n#define EEPROM_93C46_INIT_ALL           (1)\n\n#define EEPROM_93C46_DATA_SIZE          (128) /* (64 * sizeof (word)) */\n\n#define EEPROM_93C46_STATUS_START       (0) // Waiting for Start Bit\n#define EEPROM_93C46_STATUS_OPCODE      (1) // Reading Opcode + Address\n#define EEPROM_93C46_STATUS_READING     (2) // Clocking out data to output\n#define EEPROM_93C46_STATUS_WRITING     (3) // Clocking in data to write\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_93c46\n{\n  byte          Enabled;\n  byte          Lines;\n  byte          Status;\n  byte          Read_Only;\n  byte          Position;\n  word          Opcode;\n  word          Latch;\n  word          Data [EEPROM_93C46_DATA_SIZE/2]; // Data must be at end of structure\n};\n\nextern t_93c46  EEPROM_93c46;\n\n// Legacy structure (for loading old MEKA savestates) -------------------------\n\n/*\nstruct t_93c46_LEGACY\n{\n  byte          Action;\n  byte          Enabled;\n  byte          Wait;\n  byte          Pos;\n  byte          Opcode;\n  byte          Address;\n  byte          Dummy_Zero;\n  word          Data_Temp;\n  word          Data [64]; // _DATA_SIZE / sizeof(_DATA_TYPE)\n  byte          EW_Enable;\n  byte          Return_Read;\n};\n*/\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/effects.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - effects.c\n// Various effects - Code\n//-----------------------------------------------------------------------------\n// FIXME: merge with specials.* ?\n// FIXME: This is super old code. Everything is nonsense from beginning to end. \n// I cannot read that anymore! Argh.\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"palette.h\"\n#include \"effects.h\"\n#include \"video.h\"\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define TV_EFFECT_COLORS_MAX                (12)    // FIXME: Changing this will break the code below!\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_tv_effect\n{\n    int     start_line;\n    u16     colors[TV_EFFECT_COLORS_MAX];\n};\n\nstatic t_tv_effect  tv_effect;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Effects_TV_Init()\n{\n    tv_effect.start_line = SMS_RES_Y / 2;\n}\n\nvoid    Effects_TV_Reset()\n{\n    tv_effect.start_line = SMS_RES_Y / 2;\n}\n\nvoid    Effects_TV_Update()\n{\n    // Update color palette\n    for (int i = 0; i != TV_EFFECT_COLORS_MAX; i++)\n        tv_effect.colors[i] = Palette_MakeHostColor(g_screenbuffer_format, i * 16, i * 16, i * 16);\n\n    const int rx = g_driver->x_res;\n    const int ry = g_driver->y_res;\n    const int rx_d2 = rx / 2;\n    const int ry_d2 = ry / 2;\n\n    assert(Screenbuffer_IsLocked());\n    u16* screen_data = (u16*)g_screenbuffer_locked_region->data;\n    const int screen_pitch16 = g_screenbuffer_locked_region->pitch / sizeof(u16);\n\n    const int start_offset = (g_driver->y_show_start * screen_pitch16) + g_driver->x_start;\n\n    int i, j, k;\n\n    // Fill with random pixels\n    // Same data in the four quarters (to reduce number of calls to Random().. this was somewhat an issue back on old 486).\n    for (j = 0; j != ry_d2; j ++)\n    {\n        u16* p1 = (u16 *)(screen_data + j*screen_pitch16 + start_offset);\n        u16* p2 = (u16 *)(screen_data + (j+ry_d2)*screen_pitch16 + start_offset);\n        u16* p3 = p1 + rx_d2;\n        u16* p4 = p2 + rx_d2;\n        for (i = 0; i != rx_d2; i ++)\n        {\n            const u16 color = tv_effect.colors[RandomInt(TV_EFFECT_COLORS_MAX)];\n            *p1++ = *p2++ = *p3++ = *p4++ = color;\n        }\n    }\n\n    // Random lines\n    for (i = 0; i < 25; i ++)\n    {\n        int len;\n        const u16 color = tv_effect.colors[RandomInt(TV_EFFECT_COLORS_MAX)];\n        j = RandomInt(rx); // x\n        k = RandomInt(ry); // y\n        len = RandomInt(30); // len\n        j -= len;\n        if (j < 0) \n            j = 0;\n        u16* p1 = (u16 *)(screen_data + k*screen_pitch16 + j + start_offset);\n        while (len-- != 0)\n            *p1++ = color;\n    }\n\n    j = RandomInt(ry);\n    k = RandomInt(16) + (rx - 16);\n    i = RandomInt(16);\n    u16* p1 = (u16 *)(screen_data + j*screen_pitch16 + i + start_offset);\n    for (; i < k; i ++)\n    {\n        int r = RandomInt(16);\n        if (r != 0)\n            *p1 = tv_effect.colors[r % 3];\n        p1 ++;\n    }\n\n    if (tv_effect.start_line > 0)\n    {\n        for (j = 0; j != tv_effect.start_line; j++)\n        {\n            u16* p1 = (u16 *)(screen_data + j*screen_pitch16 + start_offset);\n            for (i = 0; i != rx; i++)\n            {\n                if (RandomInt(tv_effect.start_line) != 0)\n                {\n                    *p1 = tv_effect.colors[0];\n                }\n                p1 ++;\n            }\n        }\n        for (j = ry - 1; j > (ry - tv_effect.start_line); j --)\n        {\n            u16* p1 = (u16 *)(screen_data + j*screen_pitch16 + start_offset);\n            for (i = 0; i < rx; i ++)\n            {\n                if (RandomInt(tv_effect.start_line) != 0)\n                {\n                    *p1 = tv_effect.colors[0];\n                }\n                p1 ++;\n            }\n        }\n        tv_effect.start_line -= 24;\n    }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/effects.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - effects.h\n// Various effects - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Effects_TV_Init();\nvoid    Effects_TV_Reset();\nvoid    Effects_TV_Update();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/errors.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - errors.c\r\n// Error codes and handling\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nint meka_errno = MEKA_ERR_OK;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// FIXME: switch that to a table with the #define inside\r\nconst char *  meka_strerror()\r\n{\r\n    switch (meka_errno)\r\n    {\r\n    case MEKA_ERR_MEMORY:            return (Msg_Get(MSG_Error_Memory));\r\n    case MEKA_ERR_FILE_OPEN:         return (Msg_Get(MSG_Error_File_Not_Found));\r\n    case MEKA_ERR_FILE_READ:         return (Msg_Get(MSG_Error_File_Read));\r\n    case MEKA_ERR_FILE_EMPTY:        return (Msg_Get(MSG_Error_File_Empty));\r\n    case MEKA_ERR_ZIP_NOT_SUPPORTED: return (Msg_Get(MSG_Error_ZIP_Not_Supported));\r\n    case MEKA_ERR_ZIP_LOADING:       return (Msg_Get(MSG_Error_ZIP_Loading));\r\n    case MEKA_ERR_ZIP_INTERNAL:      return (Msg_Get(MSG_Error_ZIP_Internal));\r\n    }\r\n    return (Msg_Get(MSG_Error_Error));\r\n}\r\n\r\n#ifdef ARCH_WIN32\r\nstatic LPVOID   GetWindowsErrorMessage()\r\n{\r\n    LPVOID lpMsgBuf;\r\n\r\n    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\r\n        NULL,\r\n        GetLastError(),\r\n        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r\n        (LPTSTR) &lpMsgBuf,\r\n        0,\r\n        NULL);\r\n    return (lpMsgBuf);\r\n}\r\n\r\nvoid            ShowWindowsErrorMessage()\r\n{\r\n    LPVOID lpMsgBuf;\r\n\r\n    lpMsgBuf = GetWindowsErrorMessage();\r\n    MessageBox(NULL, (LPCTSTR)lpMsgBuf, \"Error\", MB_OK | MB_ICONINFORMATION);\r\n    LocalFree(lpMsgBuf);\r\n}\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/errors.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - errors.h\r\n// Error codes and handling\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Error Codes ----------------------------------------------------------------\r\n#define MEKA_ERR_OTHER                 (-1)\r\n#define MEKA_ERR_OK                     (0)\r\n#define MEKA_ERR_FAIL                   (1)\r\n#define MEKA_ERR_MEMORY                 (2)\r\n#define MEKA_ERR_SYNTAX                 (3)\r\n#define MEKA_ERR_EMPTY                  (4)\r\n#define MEKA_ERR_INCOHERENT             (5)\r\n#define MEKA_ERR_FILE_OPEN              (6)\r\n#define MEKA_ERR_FILE_READ              (7)\r\n#define MEKA_ERR_FILE_WRITE             (8)\r\n#define MEKA_ERR_FILE_CLOSE             (9)\r\n#define MEKA_ERR_FILE_EMPTY             (10)\r\n#define MEKA_ERR_MISSING                (11)\r\n#define MEKA_ERR_UNKNOWN                (12)\r\n#define MEKA_ERR_INCOMPLETE             (13)\r\n#define MEKA_ERR_ZIP_NOT_SUPPORTED      (14)\r\n#define MEKA_ERR_ZIP_LOADING            (15)\r\n#define MEKA_ERR_ZIP_INTERNAL           (16)\r\n#define MEKA_ERR_CONSOLE_WIN32_INIT     (17)\r\n#define MEKA_ERR_CANCEL                 (18)\r\n#define MEKA_ERR_ALREADY_DEFINED        (19)\r\n#define MEKA_ERR_VALUE_OUT_OF_BOUND     (20)\r\n#define MEKA_ERR_VALUE_INCORRECT        (21)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nextern int      meka_errno;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nconst char *    meka_strerror();\r\n\r\n#ifdef ARCH_WIN32\r\nvoid            ShowWindowsErrorMessage();\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/fdc765.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - fdc765.c\n// FDC765 (Floppy Disk Drive) Emulator - Code\n//-----------------------------------------------------------------------------\n// Ulrich Cordes\n// Modifications for SF-7000 by Marc Le Douarain, Omar Cornut, Thomas Bernard\n//-----------------------------------------------------------------------------\n\n// Original file header:\n\n/***************************************/\n/**                                   **/\n/** AMSTRAD/Schneider CPC-Emulator    **/\n/** for Linux and X11                 **/\n/**                                   **/\n/** (c) 1999,                         **/\n/** Ulrich Cordes                     **/\n/** Bergstrasse 8                     **/\n/** 34292 AHNATAL / Germany           **/\n/**                                   **/\n/** email:  ulrich.cordes@gmx.de      **/\n/** WWW:    http://www.amstrad-cpc.de **/\n/**                                   **/\n/***************************************/\n\n// Modified for SEGA SF-7000\n// by Marc 'Mavati' Le Douarain\n// in November 2000\n\n// Generally cleaned/modified/translated/fixed for MEKA\n// by Omar 'Bock' Cornut\n// in November 2000\n\n// Support added for DSK standard and extended format\n// by Thomas 'Nanard' Bernard\n// in November 2022\n\n// Note from the original author:\n// If you want to make changes, please do not(!) use TABs !!!!!\n// (obviously abused by Omar, anyway it was a big source cleaning that I made)\n\n#include \"shared.h\"\n#include \"fdc765.h\"\n\n#ifndef ARRAYSIZE\n#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))\n#endif\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nFDC765_Disk dsk[FDC765_MAXDRIVES];\nu8      FDC765_Cmd_For_SF7000;\n\n//-----------------------------------------------------------------------------\n\nbyte    FloppyMotor;                    // True= Motor ON, False= Motor OFF\nbyte    FDCCurrDrv;                     // Current drive\nbyte    FDCWrProtect[FDC765_MAXDRIVES]; // Write protection, not used so far\nbyte    FDCCurrTrack[FDC765_MAXDRIVES]; // Current track of each drive\nbyte    FDCCurrSide[FDC765_MAXDRIVES];  // Current side of each drive\nbyte    ExecCmdPhase;                   // TRUE=Kommandophase findet gerade statt\nbyte    ResultPhase;                    // TRUE=Result-Phase findet gerade statt\nbyte    StatusRegister;                 // Status Register\nword    StatusCounter;\nbyte    st0, st1, st2, st3;\n\nbyte    FDCCommand [9];            /* Feld fr Kommandos  */\nbyte    FDCResult [7];             /* Feld fr Ergebnisse */\n\nword    FDCPointer;                /* Zeiger auf die akt. Variable im Komando-Feld (beim bertragen) */\nword    FDCCmdPointer;             /* Zeiger auf das aktuell zu bertragende Zeichen (READ/WRITE)    */\nword    FDCResPointer;             /* Zeiger auf das akt. Result                                     */\nword    FDCResCounter;             /* Anzahl der Results, die Zurckgegeben werden                   */\nunsigned long FDCDataPointer;      /* Sektor-Zeiger (Zhler) */\nunsigned long FDCDataLength;       /* Anzahl der zu lesenden Daten */\nword    TrackIndex;                /* Index auf dsk[].Tracks[....] */\nunsigned long TrackDataStart;      /* Startposition der Daten des akt. Sektors im Track */\n\nconst byte bytes_in_cmd[32] =\n{\n  1,  /*  0 = none                                */\n  1,  /*  1 = none                                */\n  9,  /*  2 = READ TRACK, not implemented         */\n  3,  /*  3 = SPECIFY                             */\n  2,  /*  4 = SENSE DRIVE STATUS                  */\n  9,  /*  5 = WRITE DATA                          */\n  9,  /*  6 = READ DATA                           */\n  2,  /*  7 = RECALIBRATE                         */\n  1,  /*  8 = SENSE INTERRUPT STATUS              */\n  9,  /*  9 = WRITE DELETED DATA, not implemented */\n  2,  /* 10 = READ SECTOR ID                      */\n  1,  /* 11 = none                                */\n  9,  /* 12 = READ DELETED DATA, not implemented  */\n  6,  /* 13 = FORMAT A TRACK                      */\n  1,  /* 14 = none                                */\n  3,  /* 15 = SEEK                                */\n  1,  /* 16 = none                                */\n  9,  /* 17 = SCAN EQUAL                          */\n  1,  /* 18 = none                                */\n  1,  /* 19 = none                                */\n  1,  /* 20 = none                                */\n  1,  /* 21 = none                                */\n  1,  /* 22 = none                                */\n  1,  /* 23 = none                                */\n  1,  /* 24 = none                                */\n  9,  /* 25 = SCAN LOW OR EQUAL                   */\n  1,  /* 26 = none                                */\n  1,  /* 27 = none                                */\n  1,  /* 28 = none                                */\n  1,  /* 29 = none                                */\n  9,  /* 30 = SCAN HIGH OR EQUAL                  */\n  1   /* 31 = none                                */\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    GetRes7()                       /* Return 7 result bytes */\n{\n  FDCResult[0] = st0;\n  FDCResult[1] = st1;\n  FDCResult[2] = st2;\n  FDCResult[3] = FDCCommand[2];         /* C, H, R, N */\n  FDCResult[4] = FDCCommand[3];\n  FDCResult[5] = FDCCommand[4];\n  FDCResult[6] = FDCCommand[5];\n  StatusRegister = 0xD0;                /* Ready to return results */\n  StatusCounter = 100;\n  FDCResPointer = 0;\n  FDCResCounter = 7;\n  st0 = st1 = st2 = 0;\n  ExecCmdPhase = FALSE;\n  ResultPhase = TRUE;\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    FDCExecWriteCommand (register byte Value)\n{\n    // FIXME: Failed attempt at detecting writes from non IPL code\n    // However even e.g. Burglar Bill fills buffer + call lowest-level IPL function\n    /*\n    if (IPL_Disabled || sms.R.PC.W >= 0x4000)\n        Msg(MSGT_USER_LOG, \"FDC765: Command %d from code that isn't in IPL: %04X\", FDCCommand[0], sms.R.PC.W);\n    */\n\n  switch (FDCCommand [0])\n    {\n    case 2:             /* Read track */\n      FDCCurrDrv = FDCCommand[1] & 3;\n      FDCCurrSide[FDCCurrDrv] = (FDCCommand[1] >> 2) & 1;\n      FDCCurrTrack[FDCCurrDrv] = FDCCommand[2];\n      if (dsk[FDCCurrDrv].HasDisk == FALSE)\n        {\n        st0 = FDCCurrDrv | 0xD8;  /* Equipment check, Not ready */\n        GetRes7();\n        }\n      else\n        {\n        FDCCurrSide[FDCCurrDrv] = (FDCCommand[1] >> 2) & 1;\n        FDCCurrTrack[FDCCurrDrv] = FDCCommand[2];\n        ExecCmdPhase = TRUE;\n        TrackIndex = FDCCurrTrack[FDCCurrDrv] * dsk[FDCCurrDrv].Header.nbof_heads + FDCCurrSide[FDCCurrDrv];\n        TrackDataStart = ((FDCCommand[4] & 0x0F)-1) << 9;\n//        FDCDataLength = (dsk[FDCCurrDrv].Tracks[TrackIndex].BPS * dsk[FDCCurrDrv].Tracks[TrackIndex].SPT) << 9;\n        FDCDataLength = (FDC765_BPS * FDC765_SPT) << 9;\n        FDCDataPointer = 0;\n        StatusCounter = 100;\n        StatusRegister = 0xF0;     /* RQM=1, DIO=FDC->CPU, EXM=1, CB=1 */\n        }\n      break;\n\n    case 3:             /* Specify */\n      break;\n\n    case 4:             /* Sense drive status */\n      FDCCurrDrv = FDCCommand[1] & 3;\n      st3 = FDCCommand[1] & 7;\n      if (FDCWrProtect[FDCCurrDrv]) st3 |= 0x40;\n      if (dsk[FDCCurrDrv].HasDisk) st3 |= 0x20;\n      if (FDCCurrTrack[FDCCurrDrv] == 0) st3 |= 0x10;\n      if (st3 & 4) st3 |= 8; /* Two side drive */\n      FDCResCounter = 1;       /* Ein Result-Byte, das zurck gegeben wird */\n      FDCResPointer = 0;\n      FDCResult[0] = st3;\n      ExecCmdPhase = FALSE;\n      ResultPhase = TRUE;\n      StatusCounter = 100;\n      StatusRegister = 0xD0;        /* Ready to return results */\n      break;\n\n    case 5:              /* Write data */\n      if (!ExecCmdPhase)\n        {\n        FDCCurrDrv = FDCCommand[1] & 3;\n        FDCCurrSide[FDCCurrDrv] = (FDCCommand[1] >> 2) & 1;\n        FDCCurrTrack[FDCCurrDrv] = FDCCommand[2];\n        ExecCmdPhase = TRUE;\n        if (dsk[FDCCurrDrv].HasDisk == FALSE)\n          {\n          st0 = FDCCurrDrv | 0xD8;  /* Equipment check, Not ready */\n          GetRes7();\n          }\n        else\n          {\n          TrackIndex = FDCCurrTrack[FDCCurrDrv] * dsk[FDCCurrDrv].Header.nbof_heads + FDCCurrSide[FDCCurrDrv];\n          TrackDataStart = ((FDCCommand[4] & 0x0F)-1) << 9;\n          FDCDataLength = 512 + ((FDCCommand[4] - FDCCommand[6]) << 9);\n          FDCDataPointer = 0;\n          StatusCounter = 100;\n          StatusRegister = 0xB0;     /* RQM=1, DIO=CPU->FDC, EXM=1, CB=1 */\n          }\n        }\n      else\n        {\n        dsk[FDCCurrDrv].Tracks[TrackIndex].DiscData[TrackDataStart + FDCDataPointer] = Value;\n        FDCDataPointer ++;\n        if (FDCDataPointer == FDCDataLength)\n          {\n          st0 = FDCCommand[1] & 7;\n          GetRes7();\n          }\n        }\n      break;\n\n    case 6:                      /* Read data */\n      // Note FDC765 supports reading several sectors in a row, but\n      // it is currently not supported.\n      // In theory LS should be Last Sector we are only getting values of 0x10\n      // as the SF-7000 IPL always sets 0x10 in it.\n      FDCCurrDrv = FDCCommand[1] & 3;\n\n      //Msg(MSGT_USER_LOG, \"FDC765: Cmd 6: HU=%02X TR=%02X HD=%02X SC=%02X SZ=%02X LS=%02X GP=%02X SL=%02X\",\n      //    FDCCommand[1], FDCCommand[2], FDCCommand[3], FDCCommand[4], FDCCommand[5], FDCCommand[6], FDCCommand[7], FDCCommand[8]);\n\n      if (FDCCurrDrv >= ARRAYSIZE(dsk))\n      {\n          Msg(MSGT_USER_LOG, \"FDC765: Cmd 6: Selected unsupported drive: %d\", (int)FDCCurrDrv);\n          FDCCurrDrv = 0;\n      }\n\n      FDCCurrSide[FDCCurrDrv] = (FDCCommand[1] >> 2) & 1;\n      //FDCCurrTrack[FDCCurrDrv] = FDCCommand[2]; // Physical track should not be read from Read command\n      // It is set using Recalibrate (7) and Seek (15) Commands\n      if (dsk[FDCCurrDrv].HasDisk == FALSE)\n        {\n        st0 = FDCCurrDrv | 0xD8;  /* Equipment check, Not ready */\n        GetRes7();\n        }\n      else\n        {\n        ExecCmdPhase = TRUE;\n        TrackIndex = FDCCurrTrack[FDCCurrDrv] * dsk[FDCCurrDrv].Header.nbof_heads + FDCCurrSide[FDCCurrDrv];\n//        TrackDataStart = ((FDCCommand[4] & 0x0F)-1) << 9;\n//        FDCDataLength = 512 + (((FDCCommand[4] & 0xF) - (FDCCommand[6] & 0xF))<<9);\n        if (dsk[FDCCurrDrv].ImageType == DSK_FORMAT_RAW)\n          {\n          TrackDataStart = ((FDCCommand[4] & 0x1F)-1) << 8;\n          FDCDataLength = TrackDataStart+256;// + (((FDCCommand[4] & 0xF) - (FDCCommand[6] & 0xF))<<8);\n          }\n        else\n          {\n          unsigned long offset;\n          if (dsk[FDCCurrDrv].ImageType == DSK_FORMAT_STANDARD_DSK)\n            offset = FDCCurrTrack[FDCCurrDrv] * dsk[FDCCurrDrv].Header.tracksize;\n          else\n            {\n            byte t;\n            // FDCCommand[2] should equals FDCCurrTrack[FDCCurrDrv]\n            for (t = 0, offset = 0; t < FDCCurrTrack[FDCCurrDrv]; t++)\n              {\n              offset += dsk[FDCCurrDrv].Header.tracksizetable[t] << 8;\n              }\n            // offset = track offset\n            if (dsk[FDCCurrDrv].Header.tracksizetable[t] == 0)\n              {\n              // Empty track\n                Msg(MSGT_USER_LOG, \"FDC765: Cmd 6: Track %d is empty\", (int)t);\n              }\n          }\n          byte s;\n          byte sector_count = dsk[FDCCurrDrv].Tracks[0].DiscData[offset + 0x15];\n          const byte * sp = dsk[FDCCurrDrv].Tracks[0].DiscData + offset + 0x18;\n          offset += 256;\n          for (s = 0; s < sector_count; s++, sp += 8)\n            {\n            word stored_length = sp[6] + (sp[7] << 8);\n            if (stored_length == 0)\n              stored_length = 0x80 << sp[3];\n            if (FDCCommand[2] == sp[0] && FDCCommand[3] == sp[1] && FDCCommand[4] == sp[2])\n              {\n              // right sector found\n              TrackDataStart = offset;\n              FDCDataLength = TrackDataStart + (0x80 << sp[4]);\n              break;\n              }\n            offset += stored_length;\n            }\n          }\n        FDCDataPointer = 0;\n        StatusCounter = 100;\n        StatusRegister = 0xF0; /* RQM=1, DIO=FDC->CPU, EXM=1, CB=1 */\n        }\n      break;\n\n   case 7:                     /* Recalibrate (Track 0 Lookup) */\n      st0 = st1 = st2 = 0;\n      FDCCurrDrv = FDCCommand[1] & 3;\n      st0 = FDCCommand[1] & 7;\n      if (dsk[FDCCurrDrv].HasDisk == FALSE)\n        {\n        st0 |= 0xD8;  /* Equipment check, Not ready */\n        }\n      else\n        {\n        if (FDCCurrTrack[FDCCurrDrv] > 77)\n          {\n          FDCCurrTrack[FDCCurrDrv] -= 77;\n          st0 |= 0x30;\n          }\n        else\n          {\n          FDCCurrTrack[FDCCurrDrv] = 0;\n          st0 |= 0x20;\n          }\n        }\n      StatusCounter = 100;\n      StatusRegister = 0x80 | (1 << (FDCCommand[1] & 3)); /* RQM=1, DIO=CPU->FDC, EXM = 0 */\n      ExecCmdPhase = FALSE;\n      break;\n\n    case 8:                    /* Sense Interrupt */\n      StatusRegister = 0xD0;   /* RQM=1, DIO=FDC->CPU, EXM = 0, CB=1, DB0-DB3 = 0 */\n      FDCResCounter = 2;       /* Two Result-Bytes, die zurck gegeben werden */\n      FDCResPointer = 0;\n      //st0 = FDCCurrDrv | (FDCCurrSide[FDCCurrDrv]<<2);\n      if (dsk[FDCCurrDrv].HasDisk == FALSE)\n         st0 |= 0x08;                  /* Drive not ready */\n      if (!(st0 & 0x38)) st0 |= 0x80;  /* If no interrupt is available */\n/* MLD */\n// Needed else SF-7000 IPL says 'Cannot read this disk'\nst0 &= 0x3F;\n      FDCResult[0] = st0; st0 = 0x00;\n      FDCResult[1] = FDCCurrTrack [FDCCurrDrv];\n      ExecCmdPhase = FALSE;\n      ResultPhase = TRUE;\n      StatusCounter = 100;\n      break;\n\n    case 10:                   /* ID des nchsten Sektors lesen */\n      FDCCurrDrv = FDCCommand[1] & 3;\n      FDCCurrSide[FDCCurrDrv] = (FDCCommand[1] >> 2) & 1;\n      if (dsk[FDCCurrDrv].HasDisk == FALSE)\n        {\n        st0 = FDCCurrDrv | 0xD8;  /* Equipment check, Not ready */\n        GetRes7();\n        }\n      else\n        {\n        TrackIndex = FDCCurrTrack[FDCCurrDrv] * dsk[FDCCurrDrv].Header.nbof_heads + FDCCurrSide[FDCCurrDrv];\n        st0 = FDCCommand[1] & 7;\n        GetRes7();\n//        FDCResult[5] = dsk[FDCCurrDrv].Tracks[TrackIndex].sector[0].sector;   /* 0x01=IBM, 0x41=Data, 0xC1=System */\n        FDCResult[5] = 0x41;   /* 0x01=IBM, 0x41=Data, 0xC1=System */\n        }\n      break;\n\n    case 15:                    /* SEEK - Spur suchen */\n      StatusCounter = 100;\n      StatusRegister = 0x80 | (1 << (FDCCommand[1] & 3));\n      FDCCurrDrv = FDCCommand[1] & 3;\n      FDCCurrSide[FDCCurrDrv] = (FDCCommand[1] >> 2) & 1;\n      if (dsk[FDCCurrDrv].HasDisk == FALSE)\n        {\n        st0 = FDCCurrDrv | 0xD8;  /* Equipment check, Not ready */\n        GetRes7();\n        }\n      else\n        {\n        FDCCurrTrack[FDCCurrDrv] = FDCCommand[2];\n        /* Diskette eingelegt? */\n        if (dsk[FDCCurrDrv].HasDisk == TRUE)\n          st0 = 0x20 | (FDCCommand[1] & 7); /* SEEK end + HD + US1 + US0 */\n        else\n          st0 = 0x08 | (FDCCommand[1] & 7); /* NOT READY + HD + US1 + US0 */\n        ExecCmdPhase = FALSE;\n        }\n      break;\n\n    default:\n      Msg(MSGT_DEBUG, Msg_Get(MSG_FDC765_Unknown_Write), FDCCommand [0]);\n      break;\n  }\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nbyte    FDCExecReadCommand()\n{\n  byte  ret = 0;\n\n  switch (FDCCommand [0])\n    {\n    case 2:\n      if (dsk[FDCCurrDrv].ImageType == DSK_FORMAT_RAW)\n        ret = dsk[FDCCurrDrv].Tracks[TrackIndex].DiscData[TrackDataStart + FDCDataPointer];\n      else\n        ret = dsk[FDCCurrDrv].Tracks[0].DiscData[TrackDataStart + FDCDataPointer];\n      FDCDataPointer ++;\n      if (FDCDataPointer == FDCDataLength)\n        {\n        st0 = (FDCCommand[1] & 7) | 0x40;   /* Unit, head, command canceled */\n        st1 = 0x80;                         /* End of track error           */\n        GetRes7();\n        }\n      break;\n\n    case 6:\n      if (dsk[FDCCurrDrv].ImageType == DSK_FORMAT_RAW)\n        ret = dsk[FDCCurrDrv].Tracks[TrackIndex].DiscData[TrackDataStart + FDCDataPointer];\n      else\n        ret = dsk[FDCCurrDrv].Tracks[0].DiscData[TrackDataStart + FDCDataPointer];\n      FDCDataPointer ++;\n      if (FDCDataPointer == FDCDataLength)\n        {\n        st0 = (FDCCommand[1] & 7) | 0x40;   /* Unit, head, command canceled */\n        st1 = 0x80;                         /* End of track error           */\n        GetRes7();\n        }\n      break;\n\n    default:\n      Msg(MSGT_DEBUG, Msg_Get(MSG_FDC765_Unknown_Read), FDCCommand [0]);\n      break;\n  }\n  return ret;\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nbyte    FDCGetResult()\n{\n  byte  ret = FDCResult[FDCResPointer];\n\n  FDCResPointer ++;\n  if (FDCResPointer == FDCResCounter)\n    {\n    StatusRegister = 0x80;\n    ResultPhase = FALSE;\n    }\n  return ret;\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    FDC765_Init()\n{\n  int   i;\n\n  for (i = 0; i < FDC765_MAXDRIVES /* was 1 ?!? */; i++)\n    {\n    dsk[i].HasDisk = FALSE;\n    dsk[i].Tracks = NULL;\n    dsk[i].TracksSize = 0;\n    }\n  FDC765_Reset();\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    FDC765_Close()\n{\n  int   i;\n\n  for (i = 0; i < FDC765_MAXDRIVES /* was 1 ?!? */; i++)\n    {\n    // WriteDskImage (i);\n    free (dsk[i].Tracks); // free() is doing the NULL test\n    }\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    FDC765_Reset()\n{\n  int   i;\n\n  FloppyMotor = 0;\n  FDCPointer = 0;\n  ExecCmdPhase = FALSE;\n  ResultPhase = FALSE;\n  StatusRegister = 128;\n\n  for (i = 0; i < FDC765_MAXDRIVES; i++)\n    {\n    FDCCurrTrack[i] = 0;\n    FDCWrProtect[i] = FALSE;\n    }\n  for (i = 0; i < 9; i++)\n    FDCCommand[i] = 0;\n  FDC765_Cmd_For_SF7000 = FALSE;\n}\n\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    FDC765_Data_Write (register byte Value)\n{\n  if (!ExecCmdPhase)\n     {\n     if (FDCPointer == 0)\n        {\n        FDCCommand [0] = Value & 0x1F;  /* New Command */\n        FDCPointer ++;\n        StatusRegister |= 0x10;         /* FDC Busy */\n        }\n     else\n     if (FDCPointer < bytes_in_cmd[FDCCommand[0]])\n        {\n        FDCCommand[FDCPointer] = Value; // Parameter for the command\n        FDCPointer ++;\n        }\n\n     if (FDCPointer == bytes_in_cmd[FDCCommand[0]])\n        {\n        FDCPointer = 0;\n        StatusRegister |= 0x20;\n        FDCExecWriteCommand (Value);                     /* Kommando ausfhren */\n        FDC765_Cmd_For_SF7000 = TRUE;\n        }\n     }\n  else\n     {\n     FDCExecWriteCommand (Value);                     /* Kommando ausfhren */\n     }\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nbyte    FDC765_Data_Read()\n{\n  FDC765_Cmd_For_SF7000 = FALSE;\n  if (ExecCmdPhase)\n     return FDCExecReadCommand();\n  if (ResultPhase)\n     return FDCGetResult();\n  return 0;\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nbyte    FDC765_Status_Read()\n{\n  // if (StatusCounter > 0)\n  //    {\n  //    StatusCounter --;\n  //    return 0;\n  //    }\n  return StatusRegister;\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/*********************************************************************/\nvoid    FDC765_Disk_Write_Get (int DrvNum, void **Data, int *DataSize)\n{\n  if (dsk[DrvNum].HasDisk)\n     {\n     *Data = dsk[DrvNum].Tracks;\n     *DataSize = dsk[DrvNum].TracksSize;\n     }\n  else\n     {\n     *Data = NULL;\n     *DataSize = 0;\n     }\n}\n\nvoid    FDC765_Disk_Remove (int DrvNum)\n{\n  dsk[DrvNum].HasDisk = FALSE;\n  free (dsk[DrvNum].Tracks); // free does the NULL pointer test\n}\n\n/*********************************************************************/\n/**                                                                 **/\n/** Zeigt einen Datei-Dialog zur Auswahl von Disk-Image-Dateien an, **/\n/** schliet eine evtl. bereits geffnete Datei, ffnet die ausge-  **/\n/** whlte Image-Datei und liest diese in den Speicher ein.         **/\n/** Der fr die Track-Informationen und die Daten des Disk-Images   **/\n/** bentigte Speicher wird jedoch nur einmal mit MALLOC vom Syste  **/\n/** angefordert und immer wieder verwendet, bis die Emulation be-   **/\n/** endet wird.                                                     **/\n/**                                                                 **/\n/** DRVNUM = Driver Number (0 for A: and 1 for B:)                  **/\n/**                                                                 **/\n/*********************************************************************/\n\nvoid    FDC765_Disk_Insert (int DrvNum, void *Data, int DataSize)\n{\n  FDC765_Disk *Disk = &dsk[DrvNum];\n\n  // Write existing disk ?\n  // WriteDskImage (DrvNum);\n\n  // Remove existing disk\n  FDC765_Disk_Remove (DrvNum);\n\n  // Set HasDisk and Write Protection flags\n  Disk->HasDisk = TRUE;\n  FDCWrProtect[DrvNum] = TRUE; // Write protection always ON yet\n\n  // detect DSK FORMAT -- TB\n  if (memcmp(Data, \"MV - CPCEMU Disk-File\\r\\nDisk-Info\\r\\n\", 34) == 0) {\n    Disk->ImageType = DSK_FORMAT_STANDARD_DSK;\n    memcpy(&Disk->Header, Data, 256);\n    Disk->Header.tracksize = ((const byte *)Data)[32] + (((const byte *)Data)[33] << 8);\n  } else if (memcmp(Data, \"EXTENDED CPC DSK File\\r\\nDisk-Info\\r\\n\", 34) == 0) {\n    dsk->ImageType = DSK_FORMAT_EXTENDED_DSK;\n    memcpy(&Disk->Header, Data, 256);\n  } else {\n    dsk->ImageType = DSK_FORMAT_RAW;\n    // No header in sf7000 image disks, initialization here\n    Disk->Header.nbof_tracks = 40;\n    Disk->Header.nbof_heads = 1;\n    Disk->Header.tracksize = (16 * 0x100);\n  }\n  ConsolePrintf (\"FDC765 %d %d head(s) %d tracks\\n\", Disk->ImageType, Disk->Header.nbof_heads, Disk->Header.nbof_tracks);\n\n  if (dsk->ImageType == DSK_FORMAT_RAW) {\n    // Calculating track size and allocating memory for it\n    Disk->TracksSize = Disk->Header.tracksize * Disk->Header.nbof_tracks * Disk->Header.nbof_heads;\n    Disk->Tracks = (FDC765_Track *)malloc (Disk->TracksSize);\n\n    // Copying memory from data source\n    memcpy (Disk->Tracks, Data, DataSize);\n    if (DataSize > Disk->TracksSize)\n       {\n       Msg(MSGT_USER, Msg_Get(MSG_FDC765_Disk_Too_Large1), DataSize, Disk->TracksSize);\n       Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_FDC765_Disk_Too_Large2));\n       }\n    if (DataSize < Disk->TracksSize)\n       {\n       Msg(MSGT_USER, Msg_Get(MSG_FDC765_Disk_Too_Small1), DataSize, Disk->TracksSize);\n       Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_FDC765_Disk_Too_Small2));\n       memset ((byte *)Disk->Tracks + DataSize, 0, Disk->TracksSize - DataSize);\n       }\n  } else {\n    Disk->TracksSize = DataSize - 256;\n    Disk->Tracks = (FDC765_Track *)malloc (Disk->TracksSize);\n    memcpy (Disk->Tracks, (const byte *)Data + 256, Disk->TracksSize);\n  }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/fdc765.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - fdc765.h\n// FDC765 (Floppy Disk Drive) Emulator - Headers\n//-----------------------------------------------------------------------------\n// Originally from Ulrich Cordes\n// Modifications for SF-7000 by Marc Le Douarain, Omar Cornut, Thomas Bernard\n//-----------------------------------------------------------------------------\n\n// Original file header:\n\n/***************************************/\n/**                                   **/\n/** AMSTRAD/Schneider CPC-Emulator    **/\n/** for Linux and X11                 **/\n/**                                   **/\n/** (c) 1999,                         **/\n/** Ulrich Cordes                     **/\n/** Bergstrasse 8                     **/\n/** 34292 AHNATAL / Germany           **/\n/**                                   **/\n/** email:  ulrich.cordes@gmx.de      **/\n/** WWW:    http://www.amstrad-cpc.de **/\n/**                                   **/\n/***************************************/\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define FDC765_MAXDRIVES   (2)    // Number of emulated drives\n#define FDC765_SPT         (16)   // (sectors per track) (9, max. 18 possible)\n#define FDC765_BPS         (2)    // (bytes per sector) (2 for 0x200 Bytes)\n\n#define DSK_FORMAT_RAW          1\n#define DSK_FORMAT_STANDARD_DSK 2\n#define DSK_FORMAT_EXTENDED_DSK 3\n\n//-----------------------------\n// Disk Header (256 bytes)\n//-----------------------------\nstruct FDC765_DiskHeader\n{\n  byte   tag[0x30];     /* 00-21  MV - CPC ...                                      */\n                        /* 22-2F  unused (0)                                        */\n  byte   nbof_tracks;   /* 30     number of tracks (40)                             */\n  byte   nbof_heads;    /* 31     number of heads (1) 2 not yet supported by cpcemu */\n  word   tracksize;     /* 32-33  tracksize (including 0x100 bytes header)          */\n                        /*        9 sectors * 0x200 bytes each + header = 0x1300    */\n  byte   tracksizetable[0xcc]; /* 34-FF  unused (0) or tracksize table for EXTENDED */\n};\n\nstruct FDC765_Track\n{\n  byte                  DiscData [4096];        // 16*256 bytes Data\n};\n\nstruct FDC765_Disk\n{\n  byte                  HasDisk;                // TRUE if a disk is inserted\n  byte                  ImageType;              // DSK_FORMAT_RAW / etc.\n  FDC765_DiskHeader     Header;                 // then the structure is valid\n  FDC765_Track         *Tracks;\n  int                   TracksSize;\n};\n\n// Initialize/Close funtions --------------------------------------------------\nvoid    FDC765_Init             ();         // Initialization\nvoid    FDC765_Close            ();         // Final Closure\nvoid    FDC765_Reset            ();         // Reset\n//-----------------------------------------------------------------------------\n\n// Disk Management functions --------------------------------------------------\nvoid    FDC765_Disk_Insert      (int DrvNum, void *Data, int DataSize);\nvoid    FDC765_Disk_Remove      (int DrvNum);\nvoid    FDC765_Disk_Write_Get   (int DrvNum, void **Data, int *DataSize);\n//-----------------------------------------------------------------------------\n\n// Emulation functions --------------------------------------------------------\nvoid    FDC765_Data_Write       (register byte Value);\nbyte    FDC765_Data_Read        ();\nbyte    FDC765_Status_Read      ();\n//-----------------------------------------------------------------------------\n\n// Added by Marc Le Douarain for SF-7000 emulation ----------------------------\n// (Pin 17 of the FDC is connected to SF-7000 [PA2] input port)\nextern u8 FDC765_Cmd_For_SF7000;\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/file.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - file.c\r\n// ROM File Loading & File Tools - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_game.h\"\r\n#include \"bios.h\"\r\n#include \"blitintf.h\"\r\n#include \"checksum.h\"\r\n#include \"file.h\"\r\n#include \"db.h\"\r\n#include \"debugger.h\"\r\n#include \"desktop.h\"\r\n#include \"fdc765.h\"\r\n#include \"patch.h\"\r\n#include \"saves.h\"\r\n#include \"sdsc.h\"\r\n#include \"vlfn.h\"\r\n#include \"vmachine.h\"\r\n#ifdef MEKA_ZIP\r\n    #include \"unzip.h\"\r\n#endif\r\n\r\n#if defined(ARCH_MACOSX)\r\n    #include \"platform/macosx/osxhelpers.h\"\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic int      Loading_UserVerbose = TRUE;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic int      Load_ROM_Init_Memory    ();\r\nint             Load_ROM_File           (const char *filename_ext);\r\nint             Load_ROM_Zipped         ();\r\nint             Load_ROM_Main           ();\r\nvoid            Load_ROM_Misc           (int reset);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Check if the loaded media is an overdump, and reduce size accordingly\r\n// FIXME: Function should work on a t_media_image eventually.\r\n//-----------------------------------------------------------------------------\r\nstatic void     Check_OverDump()\r\n{\r\n    int overdump_ratio = 1;\r\n\r\n    // Msg(MSGT_DEBUG, \"tsms.Size_ROM=%d\", tsms.Size_ROM);\r\n\r\n    // No check on ROM that are multiple of 8192 ...\r\n    if ((tsms.Size_ROM % 8192) != 0)\r\n        return; \r\n\r\n    // Added a limit to 8192 (the only smaller ROM I know is ColecoVision homebrew Tic Tac Toe)\r\n    while (tsms.Size_ROM > 8192)\r\n    {\r\n        int size_half = tsms.Size_ROM / 2;\r\n        u8 *d1 = &ROM[0];\r\n        u8 *d2 = &ROM[size_half];\r\n        int i;\r\n        for (i = size_half; i > 0; i--)\r\n            if (*d1++ != *d2++)\r\n                break;\r\n        if (i > 0)\r\n            break;\r\n        overdump_ratio *= 2;\r\n        tsms.Size_ROM /= 2;\r\n    }\r\n\r\n    // Verbose\r\n    if (Loading_UserVerbose && overdump_ratio > 1)\r\n        Msg(MSGT_USER, Msg_Get(MSG_OverDump), overdump_ratio);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Initialize filenames of various path/files (configuration files, etc).\r\n// FIXME-BUFFER: Potential buffer overflows here.\r\n//-----------------------------------------------------------------------------\r\nvoid    Filenames_Init()\r\n{\r\n    // Get and save current directory\r\n    getcwd(g_env.Paths.StartingDirectory, countof(g_env.Paths.StartingDirectory));\r\n\r\n    // Find emulator directory --------------------------------------------------\r\n\r\n#if defined(ARCH_MACOSX)\r\n    GetResourcePath( g_env.Paths.EmulatorDirectory, sizeof(g_env.Paths.EmulatorDirectory) );\r\n    ConsolePrintf (\"Resource path = %s\\n\", g_env.Paths.EmulatorDirectory);\r\n#else\r\n    strcpy(g_env.Paths.EmulatorDirectory, g_env.argv[0]);\r\n    #ifdef ARCH_WIN32\r\n        StrReplace(g_env.Paths.EmulatorDirectory, '\\\\', '/');\r\n    #endif\r\n    char* p = strrchr(g_env.Paths.EmulatorDirectory, '/');\r\n    if (p)\r\n        *p = EOSTR;\r\n    else\r\n        strcpy(g_env.Paths.EmulatorDirectory, g_env.Paths.StartingDirectory);\r\n#endif\r\n\r\n#if defined(ARCH_UNIX) || defined(ARCH_MACOSX)\r\n    char* rp = realpath(g_env.Paths.EmulatorDirectory, NULL);\r\n    if (rp != NULL)\r\n    {\r\n        strcpy(g_env.Paths.EmulatorDirectory, rp);\r\n        //strcat(g_env.Paths.EmulatorDirectory, \"/\");\r\n        free(rp);\r\n    }\r\n#endif\r\n\r\n    char data_dir[FILENAME_LEN];\r\n    char internal_resources_dir[FILENAME_LEN];\r\n    char external_resources_dir[FILENAME_LEN];\r\n    strcpy(data_dir, g_env.Paths.EmulatorDirectory);\r\n#ifdef ARCH_MACOSX\r\n    GetWritableInternalResourcePath( internal_resources_dir, sizeof(internal_resources_dir) );\r\n    GetWritableExternalResourcePath( external_resources_dir, sizeof(external_resources_dir) );\r\n    const char* files_to_copy_internal_resources[2] = \r\n    {\r\n        \"meka.inp\",\r\n        NULL\r\n    };\r\n    PopulateWritableInternalResourcesPath(internal_resources_dir, files_to_copy_internal_resources);\r\n#else\r\n    strcpy(internal_resources_dir, g_env.Paths.EmulatorDirectory);\r\n    strcpy(external_resources_dir, g_env.Paths.EmulatorDirectory);\r\n#endif\r\n\r\n    //ConsolePrintf(\"Data Directory = %s\\n\", data_dir);\r\n    //ConsolePrintf(\"Internal Writable Resources Directory = %s\\n\", internal_resources_dir);\r\n    //ConsolePrintf(\"External Writable Resources Directory = %s\\n\", external_resources_dir);\r\n\r\n    // Datafiles\r\n    sprintf(g_env.Paths.DataFile,       \"%s/meka.dat\",    data_dir);\r\n    sprintf(g_env.Paths.DataBaseFile,   \"%s/meka.nam\",    data_dir);\r\n    sprintf(g_env.Paths.SkinFile,       \"%s/meka.thm\",    data_dir);\r\n\r\n    sprintf(Patches.filename,           \"%s/meka.pat\",    data_dir);\r\n    sprintf(Blitters.filename,          \"%s/meka.blt\",    data_dir);\r\n    sprintf(Messages.FileName,          \"%s/meka.msg\",    data_dir);\r\n\r\n    // files that are written to\r\n    sprintf(Desktop.filename,           \"%s/meka.dsk\",    internal_resources_dir);\r\n    sprintf(VLFN_DataBase.filename,     \"%s/meka.fdb\",    internal_resources_dir);\r\n    sprintf(Inputs.FileName,            \"%s/meka.inp\",    internal_resources_dir);\r\n\r\n    // Documentations\r\n    sprintf(g_env.Paths.DocumentationMain,       \"%s/meka.txt\",      data_dir);\r\n    sprintf(g_env.Paths.DocumentationCompat,     \"%s/compat.txt\",    data_dir);\r\n    sprintf(g_env.Paths.DocumentationMulti,      \"%s/multi.txt\",     data_dir);\r\n    sprintf(g_env.Paths.DocumentationChanges,    \"%s/changes.txt\",   data_dir);\r\n    sprintf(g_env.Paths.DocumentationDebugger,   \"%s/debugger.txt\",  data_dir);\r\n\r\n    // Configuration file\r\n#ifdef ARCH_WIN32\r\n    sprintf(g_env.Paths.ConfigurationFile,       \"%s/mekaw.cfg\",     g_env.Paths.EmulatorDirectory);\r\n#else /* unix */\r\n    sprintf(g_env.Paths.ConfigurationFile,       \"%s/meka.cfg\",      internal_resources_dir);\r\n#endif\r\n\r\n    // Directories\r\n    sprintf(g_env.Paths.ScreenshotDirectory,     \"%s/Screenshots\",   external_resources_dir);\r\n    sprintf(g_env.Paths.SavegameDirectory,       \"%s/Saves\",         external_resources_dir);\r\n    sprintf(g_env.Paths.MusicDirectory,          \"%s/Music\",         external_resources_dir);\r\n    sprintf(g_env.Paths.DebugDirectory,          \"%s/Debug\",         external_resources_dir);\r\n\r\n    // ROM\r\n    strcpy(g_env.Paths.MediaImageFile,  \"\");\r\n    strcpy(g_env.Paths.BatteryBackedMemoryFile, \"\");\r\n}\r\n\r\nvoid    Filenames_Init_ROM()\r\n{\r\n    // ROM (when parsed from command line)\r\n    if (StrIsNull(g_env.Paths.MediaImageFile))\r\n    {\r\n        strcpy(g_env.Paths.BatteryBackedMemoryFile, \"\");\r\n        return;\r\n    }\r\n\r\n    // Save/OnBoard memory filename\r\n    {\r\n        char temp[FILENAME_LEN];\r\n        strcpy(temp, g_env.Paths.MediaImageFile);\r\n        StrPath_RemoveExtension(temp);\r\n        StrPath_RemoveDirectory(temp);\r\n        sprintf(g_env.Paths.BatteryBackedMemoryFile, \"%s/%s.sav\", g_env.Paths.SavegameDirectory, temp);\r\n    }\r\n}\r\n\r\nbool    Load_ROM_Command_Line()\r\n{\r\n    if (StrIsNull(g_env.Paths.MediaImageFile))\r\n        return false;\r\n    return Load_ROM(LOAD_MODE_COMMANDLINE, true);\r\n}\r\n\r\n// Reload current ROM file\r\nbool    Reload_ROM()\r\n{\r\n    if (StrIsNull(g_env.Paths.MediaImageFile))\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_LoadROM_Reload_No_ROM));\r\n        return false;\r\n    }\r\n    if (Load_ROM(LOAD_MODE_GUI, FALSE))\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_LoadROM_Reload_Reloaded));\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n// Load media/ROM from given filename.\r\n// If user_verbose if false, avoid printing stuff to the message box\r\n// Note: path to ROM filename must be set in 'g_env.Paths.MediaImageFile' before calling this\r\nbool    Load_ROM(t_load_mode load_mode, bool user_verbose)\r\n{\r\n    // Set file global flag\r\n    Loading_UserVerbose = user_verbose;\r\n\r\n    switch (load_mode)\r\n    {\r\n    case LOAD_MODE_COMMANDLINE:\r\n        if (user_verbose)\r\n            ConsolePrint(Msg_Get(MSG_LoadROM_Loading));\r\n        break;\r\n    case LOAD_MODE_GUI:\r\n        // FIXME: do not save Backed Memory in non-verbose mode\r\n        // This mode is only used by the file browser. This way we avoid loading\r\n        // and saving all battery backed memory when doing a \"Load All\".\r\n        // Of course, this is a little hack but it's better this way.\r\n        if (user_verbose)\r\n            BMemory_Save();\r\n        break;\r\n    }\r\n\r\n    if (Load_ROM_Main() != MEKA_ERR_OK)\r\n    {\r\n        switch (load_mode)\r\n        {\r\n        case LOAD_MODE_COMMANDLINE:\r\n            Quit_Msg(\"%s\\n\\\"%s\\\"\\n\", meka_strerror(), g_env.Paths.MediaImageFile);\r\n            return false;\r\n        case LOAD_MODE_GUI:\r\n            Msg(MSGT_USER, Msg_Get(MSG_Error_Base), meka_strerror());\r\n            return false;\r\n        }\r\n    }\r\n\r\n    // If we are already in SF-7000 mode, do not reset (allows hot switching disks)\r\n    const bool reset = (g_driver->id != DRV_SF7000);\r\n\r\n    // Miscellaneous stuff (including reset)\r\n    Load_ROM_Misc(reset);\r\n\r\n    if (load_mode == LOAD_MODE_COMMANDLINE)\r\n    {\r\n        if (user_verbose)\r\n            ConsolePrint(\"\\n\");\r\n        if (opt.State_Load != -1)\r\n        {\r\n            opt.State_Current = opt.State_Load; // Note: we're not calling the function to avoid displaying the 'slot change' message\r\n            opt.State_Load = -1;\r\n            SaveState_Load();\r\n        }\r\n    }\r\n\r\n    // Verbose\r\n    if (user_verbose)\r\n    {\r\n        // Display success message\r\n        char filename[FILENAME_LEN];\r\n        StrPath_RemoveDirectory(filename, g_env.Paths.MediaImageFile);\r\n        if (g_driver->id != DRV_SF7000)\r\n            Msg(MSGT_USER, Msg_Get(MSG_LoadROM_Success), filename);\r\n        else\r\n            Msg(MSGT_USER, Msg_Get(MSG_LoadDisk_Success), filename);\r\n\r\n        // Display data from DB\r\n        if (DB.current_entry)\r\n        {\r\n            // Name\r\n            Msg(MSGT_USER, \"\\\"%s\\\"\", DB_Entry_GetCurrentName (DB.current_entry));\r\n\r\n            // Comment\r\n            if (DB.current_entry->comments)\r\n                Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_Comment), DB.current_entry->comments);\r\n\r\n            // Show SMS-GG mode info\r\n            if (DB.current_entry->flags & DB_FLAG_SMSGG_MODE)\r\n            {\r\n                if (DB.current_entry->comments)\r\n                    // Append to comment message\r\n                    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_LoadROM_SMSGG_Mode_Comment));\r\n                else // Print the comment marker before\r\n                    Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_Comment), Msg_Get(MSG_LoadROM_SMSGG_Mode_Comment));\r\n            }\r\n\r\n            // Show BAD ROM warning\r\n            if (DB.current_entry->flags & DB_FLAG_BAD)\r\n            {\r\n                Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_LoadROM_Warning));\r\n                Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_LoadROM_Bad_Dump_Long));\r\n                Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_LoadROM_Bad_Dump_Short));\r\n            }\r\n\r\n            // Show Product Number\r\n            if (DB.current_entry->product_no && g_config.show_product_number)\r\n                Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_Product_Num), DB.current_entry->product_no);\r\n        }\r\n\r\n        // Show SDSC Header\r\n        if (user_verbose)\r\n            SDSC_Read_and_Display();\r\n    }\r\n\r\n    // Automatically change input peripheral depending on MEKA.NAM entry\r\n    // FIXME: we don't do it at all if !user_verbose, to save us from passing\r\n    // the verbose flag all down to inputs peripherals changing functions.\r\n    // Since the verbose flag is only cleared by the file browser \"Load All\"\r\n    // functionality, it is ok to avoid changing inputs.\r\n    if (user_verbose)\r\n        Input_ROM_Change();\r\n\r\n    return true;\r\n}\r\n\r\nvoid    Load_Header_and_Footer_Remove (int *pstart, long *psize)\r\n{\r\n    int start = 0;\r\n    int size = *psize;\r\n    \r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_COLECO: //--- Coleco Vision\r\n        // Skip 128 bytes header + 512 bytes footer if necessary\r\n        // (both on the same time)\r\n        if (size > 0x1000)\r\n        {\r\n            /*\r\n            const int size_mod = size % 0x1000;\r\n            if (size_mod == 128 + 512)\r\n            { \r\n                start += 128; size -= 128 + 512; \r\n            }\r\n            else\r\n            {\r\n                if (size_mod == 128 || size_mod == (128+512))\r\n                { \r\n                    start += 128; size -= 128; \r\n                }\r\n                if (size_mod == 512)\r\n                { \r\n                    size -= 512; \r\n                }\r\n            }\r\n            */\r\n        }\r\n        break;\r\n    case DRV_SF7000: //--- SF-7000\r\n        break;\r\n    default:         //--- Master System, Game Gear, SG-1000, SC-3000...\r\n        // Skip 512 bytes header if necessary\r\n        if (size > 0x4000 && (size % 0x4000) == 512)\r\n        { start += 512; size -= 512; }\r\n        // Skip 64 bytes footer if necessary\r\n        if (size > 0x1000 && (size % 0x1000) == 64)\r\n        { size -= 64; }\r\n        break;\r\n    }\r\n\r\n    *pstart = start;\r\n    *psize = size;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Load_ROM_Zipped ()\r\n// Load ROM from a ZIP file\r\n//-----------------------------------------------------------------------------\r\n#ifdef MEKA_ZIP\r\nint             Load_ROM_Zipped ()\r\n{\r\n    int           err = UNZ_OK;\r\n    unzFile       zf = NULL;\r\n    unz_file_info zf_infos;\r\n    int           start_at;\r\n    char          temp[FILENAME_LEN];\r\n\r\n    zf = unzOpen(g_env.Paths.MediaImageFile);\r\n    if (zf == NULL)\r\n        return (MEKA_ERR_ZIP_LOADING); // Error loading ZIP file\r\n\r\n    // Locating..\r\n    err = unzGoToFirstFile(zf);\r\n    do\r\n    {\r\n        if (err != UNZ_OK) { unzClose(zf); return (MEKA_ERR_ZIP_INTERNAL); }\r\n\r\n        // Getting informations..\r\n        unzGetCurrentFileInfo(zf, &zf_infos, temp, FILENAME_LEN, NULL, 0, NULL, 0);\r\n        StrPath_GetExtension(temp);\r\n        StrUpper(temp);\r\n\r\n        // Check if valid\r\n        if (drv_is_known_filename_extension(temp))\r\n        {\r\n            break;\r\n        }\r\n\r\n        // Else try next file\r\n        err = unzGoToNextFile(zf);\r\n\r\n        // If that was the last one, we'll use it\r\n    } while (err != UNZ_END_OF_LIST_OF_FILE);\r\n    \r\n    tsms.Size_ROM = zf_infos.uncompressed_size;\r\n\r\n    // Setting driver ------------------------------------------------------------\r\n    // Must be done there because we don't have the filename before..\r\n    g_machine.driver_id = drv_get_from_filename_extension(temp);\r\n\r\n    // Remove Header & Footer\r\n    Load_Header_and_Footer_Remove(&start_at, &tsms.Size_ROM);\r\n\r\n    // Check out if the ROM isn't actually empty\r\n    if (tsms.Size_ROM <= 0)\r\n    { unzClose (zf); return (MEKA_ERR_FILE_EMPTY); } /* File empty */\r\n\r\n    // Allocate necessary memory to load ROM -------------------------------------\r\n    if (Load_ROM_Init_Memory () == -1)\r\n    { unzClose (zf); return (MEKA_ERR_MEMORY); } /* Not enough memory */\r\n\r\n    // Opening..\r\n    err = unzOpenCurrentFile (zf);\r\n    if (err != UNZ_OK) { unzClose (zf); return (MEKA_ERR_ZIP_INTERNAL); }\r\n\r\n    // Skipping header if necessary..\r\n    if (start_at != 0)\r\n        unzReadCurrentFile (zf, ROM, start_at);\r\n\r\n    // Reading..\r\n    err = unzReadCurrentFile (zf, ROM, tsms.Size_ROM);\r\n    if (err < 0 || err != tsms.Size_ROM)\r\n    {\r\n        unzCloseCurrentFile (zf);\r\n        unzClose (zf);\r\n        return (MEKA_ERR_ZIP_INTERNAL);\r\n    }\r\n\r\n    // Closing..\r\n    unzCloseCurrentFile (zf);\r\n    unzClose (zf);\r\n\r\n    return (MEKA_ERR_OK);\r\n}\r\n#endif // ifdef MEKA_ZIP\r\n\r\n// LOAD A ROM FROM A FILE -----------------------------------------------------\r\nint             Load_ROM_File(const char *filename_ext)\r\n{\r\n    FILE *      f;\r\n    int         start_at;\r\n\r\n    // Setting driver -----------------------------------------------------------\r\n    // Must be done there because Load_ROM_Zip\r\n    g_machine.driver_id = drv_get_from_filename_extension(filename_ext);\r\n\r\n    // Open file ----------------------------------------------------------------\r\n    if ((f = fopen(g_env.Paths.MediaImageFile, \"rb\")) == NULL)\r\n        return (MEKA_ERR_FILE_OPEN);\r\n\r\n    // Get file size\r\n    fseek (f, 0, SEEK_END);\r\n    tsms.Size_ROM = ftell (f);\r\n\r\n    // Remove Header & Footer\r\n    Load_Header_and_Footer_Remove (&start_at, &tsms.Size_ROM);\r\n\r\n    // Check out if the ROM isn't actually empty\r\n    if (tsms.Size_ROM <= 0)\r\n        return (MEKA_ERR_FILE_EMPTY);       // File empty .. FIXME: to short ? because of header..\r\n    fseek (f, start_at, SEEK_SET);\r\n\r\n    // Allocate necessary memory to load ROM ------------------------------------\r\n    if (Load_ROM_Init_Memory () == -1)\r\n        return (MEKA_ERR_MEMORY);           // Not enough memory\r\n\r\n    // Read data then close file ------------------------------------------------\r\n    if (fread (ROM, 1, tsms.Size_ROM, f) != (unsigned int)tsms.Size_ROM)\r\n        return (MEKA_ERR_FILE_READ);        // Error reading file\r\n    fclose (f);\r\n\r\n    // Copy data for Colecovision mirroring -------------------------------------\r\n    if (g_machine.driver_id == DRV_COLECO)\r\n    {\r\n        // FIXME\r\n    }\r\n\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\n// ALLOCATE SUFFICIENT MEMORY TO LOAD ROM -------------------------------------\r\nstatic int      Load_ROM_Init_Memory ()\r\n{\r\n    u8 *        p;\r\n    int         alloc_size;\r\n\r\n    // FIXME: The computation below are so old that I should be checking them someday. I\r\n    // I'm sure that something wrong lies here.\r\n    tsms.Pages_Mask_8k = 1;\r\n    tsms.Pages_Count_8k = (tsms.Size_ROM / 0x2000);\r\n    if (tsms.Size_ROM % 0x2000) tsms.Pages_Count_8k += 1;\r\n    while (tsms.Pages_Mask_8k < tsms.Pages_Count_8k)\r\n        tsms.Pages_Mask_8k *= 2;\r\n    tsms.Pages_Mask_8k --;\r\n    tsms.Pages_Count_8k --;\r\n    tsms.Pages_Mask_16k = 1;\r\n    tsms.Pages_Count_16k = (tsms.Size_ROM / 0x4000);\r\n    if (tsms.Size_ROM % 0x4000) tsms.Pages_Count_16k += 1;\r\n    while (tsms.Pages_Mask_16k < tsms.Pages_Count_16k)\r\n        tsms.Pages_Mask_16k *= 2;\r\n    tsms.Pages_Mask_16k --;\r\n    tsms.Pages_Count_16k --;\r\n\r\n    // Calculate allocation size to upper bound of Pages_Count_16k\r\n    // If ROM is smaller than 48 kb, malloc 48 kb to avoid problem reading\r\n    // data under Z80 emulation (default Sega mapper).\r\n    alloc_size = (tsms.Pages_Mask_16k + 1) * 0x4000;\r\n    if (alloc_size < 0xC000)\r\n        alloc_size = 0xC000;\r\n\r\n    // Allocate\r\n    if ((p = (u8*)malloc (alloc_size)) == NULL)\r\n        return (-1);\r\n    if (Game_ROM)\r\n        free (Game_ROM);\r\n    Game_ROM = p;\r\n\r\n    // Fill ROM with 0xFF\r\n    // - SG-1000 Safari Hunting : ROM is 16kb, access 48 kb memory map\r\n    //   (actually there's a correct way to emulate that, see Cgfm2's SC-3000 \r\n    //    documentation, in the meanwhile, filling with 0xFF allow the game to work)\r\n    // - ROM image that are not power of 2 trying to access inexistant pages.\r\n    //   eg: Shinobi (UE) [b2].sms\r\n    memset (Game_ROM, 0xFF, alloc_size);\r\n\r\n    ROM = Game_ROM;\r\n\r\n    return (0);\r\n}\r\n\r\n// LOAD A ROM INTO MEMORY, RESET SYSTEM AND VARIOUS STUFF.. -------------------\r\nint             Load_ROM_Main ()\r\n{\r\n    int         err;\r\n    char        filename_ext[FILENAME_LEN];\r\n#ifdef MEKA_ZIP\r\n    int         zipped = FALSE;\r\n#endif\r\n\r\n    Filenames_Init_ROM();\r\n\r\n    // Check extension ----------------------------------------------------------\r\n    strcpy(filename_ext, g_env.Paths.MediaImageFile);\r\n    StrPath_GetExtension(filename_ext);\r\n    StrUpper(filename_ext);\r\n    if (strcmp(filename_ext, \"ZIP\") == 0)\r\n    {\r\n#ifdef MEKA_ZIP\r\n        zipped = TRUE;\r\n#else\r\n        meka_errno = MEKA_ERR_ZIP_NOT_SUPPORTED;\r\n        return (MEKA_ERR_ZIP_NOT_SUPPORTED); // ZIP files not supported\r\n#endif\r\n    }\r\n\r\n#ifdef MEKA_ZIP\r\n    if (zipped)\r\n        err = Load_ROM_Zipped();\r\n    else\r\n#endif\r\n        err = Load_ROM_File(filename_ext);\r\n\r\n    // Now done in Load_ROM_xxx()\r\n    // g_machine.driver_id = drv_get_from_ext (file.temp);\r\n\r\n    return (meka_errno = err);\r\n}\r\n\r\nvoid    Load_ROM_Misc (int reset)\r\n{\r\n    // Check for overdump\r\n    Check_OverDump();\r\n\r\n    // Perform checksum and DB lookup\r\n    Checksum_Perform (ROM, tsms.Size_ROM);\r\n\r\n    // Automatic SMS-GG mode\r\n    // This is because GoodTools kept putting SMS-mode GG games with a .GG extension\r\n    // So the emulator is forced to look them up with a database ...\r\n    if (DB.current_entry && (DB.current_entry->flags & DB_FLAG_SMSGG_MODE))\r\n    {\r\n        // Why the test? Because we want the game to disfunction \"properly\" with a .SG/.COL extension\r\n        // Of course, in the future, MEKA may could force ALL driver based on DB entry.\r\n        // But this will cause a problem for Pit Pot secret screen in SG-1000 mode (and Hang On, etc...)\r\n        // Then this will require advanced-user selectable machine.\r\n        if (g_machine.driver_id == DRV_GG)\r\n            g_machine.driver_id = DRV_SMS;\r\n    }\r\n\r\n    // Initialize patching system for this ROM and apply\r\n    Patches_ROM_Initialize();\r\n    Patches_ROM_Apply();\r\n\r\n    // Set driver\r\n    drv_set (g_machine.driver_id);\r\n\r\n    // Do not system if old AND new driver is SF7000 (for disk change, this is slighty hacky)\r\n    if (reset || g_machine.driver_id != DRV_SF7000)\r\n    {\r\n        Machine_Init();\r\n        g_machine_flags |= MACHINE_ROM_LOADED;\r\n        Machine_Insert_Cartridge();\r\n        Machine_ON();\r\n    }\r\n\r\n    if (g_machine.driver_id == DRV_SF7000)\r\n        FDC765_Disk_Insert(0, ROM, tsms.Size_ROM);\r\n\r\n    // FIXME: do not save Backed Memory in non-verbose mode\r\n    // Read the full comment next to BMemory_Save() in Load_ROM()\r\n    if (Loading_UserVerbose)\r\n        BMemory_Load();\r\n\r\n    // Update game boxes\r\n    gamebox_rename_all();\r\n\r\n    // Miscellaneous things to apply when machine type change\r\n    Change_System_Misc();\r\n\r\n    // BIOS load/unload\r\n    // FIXME: this is a mess\r\n    if ((g_config.enable_BIOS) && (g_machine.driver_id == DRV_SMS) && (sms.Country == COUNTRY_EXPORT))\r\n        BIOS_Load();\r\n    else\r\n        BIOS_Unload();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/file.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - file.h\n// ROM File Loading & File Tools - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\nenum t_load_mode\n{\n    LOAD_MODE_COMMANDLINE,\n    LOAD_MODE_GUI\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nbool            Load_ROM                (t_load_mode load_mode, bool user_verbose);\nbool            Load_ROM_Command_Line  ();\nbool            Reload_ROM             ();\n\nvoid            Filenames_Init         ();     // Initialize filenames used by emulator (path to config files, etc.)\nvoid            Filenames_Init_ROM     ();     // Initialize filenames for current ROM\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/fonts.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - fonts.c\r\n// Fonts Tools (mostly wrapping Allegro functionalities now) - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_font      Fonts[FONTID_COUNT_];\r\nt_font *    FontCurrent = NULL;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void Font_Declare(t_font_id id, const char* text_id, const char* load_filename, int load_size)\r\n{\r\n    Fonts[id].id = id;\r\n    Fonts[id].text_id = text_id;\r\n    Fonts[id].load_filename = load_filename;\r\n    Fonts[id].load_size = load_size;\r\n}\r\n\r\nvoid    Fonts_Init()\r\n{\r\n    Font_Declare(FONTID_SMALL,          \"CLASSIC_SMALL\",    \"font_2.tga\",                   0);\r\n    Font_Declare(FONTID_MEDIUM,         \"CLASSIC_MEDIUM\",   \"font_1.tga\",                   0);\r\n    Font_Declare(FONTID_LARGE,          \"CLASSIC_LARGE\",    \"font_0.tga\",                   0);\r\n    Font_Declare(FONTID_PROGGY_TINY,        \"PROGGY_TINY\",      \"fonts/ProggyTinySZ.ttf\",       -10);\r\n    Font_Declare(FONTID_PROGGY_SMALL,   \"PROGGY_SMALL\",     \"fonts/ProggySmall.ttf\",        -10);\r\n    Font_Declare(FONTID_PROGGY_SQUARE,  \"PROGGY_SQUARE\",    \"fonts/ProggySquareSZ.ttf\",     -11);\r\n    Font_Declare(FONTID_PROGGY_CLEAN,   \"PROGGY_CLEAN\",     \"fonts/ProggyCleanSZ.ttf\",      -13);\r\n    Font_Declare(FONTID_PCMONO,         \"PCMONO\",           \"fonts/PixelCarnageMono.ttf\",   -16);\r\n    Font_Declare(FONTID_CRISP,          \"CRISP\",            \"fonts/Crisp.ttf\",              -16);\r\n    // NB: actual data loaded in Data.c\r\n}\r\n\r\nvoid    Fonts_Close()\r\n{\r\n}\r\n\r\n// Register font to the fonts system\r\nvoid    Fonts_DeclareFont(t_font_id font_id, const char* text_id)\r\n{\r\n    t_font *font        = &Fonts[font_id];\r\n    font->id            = font_id;\r\n    font->height        = al_get_font_line_height(font->library_data);\r\n    font->text_id       = text_id;\r\n}\r\n\r\nvoid    Font_SetCurrent(t_font_id font_id)\r\n{\r\n    FontCurrent = &Fonts[font_id];\r\n}\r\n\r\n// from imgui.cpp\r\nconst char* CalcWordWrapPosition(t_font* font, const char* text, const char* text_end, int wrap_width)\r\n{\r\n    int line_width = 0;\r\n    int word_width = 0;\r\n    int blank_width = 0;\r\n\r\n    const char* word_end = text;\r\n    const char* prev_word_end = NULL;\r\n    bool inside_word = true;\r\n\r\n    const char* s = text;\r\n    while (s < text_end)\r\n    {\r\n        const char c = *s;\r\n\r\n        if (c == '\\n')\r\n        {\r\n            line_width = word_width = blank_width = 0;\r\n            inside_word = true;\r\n            s++;\r\n            continue;\r\n        }\r\n\r\n        const char buf[2] = { c, 0 };\r\n        const int char_width = Font_TextWidth(font->id, buf);\r\n        if (c == ' ' || c == '\\t')\r\n        {\r\n            if (inside_word)\r\n            {\r\n                line_width += blank_width;\r\n                blank_width = 0;\r\n            }\r\n            blank_width += char_width;\r\n            inside_word = false;\r\n        }\r\n        else\r\n        {\r\n            word_width += char_width;\r\n            if (inside_word)\r\n            {\r\n                word_end = s + 1;\r\n            }\r\n            else\r\n            {\r\n                prev_word_end = word_end;\r\n                line_width += word_width + blank_width;\r\n                word_width = blank_width = 0;\r\n            }\r\n\r\n            // Allow wrapping after punctuation.\r\n            inside_word = !(c == '.' || c == ',' || c == ';' || c == '!' || c == '?' || c == '\\\"');\r\n        }\r\n\r\n        // We ignore blank width at the end of the line (they can be skipped)\r\n        // Words that cannot possibly fit within an entire line will be cut anywhere.\r\n        if (line_width + word_width >= wrap_width)\r\n        {\r\n            if (word_width < wrap_width)\r\n                s = prev_word_end ? prev_word_end : word_end;\r\n            break;\r\n        }\r\n\r\n        s++;\r\n    }\r\n\r\n    return s;\r\n}\r\n\r\n// Print given string with parameters using current font\r\nvoid    Font_Print(t_font_id font_id, const char *text, int x, int y, ALLEGRO_COLOR color, int wrap_width)\r\n{\r\n    t_font* font = (font_id == FONTID_CUR) ? FontCurrent : &Fonts[font_id];\r\n\r\n    while (*text)\r\n    {\r\n        // Split by line\r\n        const char* line_start = text;\r\n        const char* line_end = strchr(line_start, '\\n');\r\n        if (!line_end)\r\n            line_end = line_start + strlen(line_start);\r\n\r\n        // Wrap\r\n        if (wrap_width > 0)\r\n        {\r\n            const char* new_line_end = CalcWordWrapPosition(font, line_start, line_end, wrap_width);\r\n            if (line_end != new_line_end)\r\n            {\r\n                line_end = new_line_end;\r\n                while (*line_end == ' ' || *line_end == '\\t' || *line_end == '\\r' || *line_end == '\\n')\r\n                    line_end++;\r\n            }\r\n        }\r\n\r\n        // Copy it into a buffer - Allegro doesn't provide the right apis\r\n        char buf[MSG_MAX_LEN];\r\n        memcpy(buf, line_start, line_end-line_start);\r\n        buf[line_end-line_start] = 0;\r\n        al_draw_text(font->library_data, color, x, y, ALLEGRO_ALIGN_LEFT, buf);\r\n\r\n        y += font->height;\r\n\r\n        text = line_end;\r\n        if (*text == '\\n')\r\n            text++;\r\n    }\r\n}\r\n\r\n// Print given string, centered around a given x position\r\nvoid    Font_PrintCentered(t_font_id font_id, const char *text, int x, int y, ALLEGRO_COLOR color)\r\n{\r\n    t_font* font = (font_id == FONTID_CUR) ? FontCurrent : &Fonts[font_id];\r\n\r\n    al_draw_text(font->library_data, color, x, y, ALLEGRO_ALIGN_CENTRE, text);\r\n}\r\n\r\nint     Font_Height(t_font_id font_id)\r\n{\r\n    t_font* font = (font_id == FONTID_CUR) ? FontCurrent : &Fonts[font_id];\r\n\r\n    return font->height;\r\n}\r\n\r\nint      Font_TextWidth(t_font_id font_id, const char* text, const char* text_end)\r\n{\r\n    t_font* font = (font_id == FONTID_CUR) ? FontCurrent : &Fonts[font_id];\r\n\r\n    if (text_end)\r\n    {\r\n        // FIXME-OPT: allegro needs better API\r\n        static char buf[MSG_MAX_LEN];\r\n        snprintf(buf, countof(buf), \"%.*s\", text_end-text, text);\r\n        buf[countof(buf)-1] = 0;\r\n        return al_get_text_width(font->library_data, buf);\r\n    }\r\n    else\r\n    {\r\n        return al_get_text_width(font->library_data, text);\r\n    }\r\n}\r\n\r\nint      Font_TextHeight(t_font_id font_id, const char *text, int wrap_width)\r\n{\r\n    t_font* font = (font_id == FONTID_CUR) ? FontCurrent : &Fonts[font_id];\r\n\r\n    int h = 0;\r\n    while (*text)\r\n    {\r\n        // Split by line\r\n        const char* line_start = text;\r\n        const char* line_end = strchr(line_start, '\\n');\r\n        if (!line_end)\r\n            line_end = line_start + strlen(line_start);\r\n\r\n        // Wrap\r\n        if (wrap_width > 0)\r\n        {\r\n            const char* new_line_end = CalcWordWrapPosition(font, line_start, line_end, wrap_width);\r\n            if (line_end != new_line_end)\r\n            {\r\n                line_end = new_line_end;\r\n                while (*line_end == ' ' || *line_end == '\\t' || *line_end == '\\r' || *line_end == '\\n')\r\n                    line_end++;\r\n            }\r\n        }\r\n\r\n        h += font->height;\r\n\r\n        text = line_end;\r\n        if (*text == '\\n')\r\n            text++;\r\n    }\r\n    return h;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nFontPrinter::FontPrinter(t_font_id _font_id)\r\n{\r\n    this->font_id = _font_id;\r\n    this->color = COLOR_SKIN_WINDOW_TEXT;\r\n}\r\n\r\nFontPrinter::FontPrinter(t_font_id _font_id, ALLEGRO_COLOR _color)\r\n{\r\n    this->font_id = _font_id;\r\n    this->color = _color;\r\n}\r\n\r\nvoid FontPrinter::Printf(v2i pos, const char* format, ...) const\r\n{\r\n    char buf[512];\r\n    va_list args;\r\n    va_start(args, format);\r\n    vsnprintf(buf, countof(buf), format, args);\r\n    va_end(args);\r\n    Font_Print(this->font_id, buf, pos.x, pos.y, this->color);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/fonts.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - fonts.h\n// Fonts Tools (mostly wrapping Allegro functionalities) - Headers\n//-----------------------------------------------------------------------------\n\n#pragma once\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\nenum t_font_id\n{\n    FONTID_NONE         = -2,\n    FONTID_CUR          = -1,   // NB: Code tends to write -1 directly as an abbreviation\n    FONTID_SMALL        = 0,\n    FONTID_MEDIUM       = 1,\n    FONTID_LARGE        = 2,\n    FONTID_PROGGY_TINY,\n    FONTID_PROGGY_SMALL,\n    FONTID_PROGGY_SQUARE,\n    FONTID_PROGGY_CLEAN,\n    FONTID_PCMONO,\n    FONTID_CRISP,\n    FONTID_COUNT_,\n};\n\n#define         MEKA_FONT_STR_CHECKED   \"\\xC2\\x81\"  // 129 in UTF8\n#define         MEKA_FONT_STR_ARROW     \">\"         // (not using the one stored at 130)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_font\n{\n    t_font_id       id;\n    ALLEGRO_FONT *  library_data;\n    int             height;\n    const char*     text_id;\n    const char*     load_filename;\n    int             load_size;\n};\n\nextern t_font       Fonts[FONTID_COUNT_];\nextern t_font *     FontCurrent;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Fonts_Init          ();\nvoid    Fonts_Close         ();\n\n//-----------------------------------------------------------------------------\n\nvoid    Font_SetCurrent     (t_font_id font_id);\nvoid    Font_Print          (t_font_id font_id, const char *text, int x, int y, ALLEGRO_COLOR color, int wrap_width = -1);\nvoid    Font_PrintCentered  (t_font_id font_id, const char *text, int x, int y, ALLEGRO_COLOR color);\nint     Font_Height         (t_font_id font_id = FONTID_CUR);\nint     Font_TextWidth      (t_font_id font_id, const char *text, const char* text_end = NULL);\nint     Font_TextHeight     (t_font_id font_id, const char *text, int wrap_width = -1);\n\nstruct FontPrinter\n{\n    t_font_id       font_id;\n    ALLEGRO_COLOR   color;\n    \n    FontPrinter(t_font_id _font_id);\n    FontPrinter(t_font_id _font_id, ALLEGRO_COLOR _color);\n\n    void    Printf(v2i pos, const char* format, ...) const;\n};\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/fskipper.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - fskipper.c\r\n// Frame Skipper - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"fskipper.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_fskipper              fskipper;\r\nALLEGRO_TIMER*          g_timer_throttle = NULL;\r\nALLEGRO_EVENT_QUEUE*    g_timer_throttle_event_queue = NULL;\r\nALLEGRO_TIMER*          g_timer_seconds = NULL;\r\nALLEGRO_EVENT_QUEUE*    g_timer_seconds_event_queue = NULL;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Frame_Skipper_Init_Values()\r\n{\r\n    fskipper.Mode                       = FRAMESKIP_MODE_THROTTLED;\r\n    fskipper.Throttled_Speed            = 60;\r\n    fskipper.Throttled_Frame_Elapsed    = 0;\r\n    fskipper.Unthrottled_Frameskip      = 1;\r\n    fskipper.Unthrottled_Counter        = 0;\r\n    fskipper.Show_Current_Frame         = TRUE;\r\n    fskipper.FPS                        = 0.0f;\r\n    fskipper.FPS_Display                = FALSE;\r\n    fskipper.FPS_SecondsElapsed         = 0;\r\n    fskipper.FPS_FrameCountAccumulator  = 0;\r\n}\r\n\r\nvoid    Frame_Skipper_Init()\r\n{\r\n    // Throttle\r\n    g_timer_throttle = al_create_timer(1.0f/(float)fskipper.Throttled_Speed);\r\n    g_timer_throttle_event_queue = al_create_event_queue();\r\n    al_register_event_source(g_timer_throttle_event_queue, al_get_timer_event_source(g_timer_throttle));\r\n    al_start_timer(g_timer_throttle);\r\n\r\n    // FPS Counter\r\n    g_timer_seconds = al_create_timer(1.0f);\r\n    g_timer_seconds_event_queue = al_create_event_queue();\r\n    al_register_event_source(g_timer_seconds_event_queue, al_get_timer_event_source(g_timer_seconds));\r\n    al_start_timer(g_timer_seconds);\r\n}\r\n\r\nbool Frame_Skipper()\r\n{\r\n    if (fskipper.Mode == FRAMESKIP_MODE_THROTTLED)\r\n    {\r\n        // Auto frame-skipping\r\n        ALLEGRO_EVENT timer_event;\r\n        while (al_get_next_event(g_timer_throttle_event_queue, &timer_event))\r\n            if (timer_event.type == ALLEGRO_EVENT_TIMER)\r\n                fskipper.Throttled_Frame_Elapsed++;\r\n\r\n        while (fskipper.Throttled_Frame_Elapsed == 0)\r\n        {\r\n            // Blocking\r\n            al_wait_for_event(g_timer_throttle_event_queue, &timer_event);\r\n            if (timer_event.type == ALLEGRO_EVENT_TIMER)\r\n                fskipper.Throttled_Frame_Elapsed++;\r\n        }\r\n\r\n        // If retard is too high, force drawing a frame so it doesn't freeze\r\n        // It is also good since huge delay (+1/4th second) will not be catched\r\n        if (fskipper.Throttled_Frame_Elapsed > 15)\r\n        { \r\n            fskipper.Throttled_Frame_Elapsed = 1;\r\n        }\r\n\r\n        // Skip next frame if we have more than one to go (we're late)\r\n        // Else don't skip\r\n        if (fskipper.Throttled_Frame_Elapsed -- > 1)\r\n            return FALSE;\r\n    }\r\n    else\r\n    {\r\n        // Skip Standard_Counter-1 frames every Standard_Counter frames\r\n        if (fskipper.Unthrottled_Counter < fskipper.Unthrottled_Frameskip)\r\n        {\r\n            fskipper.Unthrottled_Counter ++;\r\n            return FALSE;\r\n        }\r\n        fskipper.Unthrottled_Counter = 1;\r\n    }\r\n\r\n    // Poll FPS timer \r\n    ALLEGRO_EVENT timer_event;\r\n    while (al_get_next_event(g_timer_seconds_event_queue, &timer_event))\r\n    {\r\n        switch (timer_event.type)\r\n        {\r\n        case ALLEGRO_EVENT_TIMER:\r\n            if (timer_event.timer.source == g_timer_seconds)\r\n            {\r\n                fskipper.FPS_SecondsElapsed ++;\r\n                break;\r\n            }\r\n            break;\r\n        }\r\n    }\r\n\r\n    // Compute FPS if a new second has elapsed\r\n    fskipper.FPS_FrameCountAccumulator++;\r\n    if (fskipper.FPS_SecondsElapsed > 0)\r\n    {\r\n        //int elapsed = (int)(cycle_current - fskipper.FPS_LastComputedTime);\r\n        //int fps = (fskipper.Frame_Rendered * cycle_per_second + (cycle_per_second / 2)) / elapsed;\r\n        //fskipper.FPS = fps;\r\n        //Msg(MSGT_DEBUG, \"Frame_Rendered = %d, FPS = %d\", fskipper.Frame_Rendered, fskipper.FPS);\r\n        fskipper.FPS = (float)fskipper.FPS_FrameCountAccumulator / (float)fskipper.FPS_SecondsElapsed;\r\n        fskipper.FPS_SecondsElapsed = 0;\r\n        fskipper.FPS_FrameCountAccumulator = 0;\r\n    }\r\n\r\n    // Will show next frame\r\n    return TRUE;\r\n}\r\n\r\nvoid Frame_Skipper_Switch()\r\n{\r\n    if (fskipper.Mode == FRAMESKIP_MODE_THROTTLED)\r\n    {\r\n        fskipper.Mode = FRAMESKIP_MODE_UNTHROTTLED;\r\n        fskipper.Unthrottled_Counter = 1;\r\n    }\r\n    else\r\n    {\r\n        fskipper.Mode = FRAMESKIP_MODE_THROTTLED;\r\n        fskipper.Throttled_Frame_Elapsed = 0;\r\n    }\r\n    Frame_Skipper_Show();\r\n}\r\n\r\nvoid Frame_Skipper_Configure (int v)\r\n{\r\n    switch (fskipper.Mode)\r\n    {\r\n    case FRAMESKIP_MODE_THROTTLED:\r\n        {\r\n            fskipper.Throttled_Speed += (v * 10);\r\n            fskipper.Throttled_Speed = Clamp(fskipper.Throttled_Speed, 10, 400);            // Range 10->400 Hz\r\n            al_set_timer_speed(g_timer_throttle, 1.0f/(float)fskipper.Throttled_Speed);\r\n            Sound_UpdateClockSpeed();\r\n            break;\r\n        }\r\n    case FRAMESKIP_MODE_UNTHROTTLED:\r\n        {\r\n            fskipper.Unthrottled_Frameskip += v;\r\n            fskipper.Unthrottled_Frameskip = Clamp(fskipper.Unthrottled_Frameskip, 1, 9);   // Range 1/1 to 1/9\r\n            break;\r\n        }\r\n    }\r\n    Frame_Skipper_Show();\r\n}\r\n\r\nvoid    Frame_Skipper_Show()\r\n{\r\n    if (fskipper.Mode == FRAMESKIP_MODE_THROTTLED)\r\n        Msg(MSGT_USER, Msg_Get(MSG_Frameskip_Auto), fskipper.Throttled_Speed);\r\n    else\r\n        Msg(MSGT_USER, Msg_Get(MSG_Frameskip_Standard), fskipper.Unthrottled_Frameskip);\r\n}\r\n\r\nvoid    Frame_Skipper_Switch_FPS_Counter()\r\n{\r\n    fskipper.FPS_Display = !fskipper.FPS_Display;\r\n    if (fskipper.FPS_Display)\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_FPS_Counter_Enabled));\r\n    else\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_FPS_Counter_Disabled));\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/fskipper.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - fskipper.h\n// Frame Skipper - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define FRAMESKIP_MODE_THROTTLED    (0)\n#define FRAMESKIP_MODE_UNTHROTTLED  (1)\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nbool    Frame_Skipper();\nvoid    Frame_Skipper_Configure(int v);\nvoid    Frame_Skipper_Switch();\nvoid    Frame_Skipper_Switch_FPS_Counter();\nvoid    Frame_Skipper_Show();\nvoid    Frame_Skipper_Init();\nvoid    Frame_Skipper_Init_Values();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_fskipper\n{\n    // Frame skipper\n    int             Mode;                       // Automatic (sync) or standard\n    int             Throttled_Speed;\n    volatile int    Throttled_Frame_Elapsed;\n    int             Unthrottled_Frameskip;\n    int             Unthrottled_Counter;\n    bool            Show_Current_Frame;\n\n    // FPS Counter\n    float           FPS;\n    bool            FPS_Display;\n    int             FPS_SecondsElapsed;\n    int             FPS_FrameCountAccumulator;  // Number of frames rendered (this second)\n};\n\nextern t_fskipper   fskipper;\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_action.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_action.c\r\n// Miscellaneous GUI action handlers - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: Make this code/file obsolete eventually.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"blit.h\"\r\n#include \"db.h\"\r\n#include \"video.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// ACTION: QUITTING EMULATOR --------------------------------------------------\r\n// FIXME-DEPTH: Ressources (machines, icons) not faded out\r\nvoid    Action_Quit()\r\n{\r\n    Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_Quit));\r\n\r\n    // Shut up sound while fading\r\n    Sound_Playback_Stop();\r\n\r\n    // Redraw last time, so message appears on screen\r\n    gui_redraw_everything_now_once();\r\n\r\n    /*\r\n    // Software, naive, slow fade\r\n    // Only 32-bits supported\r\n    int depth = bitmap_color_depth(gui_buffer);\r\n    switch (depth)\r\n    {\r\n    case 32:\r\n        {\r\n            while (TRUE)\r\n            {\r\n                bool more = FALSE;\r\n                int  y;\r\n                u32 **ppixels = (u32 **)&gui_buffer->line;\r\n                for (y = gui_buffer->h; y != 0; y--)\r\n                {\r\n                    u32 *pixels = *ppixels++;\r\n                    int  x;\r\n                    for (x = gui_buffer->w; x != 0; x--)\r\n                    {\r\n                        u32 c = *pixels;\r\n                        int r = c & 0x000000FF;\r\n                        int g = c & 0x0000FF00;\r\n                        int b = c & 0x00FF0000;\r\n                        int loop;\r\n                        for (loop = 3; loop != 0; loop--)\r\n                        {\r\n                            if (r != 0) r -= 0x000001;\r\n                            if (g != 0) g -= 0x000100;\r\n                            if (b != 0) b -= 0x010000;\r\n                        }\r\n                        c = r | g | b;\r\n                        if (c != 0)\r\n                            more = TRUE;\r\n                        *pixels++ = c;\r\n                    }\r\n                }\r\n                Blit_GUI();\r\n                if (!more)\r\n                    break;\r\n            }\r\n        } // 32\r\n    }\r\n    */\r\n\r\n    // Switch to full black skin\r\n    //Skins_Select(Skins_GetSystemSkinBlack(), TRUE);\r\n    //Skins_QuitAfterFade();\r\n    opt.Force_Quit = TRUE;\r\n}\r\n\r\n// ACTION: SHOW OR HIDE SPRITES LAYER -----------------------------------------------\r\nvoid    Action_Switch_Layer_Sprites()\r\n{\r\n    opt.Layer_Mask ^= LAYER_SPRITES;\r\n    gui_menu_toggle_check (menus_ID.layers, 0);\r\n    if (opt.Layer_Mask & LAYER_SPRITES)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Layer_Spr_Enabled));\r\n    }\r\n    else\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Layer_Spr_Disabled));\r\n    }\r\n}\r\n\r\n// ACTION: SHOW OR HIDE BACKGROUND LAYER --------------------------------------\r\nvoid    Action_Switch_Layer_Background()\r\n{\r\n    opt.Layer_Mask ^= LAYER_BACKGROUND;\r\n    gui_menu_toggle_check (menus_ID.layers, 1);\r\n    if (opt.Layer_Mask & LAYER_BACKGROUND)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Layer_BG_Enabled));\r\n    }\r\n    else\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Layer_BG_Disabled));\r\n    }\r\n}\r\n\r\n// ACTION: SWITCH SPRITE FLICKERING TO 'AUTOMATIC' ----------------------------\r\nvoid    Action_Switch_Flickering_Auto()\r\n{\r\n    g_config.sprite_flickering = SPRITE_FLICKERING_AUTO;\r\n    if (DB.current_entry && (DB.current_entry->flags & DB_FLAG_EMU_SPRITE_FLICKER))\r\n        g_config.sprite_flickering |= SPRITE_FLICKERING_ENABLED;\r\n    gui_menu_uncheck_all (menus_ID.flickering);\r\n    gui_menu_check (menus_ID.flickering, 0);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Flickering_Auto));\r\n}\r\n\r\n// ACTION: SWITCH SPRITE FLICKERING TO 'TRUE' ----------------------------------\r\nvoid    Action_Switch_Flickering_Yes()\r\n{\r\n    g_config.sprite_flickering = SPRITE_FLICKERING_ENABLED;\r\n    gui_menu_uncheck_all (menus_ID.flickering);\r\n    gui_menu_check (menus_ID.flickering, 1);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Flickering_Yes));\r\n}\r\n\r\n// ACTION: SWITCH SPRITE FLICKERING TO 'FALSE' -----------------------------------\r\nvoid    Action_Switch_Flickering_No()\r\n{\r\n    g_config.sprite_flickering = SPRITE_FLICKERING_NO;\r\n    gui_menu_uncheck_all (menus_ID.flickering);\r\n    gui_menu_check (menus_ID.flickering, 2);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Flickering_No));\r\n}\r\n\r\n// ACTION: SWITCH BETWEEN FULLSCREEN AND INTERFACE MODES ----------------------\r\nvoid    Action_Switch_Mode()\r\n{\r\n    switch (g_env.state)\r\n    {\r\n    case MEKA_STATE_GAME: g_env.state = MEKA_STATE_GUI;  break;\r\n    case MEKA_STATE_GUI:  g_env.state = MEKA_STATE_GAME; break;\r\n    default:\r\n        // FIXME: Should not happen\r\n        break;\r\n    }\r\n\r\n    Sound_Playback_Mute();\r\n    Video_Setup_State();\r\n    Sound_Playback_Resume();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/g_action.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_action.h\r\n// Miscellaneous GUI action handlers - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Action_Quit();\r\nvoid    Action_Switch_Mode();\r\n\r\nvoid    Action_Switch_Layer_Sprites();\r\nvoid    Action_Switch_Layer_Background();\r\n\r\nvoid    Action_Switch_Flickering_Auto();\r\nvoid    Action_Switch_Flickering_Yes();\r\nvoid    Action_Switch_Flickering_No();\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/g_box.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_box.c\r\n// GUI Boxes - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"desktop.h\"\r\n#include \"g_widget.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions (anything in this file is particularly bad code)\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    gui_update_boxes()\r\n{\r\n    if (gui.mouse.focus == GUI_FOCUS_DESKTOP || gui.mouse.focus == GUI_FOCUS_MENUS)\r\n        return;\r\n\r\n    // Update widgets, and find on which box the mouse cursor is\r\n    t_gui_box * b_hover = NULL;\r\n    bool no_widgets = false;\r\n    bool do_move = false;\r\n    bool do_resize = false;\r\n\r\n    for (int i = 0; i < gui.boxes_count; i++)\r\n    {\r\n        t_gui_box* b = gui.boxes_z_ordered[i];\r\n        if (!(b->flags & GUI_BOX_FLAGS_ACTIVE))\r\n            continue;\r\n\r\n        const int mouse_x = gui.mouse.x - b->frame.pos.x;\r\n        const int mouse_y = gui.mouse.y - b->frame.pos.y;\r\n        no_widgets = !widgets_update_box(b, mouse_x, mouse_y);\r\n\r\n        if (b_hover == NULL)\r\n        {\r\n            // FIXME-FOCUS\r\n            // Already has focus?\r\n            if ((gui.mouse.focus == GUI_FOCUS_BOX && gui.mouse.focus_box == b) && (gui.mouse.buttons & 1))\r\n            {\r\n                b_hover = b;\r\n                do_move = gui.mouse.focus_is_resizing == false;\r\n                do_resize = gui.mouse.focus_is_resizing == true;\r\n                break;\r\n            }\r\n\r\n            const bool hovering_window = gui_is_mouse_hovering_area(b->frame.pos.x - 2, b->frame.pos.y - 20, b->frame.pos.x + b->frame.size.x + 2, b->frame.pos.y + b->frame.size.y + 2);\r\n            if (hovering_window)\r\n            {\r\n                do_move = true;\r\n                if ((b->flags & GUI_BOX_FLAGS_ALLOW_RESIZE) != 0)\r\n                {\r\n                    t_frame resize_bb;\r\n                    resize_bb.pos.x = b->frame.pos.x + b->frame.size.x - 12;\r\n                    resize_bb.pos.y = b->frame.pos.y + b->frame.size.y - 12;\r\n                    resize_bb.size.x = resize_bb.size.y = 14;\r\n                    if (gui_is_mouse_hovering_area(&resize_bb))\r\n                    {\r\n                        do_move = false;\r\n                        do_resize = true;\r\n                    }\r\n                }\r\n\r\n                // When using light phaser, paddle control, graphic board, etc. which require\r\n                if (b->type == GUI_BOX_TYPE_GAME && Inputs.Peripheral[0] != INPUT_JOYPAD)\r\n                    if (gui_is_mouse_hovering_area(&b->frame))\r\n                        do_move = do_resize = false;\r\n\r\n                b_hover = b;\r\n                break;\r\n            }\r\n        }\r\n    }\r\n    if (b_hover == NULL)\r\n    {\r\n        // FIXME-FOCUS\r\n        //if ((gui.mouse.buttons) && (gui_mouse.pressed_on == PRESSED_ON_NOTHING))\r\n        //    gui_mouse.pressed_on = PRESSED_ON_DESKTOP;\r\n        if ((gui.mouse.buttons) && (gui.mouse.focus == GUI_FOCUS_NONE))\r\n        {\r\n            gui.mouse.focus = GUI_FOCUS_DESKTOP;\r\n            gui.mouse.focus_box = NULL;\r\n            gui.mouse.focus_widget = NULL;\r\n        }\r\n        return;\r\n    }\r\n\r\n    // FIXME-FOCUS\r\n    //if ((gui_mouse.on_box != NULL) && (gui_mouse.on_box != b_hover))\r\n    if (gui.mouse.focus == GUI_FOCUS_BOX && gui.mouse.focus_box != b_hover)\r\n        return;\r\n\r\n    /*\r\n    will_move = TRUE;\r\n    if ((b->n_widgets > 0) && (gui_mouse.pressed_on != PRESSED_ON_BOX))\r\n        will_move = !widgets_update_box(b, cx, cy);\r\n    */\r\n\r\n    if ((gui.mouse.buttons & 1) == 0)\r\n        return;\r\n\r\n    // Focus\r\n    //gui_mouse.on_box = b;\r\n    t_gui_box* b;\r\n    if (gui.mouse.focus == GUI_FOCUS_BOX || gui.mouse.focus == GUI_FOCUS_WIDGET)\r\n        b = gui.mouse.focus_box;\r\n    else\r\n        b = b_hover;\r\n\r\n    gui_box_set_focus(b);\r\n\r\n    // Move/resize\r\n    if ((do_move || do_resize) && (gui.mouse.focus != GUI_FOCUS_WIDGET) && (gui.mouse.buttons & 1))\r\n    {\r\n        // FIXME-FOCUS\r\n        //if (gui_mouse.pressed_on != PRESSED_ON_BOX)\r\n        if (gui.mouse.focus != GUI_FOCUS_BOX)\r\n        {\r\n            // FIXME-FOCUS\r\n            //gui_mouse.pressed_on = PRESSED_ON_BOX;\r\n            gui.mouse.focus = GUI_FOCUS_BOX;\r\n            gui.mouse.focus_box = b;\r\n            gui.mouse.focus_widget = NULL;\r\n            gui.mouse.focus_is_resizing = do_resize ? true : false;\r\n            gui.mouse.focus_pivot.x = gui.mouse.x - b->frame.pos.x;\r\n            gui.mouse.focus_pivot.y = gui.mouse.y - b->frame.pos.y;\r\n            if (gui.mouse.focus_is_resizing)\r\n            {\r\n                // Lower-right pivot for resizing\r\n                gui.mouse.focus_pivot.x -= b->frame.size.x;\r\n                gui.mouse.focus_pivot.y -= b->frame.size.y;\r\n            }\r\n        }\r\n\r\n        assert((t_gui_box*)gui.mouse.focus_box == b);\r\n\r\n        // Mouse moves box\r\n        // FIXME: rewrite this embarrassing 1998 code into something decent\r\n        if (gui.mouse.focus_is_resizing)\r\n        {\r\n            // Resize\r\n            const int sx = (gui.mouse.x - gui.mouse.focus_pivot.x) - b->frame.pos.x;\r\n            const int sy = (gui.mouse.y - gui.mouse.focus_pivot.y) - b->frame.pos.y;\r\n            gui_box_resize(b, sx, sy, true);\r\n        }\r\n        else\r\n        {\r\n            // Move\r\n            const int mx = (gui.mouse.x - gui.mouse.focus_pivot.x) - b->frame.pos.x;\r\n            const int my = (gui.mouse.y - gui.mouse.focus_pivot.y) - b->frame.pos.y;\r\n\r\n            if (mx || my)\r\n            {\r\n                int ax1, ay1, ax2, ay2;\r\n                int bx1, by1, bx2, by2;\r\n                if (mx >= 0)\r\n                {\r\n                    ax1 = b->frame.pos.x  -2;\r\n                    ay1 = b->frame.pos.y - 20;\r\n\r\n                    if (my >= 0)\r\n                    { // mx > 0 - my > 0\r\n                        ax2 = b->frame.pos.x + b->frame.size.x + 1                    +  2 ;\r\n                        ay2 = b->frame.pos.y + MIN(b->frame.size.y + 22, my) + 1    - 20 ;\r\n\r\n                        bx1 = b->frame.pos.x                                          -  2 ;\r\n                        by1 = b->frame.pos.y + MIN(b->frame.size.y + 22, my) + 1    - 20 ;\r\n                        bx2 = b->frame.pos.x + MIN(b->frame.size.x, mx) + 1         +  2 ;\r\n                        by2 = b->frame.pos.y + b->frame.size.y + 1                    +  2 ;\r\n                    }\r\n                    else\r\n                    { // mx > 0 - my < 0\r\n                        ax2 = b->frame.pos.x + MIN(b->frame.size.x, mx) + 1         +  2 ;\r\n                        ay2 = b->frame.pos.y + b->frame.size.y - MIN(b->frame.size.y + 22, -my)  +  2 ;\r\n\r\n                        bx1 = b->frame.pos.x                                          -  2 ;\r\n                        by1 = b->frame.pos.y + b->frame.size.y - MIN(b->frame.size.y + 22, -my)  +  2 ;\r\n                        bx2 = b->frame.pos.x + b->frame.size.x + 1                    +  2 ;\r\n                        by2 = b->frame.pos.y + b->frame.size.y + 1                    +  2 ;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    if (my >= 0)\r\n                    { // mx < 0 - my > 0\r\n                        ax1 = b->frame.pos.x -  2 ;\r\n                        ay1 = b->frame.pos.y - 20 ;\r\n                        ax2 = b->frame.pos.x + b->frame.size.x + 1                    +  2 ;\r\n                        ay2 = b->frame.pos.y + MIN(b->frame.size.y + 22, my) + 1    - 20 ;\r\n\r\n                        bx1 = b->frame.pos.x + b->frame.size.x - MIN(b->frame.size.x, -mx)       -  2 ;\r\n                        by1 = b->frame.pos.y + MIN(b->frame.size.y + 22, my) + 1    - 20 ;\r\n                        bx2 = b->frame.pos.x + b->frame.size.x + 1                    +  2 ;\r\n                        by2 = b->frame.pos.y + b->frame.size.y + 1                    +  2 ;\r\n                    }\r\n                    else\r\n                    { // mx < 0 - my < 0\r\n                        ax1 = b->frame.pos.x + b->frame.size.x - MIN(b->frame.size.x, -mx)       -  2 ;\r\n                        ax2 = b->frame.pos.x + b->frame.size.x + 1                    +  2 ;\r\n                        ay1 = b->frame.pos.y                                          - 20 ;\r\n                        ay2 = b->frame.pos.y + b->frame.size.y - MIN(b->frame.size.y + 22, -my)  +  2 ;\r\n\r\n                        bx1 = b->frame.pos.x                                   -  2 ;\r\n                        by1 = b->frame.pos.y + b->frame.size.y - MIN(b->frame.size.y + 22, -my)  +  2 ;\r\n                        bx2 = b->frame.pos.x + b->frame.size.x + 1                       +  2 ;\r\n                        by2 = b->frame.pos.y + b->frame.size.y + 1                       +  2 ;\r\n                    }\r\n                }\r\n\r\n                al_set_target_bitmap(gui_buffer);\r\n                al_draw_bitmap_region(gui_background, ax1, ay1, ax2 - ax1, ay2 - ay1, ax1, ay1, 0x0000);\r\n                al_draw_bitmap_region(gui_background, bx1, by1, bx2 - bx1, by2 - by1, bx1, by1, 0x0000);\r\n\r\n                // Update position\r\n                b->frame.pos.x += mx;\r\n                b->frame.pos.y += my;\r\n                gui_box_clip_position(b);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nt_gui_box * gui_box_new(const t_frame *frame, const char *title)\r\n{\r\n    assert(frame->size.x > 0 && frame->size.y > 0);\r\n\r\n    // Allocate new box\r\n    t_gui_box* box = (t_gui_box *)malloc(sizeof (t_gui_box));\r\n    assert(box != NULL);\r\n\r\n    // Setup members\r\n    box->frame      = *frame;\r\n    box->title      = strdup(title);\r\n    box->type       = GUI_BOX_TYPE_STANDARD;\r\n    box->flags      = GUI_BOX_FLAGS_ACTIVE | GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    box->gfx_buffer = NULL;\r\n    gui_box_create_video_buffer(box);\r\n    box->widgets    = NULL;\r\n    box->size_min.Set(32,32);\r\n    box->size_max.Set(10000,10000);\r\n    box->size_step.Set(1,1);\r\n    box->size_fixed_ratio = false;\r\n    box->user_data  = NULL;\r\n    box->update     = NULL;\r\n    box->destroy    = NULL;\r\n\r\n    // Clear GFX buffer\r\n    al_set_target_bitmap(box->gfx_buffer);\r\n    //clear_to_color(box->gfx_buffer, COLOR_SKIN_WINDOW_BACKGROUND);\r\n    al_clear_to_color(al_map_rgb_f(1.0f, 0.0f, 1.0f));\r\n\r\n    // Setup GUI global data\r\n    list_add(&gui.boxes, box);\r\n    gui.boxes_z_ordered[gui.boxes_count] = box;\r\n    gui.boxes_count++;\r\n    gui.info.must_redraw = true;\r\n\r\n    // Set focus\r\n    // Note: be sure to call this after gui.box_last++\r\n    gui_box_set_focus(box);\r\n    gui_box_clip_position(box);\r\n\r\n    return (box);\r\n}\r\n\r\nvoid    gui_box_destroy_video_buffer(t_gui_box* box)\r\n{\r\n    al_destroy_bitmap(box->gfx_buffer);\r\n    box->gfx_buffer = NULL;\r\n}\r\n\r\nvoid    gui_box_create_video_buffer(t_gui_box *box)\r\n{\r\n    int sx, sy;\r\n    if (box->gfx_buffer)\r\n    {\r\n        // Reuse previous bitmap size over the size stored in box.\r\n        // Because current resizing system keeps largest size gfx_buffer so size stored in box may be smaller\r\n        // (as used by Tilemap Viewer, but we may switch to properly recreating the video buffer)\r\n        sx = al_get_bitmap_width(box->gfx_buffer);\r\n        sy = al_get_bitmap_height(box->gfx_buffer);\r\n        gui_box_destroy_video_buffer(box);\r\n    }\r\n    else\r\n    {\r\n        sx = box->frame.size.x+1;\r\n        sy = box->frame.size.y+1;\r\n    }\r\n\r\n    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);\r\n    al_set_new_bitmap_format(g_config.video_gui_format_request);\r\n    box->gfx_buffer = al_create_bitmap(box->frame.size.x+1, box->frame.size.y+1);\r\n    assert(box->gfx_buffer);\r\n\r\n    // Redraw and layout all\r\n    box->flags |= GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n}\r\n\r\nvoid    gui_box_destroy_widgets(t_gui_box* box)\r\n{\r\n    list_free_custom(&box->widgets, (t_list_free_handler)widget_destroy);\r\n}\r\n\r\nvoid    gui_box_delete(t_gui_box *box)\r\n{\r\n    // Destroy applet callback\r\n    if (box->destroy != NULL)\r\n        box->destroy(box->user_data);\r\n\r\n    // Remove from lists\r\n    list_remove(&gui.boxes, box);\r\n    for (int i = 0; i < gui.boxes_count; i++)\r\n    {\r\n        if (gui.boxes_z_ordered[i] == box)\r\n        {\r\n            for (; i < gui.boxes_count - 1; i++)\r\n                gui.boxes_z_ordered[i] = gui.boxes_z_ordered[i + 1];\r\n            break;\r\n        }\r\n    }\r\n    gui.boxes_z_ordered[gui.boxes_count - 1] = NULL;\r\n    gui.boxes_count--;\r\n\r\n    // Delete widgets\r\n    list_free_custom(&box->widgets, (t_list_free_handler)widget_destroy);\r\n\r\n    // Delete\r\n    al_destroy_bitmap(box->gfx_buffer);\r\n    box->gfx_buffer = NULL;\r\n    free(box->title);\r\n    box->title = NULL;\r\n    free(box);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// gui_box_show (t_gui_box *box, bool enable, bool focus)\r\n// Enable/disable given box\r\n//-----------------------------------------------------------------------------\r\nvoid            gui_box_show(t_gui_box *box, bool enable, bool focus)\r\n{\r\n    if (enable)\r\n    {\r\n        // Show box\r\n        box->flags |= GUI_BOX_FLAGS_ACTIVE;\r\n\r\n        // Set focus\r\n        if (focus)\r\n            gui_box_set_focus(box);\r\n    }\r\n    else\r\n    {\r\n        // Hide box\r\n        box->flags &= ~GUI_BOX_FLAGS_ACTIVE;\r\n\r\n        // If this box had the focus, let give focus to the following one\r\n        if (focus && gui_box_has_focus(box))\r\n        {\r\n            for (int n = 1; n < gui.boxes_count; n++)\r\n            {\r\n                t_gui_box * box_behind = gui.boxes_z_ordered[n];\r\n                if (box_behind->flags & GUI_BOX_FLAGS_ACTIVE)\r\n                {\r\n                    gui_box_set_focus(box_behind);\r\n                    break;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    // Set global redraw flag\r\n    gui.info.must_redraw = TRUE;\r\n}\r\n\r\nint     gui_box_find_z(const t_gui_box* box)\r\n{\r\n    for (int i = 0; i < gui.boxes_count; i++)\r\n    {\r\n        if (gui.boxes_z_ordered[i] == box)\r\n            return i;\r\n    }\r\n    return -1;\r\n}\r\n\r\n// Set focus to given box\r\n// FIXME: ARGH!\r\nvoid    gui_box_set_focus(t_gui_box *box)\r\n{\r\n    if (gui_box_has_focus(box))\r\n        return;\r\n\r\n    // Shift\r\n    t_gui_box* box_prev = box;\r\n    for (int i = 0; i != gui.boxes_count; i++)\r\n    {\r\n        t_gui_box *box_curr = gui.boxes_z_ordered[i];\r\n        gui.boxes_z_ordered[i] = box_prev;\r\n        if (box_curr == box)\r\n            break;\r\n        box_prev = box_curr;\r\n    }\r\n\r\n    /*\r\n    t_gui_box * box_current_focus;\r\n    int         i;\r\n    int         box_plan;\r\n\r\n    box_plan = -1;\r\n    for (i = 0; i < gui.box_last; i++)\r\n        if (gui.box[gui.box_plan[i]] == box)\r\n        {\r\n            box_plan = i;\r\n            break;\r\n        }\r\n\r\n    box_plan = gui_box_find_plan (box);\r\n    box_current_focus = gui.box_z_ordered[0];\r\n    if (box_current_focus == box)\r\n        return;\r\n\r\n    // Shift plan/z buffer by one\r\n    for (i = box_plan; i > 0; i--)\r\n        gui.box_plan[i] = gui.box_plan[i - 1];\r\n    gui.box_plan[0] = box->stupid_id;\r\n    */\r\n}\r\n\r\n// Return whether given box has the focus\r\nint     gui_box_has_focus(t_gui_box *box)\r\n{\r\n    return (gui.boxes_z_ordered[0] == box);\r\n}\r\n\r\n// Set title of given box\r\nvoid    gui_box_set_title(t_gui_box *box, const char *title)\r\n{\r\n    free(box->title);\r\n    box->title = strdup(title);\r\n}\r\n\r\nvoid    gui_box_resize(t_gui_box *box, int size_x, int size_y, bool interactive)\r\n{\r\n    size_x = Clamp<int>(size_x, box->size_min.x, box->size_max.x);\r\n    size_y = Clamp<int>(size_y, box->size_min.y, box->size_max.y);\r\n\r\n    if (box->size_step.x != 1 || box->size_step.y != 1)\r\n    {\r\n        float inc_ratio_x = (0.49f + (float)((size_x - (box->size_min.x-1))) / box->size_step.x);\r\n        float inc_ratio_y = (0.49f + (float)((size_y - (box->size_min.y-1))) / box->size_step.y);\r\n\r\n        if (box->size_fixed_ratio)\r\n            inc_ratio_x = inc_ratio_y = MIN(inc_ratio_x, inc_ratio_y);\r\n        size_x = box->size_min.x + (int)inc_ratio_x * box->size_step.x;\r\n        size_y = box->size_min.y + (int)inc_ratio_y * box->size_step.y;\r\n    }\r\n\r\n    if (box->size_fixed_ratio && interactive)\r\n    {\r\n        const float scale = (size_x+1) / (float)g_driver->x_res;\r\n        Msg(MSGT_STATUS_BAR, Msg_Get(MSG_Options_GUI_GameWindowScale), (int)(scale*100));\r\n    }\r\n\r\n    if (box->frame.size.x == size_x && box->frame.size.y == size_y)\r\n        return;\r\n\r\n    box->frame.size.x = size_x;\r\n    box->frame.size.y = size_y;\r\n\r\n    if (box->size_fixed_ratio)\r\n        g_config.game_window_scale = (size_x+1) / (float)g_driver->x_res;\r\n\r\n    gui_box_create_video_buffer(box);\r\n    gui.info.must_redraw = true;\r\n\r\n}\r\n\r\n// Clip position of given box so that it shows on desktop.\r\nvoid    gui_box_clip_position(t_gui_box *box)\r\n{\r\n    if (box->frame.pos.x < gui.info.screen_pad.x - box->frame.size.x)\r\n        box->frame.pos.x = (gui.info.screen_pad.x - box->frame.size.x);\r\n    if (box->frame.pos.x > gui.info.screen.x - gui.info.screen_pad.x)\r\n        box->frame.pos.x = (gui.info.screen.x - gui.info.screen_pad.x);\r\n    if (box->frame.pos.y < gui.info.screen_pad.y - box->frame.size.y + gui.info.bars_height)\r\n        box->frame.pos.y = (gui.info.screen_pad.y - box->frame.size.y + gui.info.bars_height);\r\n    if (box->frame.pos.y > gui.info.screen.y - gui.info.screen_pad.y - gui.info.bars_height)\r\n        box->frame.pos.y = (gui.info.screen.y - gui.info.screen_pad.y - gui.info.bars_height);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/g_box.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_box.h\n// GUI Boxes - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nt_gui_box *     gui_box_new(const t_frame* frame, const char* title);\nvoid            gui_box_destroy_widgets(t_gui_box* box);\nvoid            gui_box_delete(t_gui_box* box);\nvoid            gui_box_create_video_buffer(t_gui_box* box);\nvoid            gui_box_destroy_video_buffer(t_gui_box* box);\nvoid            gui_box_resize(t_gui_box* box, int size_x, int size_y, bool interactive);\n\nint             gui_box_find_z(const t_gui_box* box);\n\n//-----------------------------------------------------------------------------\n// Functions / Make obsolete\n//-----------------------------------------------------------------------------\n\nvoid    gui_update_boxes        ();\n\nvoid    gui_box_show            (t_gui_box *box, bool enable, bool focus);\nvoid    gui_box_set_focus       (t_gui_box *box);\nint     gui_box_has_focus       (t_gui_box *box);\nvoid    gui_box_set_title       (t_gui_box *box, const char *title);\n\nvoid    gui_box_clip_position   (t_gui_box *box);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_init.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_init.c\n// GUI Initialization - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"app_about.h\"\n#include \"app_cheatfinder.h\"\n#include \"app_filebrowser.h\"\n#include \"app_game.h\"\n#include \"app_mapview.h\"\n#include \"app_memview.h\"\n#include \"app_palview.h\"\n#include \"app_options.h\"\n#include \"app_techinfo.h\"\n#include \"app_textview.h\"\n#include \"app_tileview.h\"\n#include \"datadump.h\"\n#include \"debugger.h\"\n#include \"desktop.h\"\n#include \"inputs_c.h\"\n#include \"skin_bg.h\"\n#include \"skin_fx.h\"\n#include \"textbox.h\"\n\n//-----------------------------------------------------------------------------\n// Forward Declaration\n//-----------------------------------------------------------------------------\n\nstatic void    GUI_InitApplets();\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    GUI_Init()\n{\n    opt.GUI_Inited = TRUE;\n\n    gui_buffer = NULL;\n    gui_background = NULL;\n\n    gui.info.screen_pad.x = 2;\n    gui.info.screen_pad.y = 2;\n    gui.info.bars_height = Font_Height((t_font_id)g_config.font_menus)+3;\n    gui.info.grid_distance = 32;\n\n    gui.boxes = NULL;\n    gui.boxes_count = 0;\n\n    gui.info.screen.x = g_config.video_mode_gui_res_x;\n    gui.info.screen.y = g_config.video_mode_gui_res_y;\n    GUI_CreateVideoBuffers();\n\n    Desktop_Init();\n\n    // Create game box (create before applets so it gets focus by default when there's no .dsk file)\n    static bool active_dummy = TRUE;\n    gamebox_instance = gamebox_create(163, 151);\n    Desktop_Register_Box(\"GAME\", gamebox_instance, 1, &active_dummy);\n\n    GUI_InitApplets();\n    SkinFx_Init();\n\n    Desktop_SetStateToBoxes();     // Set all boxes state based on MEKA.DSK data\n    gui_menus_init();              // Create menus (Note: need to be done after Desktop_SetStateToBoxes because it uses the 'active' flags to check items)\n    gui_init_mouse();\n}\n\nvoid    GUI_SetupNewVideoMode()\n{\n    gui.info.must_redraw = TRUE;\n    gui.info.screen.x = g_config.video_mode_gui_res_x;\n    gui.info.screen.y = g_config.video_mode_gui_res_y;\n    GUI_CreateVideoBuffers();\n\n    Skins_StartupFadeIn();\n\n    // Fix windows position\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\n    {\n        t_gui_box* box = (t_gui_box*)boxes->elem;;\n        gui_box_clip_position(box);\n    }\n}\n\nvoid    GUI_DestroyVideoBuffers()\n{\n    if (gui_buffer != NULL)\n    {\n        al_destroy_bitmap(gui_buffer);\n        gui_buffer = NULL;\n        assert(gui_background != NULL);\n        al_destroy_bitmap(gui_background);\n        gui_background = NULL;\n    }\n\n    // Recreate existing windows buffers\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\n    {\n        t_gui_box* box = (t_gui_box*)boxes->elem;;\n        gui_box_destroy_video_buffer(box);\n    }\n}\n\nvoid    GUI_CreateVideoBuffers()\n{\n    GUI_DestroyVideoBuffers();\n\n    // Setup buffers\n    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);\n    al_set_new_bitmap_format(g_config.video_gui_format_request);\n    gui_buffer = al_create_bitmap(gui.info.screen.x, gui.info.screen.x);\n    al_set_target_bitmap(gui_buffer);\n    al_clear_to_color(COLOR_BLACK);\n    g_gui_buffer_format = al_get_bitmap_format(gui_buffer);\n\n    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);\n    al_set_new_bitmap_format(g_config.video_gui_format_request);\n    gui_background = al_create_bitmap(gui.info.screen.x, gui.info.screen.x);\n\n    Skins_Background_Redraw();\n\n    // Recreate existing windows buffers\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\n    {\n        t_gui_box* box = (t_gui_box*)boxes->elem;;\n        gui_box_create_video_buffer(box);\n    }\n}\n\nvoid    GUI_Close()\n{\n    // FIXME: Nice....\n\n    TextViewer_Close(&TextViewer);\n}\n\nvoid    GUI_InitApplets()\n{\n    AboutBox_Init();\n    TB_Message_Init();\n    MemoryViewer_MainInstance = MemoryViewer_New(TRUE, -1, -1);\n    TilemapViewer_MainInstance = TilemapViewer_New(TRUE);\n    g_CheatFinder_MainInstance = CheatFinder_New(TRUE);\n\n    // Text Viewer\n    TextViewer_Init(&TextViewer);\n    // FIXME: save current file in meka.cfg\n    if (TextViewer_Open(&TextViewer, Msg_Get(MSG_Doc_BoxTitle), g_env.Paths.DocumentationMain) != MEKA_ERR_OK)\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Doc_File_Error));\n    TextViewer.current_file = 0; // FIXME: Remove this field\n\n    TechInfo_Init();\n    TileViewer_Init();\n    PaletteViewer_Init();\n    // FM_Editor_Init();\n    FB_Init();\n    Options_Init_Applet();\n    Inputs_CFG_Init_Applet();\n\n#ifdef SOUND_DEBUG_APPLET\n    SoundDebugApp_Init();\n#endif\n\n    // Debugger\n    #ifdef MEKA_Z80_DEBUGGER\n    Debugger_Enable();\n    Debugger_Init();\n    DataDump_Init();\n    #endif\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/g_init.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_init.h\n// GUI Initialization - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    GUI_Init();\nvoid    GUI_Close();\n\nvoid    GUI_SetupNewVideoMode();\nvoid    GUI_CreateVideoBuffers();\nvoid    GUI_DestroyVideoBuffers();\n\n//-----------------------------------------------------------------------------\n\n\n"
  },
  {
    "path": "meka/srcs/g_menu.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_menu.c\r\n// GUI Menus - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: This API is absolute crap. Redo from stratch (see WIP in g_menu.h)\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"fskipper.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_gui_status_bar    g_gui_status;\r\nt_gui_menus_id      menus_ID;\r\ngui_type_menus_opt  menus_opt;\r\nt_menu *            menus[MAX_MENUS];\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid        gui_redraw_bars()\r\n{\r\n    // Redraw status bar\r\n    al_set_target_bitmap(gui_buffer);\r\n    al_draw_filled_rectangle(0, g_config.video_mode_gui_res_y - gui.info.bars_height,     g_config.video_mode_gui_res_x+1, g_config.video_mode_gui_res_y + 1, COLOR_SKIN_WIDGET_STATUSBAR_BACKGROUND);\r\n    al_draw_filled_rectangle(0, g_config.video_mode_gui_res_y - gui.info.bars_height - 2, g_config.video_mode_gui_res_x+1, g_config.video_mode_gui_res_y - gui.info.bars_height, COLOR_SKIN_WIDGET_STATUSBAR_BORDER);\r\n\r\n    t_font_id font_id = (t_font_id)g_config.font_menus;\r\n\r\n    // Show status bar message\r\n    if (g_gui_status.timeleft)\r\n    {\r\n        Font_Print(font_id, g_gui_status.message, g_gui_status.x, g_config.video_mode_gui_res_y - 16, COLOR_SKIN_WIDGET_STATUSBAR_TEXT);\r\n        g_gui_status.timeleft --;\r\n    }\r\n\r\n    // Show FPS counter\r\n    if (fskipper.FPS_Display)\r\n    {\r\n        char s[16];\r\n        sprintf(s, \"%.1f FPS\", fskipper.FPS);\r\n        Font_Print(font_id, s, g_config.video_mode_gui_res_x - 100 - Font_TextWidth(FONTID_CUR, s), g_config.video_mode_gui_res_y - 16, COLOR_SKIN_WIDGET_STATUSBAR_TEXT);\r\n    }\r\n\r\n    // Show current time\r\n    char s[16];\r\n    meka_time_getf(s);\r\n    Font_Print(font_id, s, g_config.video_mode_gui_res_x - 10 - Font_TextWidth(FONTID_CUR, s), g_config.video_mode_gui_res_y - 16, COLOR_SKIN_WIDGET_STATUSBAR_TEXT);\r\n}\r\n\r\nvoid            gui_update_menu (int n_menu, int n_parent, int n_parent_entry, int generation)\r\n{\r\n    int            i;\r\n    int            x1, y1, x2, y2;\r\n    t_menu * menu = menus[n_menu];\r\n\r\n    //if ((gui_mouse.pressed_on != PRESSED_ON_NOTHING) && (gui_mouse.pressed_on != PRESSED_ON_MENUS))\r\n    // FIXME-FOCUS\r\n    if (gui.mouse.focus != GUI_FOCUS_NONE && gui.mouse.focus != GUI_FOCUS_MENUS)\r\n    {\r\n        return;\r\n    }\r\n\r\n    menu->generation = generation;\r\n\r\n    for (i = 0; i < menu->n_entry; i ++)\r\n    {\r\n        t_menu_item *menu_entry = menu->entry[i];\r\n        if (!(menu_entry->flags & MENU_ITEM_FLAG_ACTIVE))\r\n        {\r\n            continue;\r\n        }\r\n        gui_menu_return_entry_pos (n_menu, i, &x1, &y1, &x2, &y2);\r\n\r\n        // ---\r\n        if (gui_is_mouse_hovering_area(x1, y1, x2, y2))\r\n        {\r\n            if ((!gui.mouse.buttons) && (gui.mouse.buttons_prev & 1))\r\n            {\r\n                if (menu_entry->type == MENU_ITEM_TYPE_CALLBACK)\r\n                {\r\n                    // Setup event structure\r\n                    t_menu_event event;\r\n                    event.menu          = menu;\r\n                    event.menu_idx      = n_menu;\r\n                    event.menu_item     = menu_entry;\r\n                    event.menu_item_idx = i;\r\n                    event.user_data     = menu_entry->user_data;\r\n\r\n                    gui_menu_un_mouse_over(menus_ID.root);\r\n\r\n                    // Call event handler\r\n                    menu_entry->callback(&event);\r\n                }\r\n            }\r\n            if (gui.mouse.buttons & 1)\r\n            {\r\n                if (!((menus_opt.c_menu == n_menu) && (menus_opt.c_entry == i)))\r\n                {\r\n                    if (menus_opt.c_generation > generation)\r\n                        menu_entry->mouse_over = false;\r\n                    menus_opt.c_menu = n_menu;\r\n                    menus_opt.c_entry = i;\r\n                    menus_opt.c_somewhere = 1;\r\n                    menus_opt.c_generation = generation;\r\n                    if (menu_entry->mouse_over == false)\r\n                    {\r\n                        gui_menu_un_mouse_over (n_menu);\r\n                        menu_entry->mouse_over = true;\r\n                    }\r\n                    else\r\n                    {\r\n                        if (menu_entry->type == MENU_ITEM_TYPE_SUB_MENU)\r\n                        {\r\n                            gui_menu_un_mouse_over (menu->entry[i]->submenu_id);\r\n                        }\r\n                        menu_entry->mouse_over = false;\r\n                        gui.info.must_redraw = TRUE;\r\n                    }\r\n\r\n                    // FIXME-FOCUS\r\n                    //gui_mouse.pressed_on = PRESSED_ON_MENUS;\r\n                    gui.mouse.focus = GUI_FOCUS_MENUS;\r\n                    gui.mouse.focus_box = NULL;\r\n                    gui.mouse.focus_widget = NULL;\r\n                }\r\n            }\r\n        }\r\n\r\n        // Update sub-menus if necessary\r\n        if ((menu_entry->mouse_over) && (menu_entry->type == MENU_ITEM_TYPE_SUB_MENU))\r\n        {\r\n            gui_menu_return_children_pos (n_menu, i, &menus[menu_entry->submenu_id]->start_pos_x,\r\n                &menus[menu_entry->submenu_id]->start_pos_y);\r\n            gui_update_menu (menu_entry->submenu_id, n_menu, i, generation + 1);\r\n        }\r\n    }\r\n}\r\n\r\nvoid    gui_draw_menu(int n_menu, int n_parent, int n_parent_entry)\r\n{\r\n    t_menu *menu = menus[n_menu];\r\n\r\n    const t_font_id font_id = (t_font_id)g_config.font_menus;\r\n    const int label_to_shortcut_y_offset = (Font_Height(font_id) - Font_Height(FONTID_MEDIUM)) / 2 + 1;\r\n\r\n    if (n_menu == MENU_ID_MAIN)\r\n    {\r\n        // a) Main horizontal menu\r\n\r\n        // Draw menu background\r\n        al_set_target_bitmap(gui_buffer);\r\n        al_draw_filled_rectangle(0, 0, g_config.video_mode_gui_res_x+1, gui.info.bars_height+1, COLOR_SKIN_MENU_BACKGROUND);\r\n        al_draw_filled_rectangle(0, gui.info.bars_height + 1, g_config.video_mode_gui_res_x+1, gui.info.bars_height + 2+1, COLOR_SKIN_MENU_BORDER);\r\n\r\n        // Draw menu entries\r\n        int x = menus_opt.spacing_render;\r\n        int y = 3;\r\n        for (int i = 0; i < menu->n_entry; i ++)\r\n        {\r\n            const int ln = Font_TextWidth(FONTID_CUR, menu->entry[i]->label);\r\n            if (x + ln > g_config.video_mode_gui_res_x)\r\n                break;\r\n            if ((menu->entry[i]->mouse_over) && (menu->entry[i]->flags & MENU_ITEM_FLAG_ACTIVE))\r\n            {\r\n                gui_menu_highlight (n_menu, i);\r\n                if (menu->entry[i]->type == MENU_ITEM_TYPE_SUB_MENU)\r\n                    gui_draw_menu(menu->entry[i]->submenu_id, n_menu, i);\r\n            }\r\n            ALLEGRO_COLOR  color;\r\n            if (menu->entry[i]->flags & MENU_ITEM_FLAG_ACTIVE)\r\n                color = COLOR_SKIN_MENU_TEXT;\r\n            else\r\n                color = COLOR_SKIN_MENU_TEXT_UNACTIVE;\r\n\r\n            Font_SetCurrent(font_id);\r\n            Font_Print(FONTID_CUR, menu->entry[i]->label, x, y, color);\r\n            x += ln + menus_opt.spacing_render;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        // b) Vertical children menus\r\n\r\n        // Miscellaneous\r\n        // gui.info.must_redraw = TRUE;\r\n        gui_menu_return_children_pos(n_parent, n_parent_entry, &menu->start_pos_x, &menu->start_pos_y);\r\n\r\n        // DRAW MENU BORDER -------------------------------------------------------\r\n        // rectfill (gui_buffer, menu->sx - 2, menu->sy - 2, menu->sx + menu->lx + 2, menu->sy + menu->ly + 2, COLOR_SKIN_MENU_BORDER);\r\n        // rect (gui_buffer, menu->sx - 1, menu->sy - 1, menu->sx + menu->lx + 1, menu->sy + menu->ly + 1, COLOR_SKIN_MENU_BORDER);\r\n        al_set_target_bitmap(gui_buffer);\r\n        al_draw_rectangle(menu->start_pos_x - 1.5f, menu->start_pos_y - 0.5f, menu->start_pos_x + menu->size_x + 2.5f, menu->start_pos_y + menu->size_y + 1.5f, COLOR_SKIN_MENU_BORDER, 1.0f);\r\n        al_draw_rectangle(menu->start_pos_x - 0.5f, menu->start_pos_y - 1.5f, menu->start_pos_x + menu->size_x + 1.5f, menu->start_pos_y + menu->size_y + 2.5f, COLOR_SKIN_MENU_BORDER, 1.0f);\r\n\r\n        // DRAW MENU BACKGROUND WITH/WITHOUT GRADIENTS ----------------------------\r\n        {\r\n            t_frame menu_frame;\r\n            menu_frame.pos.x = menu->start_pos_x;\r\n            menu_frame.pos.y = menu->start_pos_y;\r\n            menu_frame.size.x = menu->size_x;\r\n            menu_frame.size.y = menu->size_y;\r\n            if (n_parent == 0)\r\n            {\r\n                menu_frame.pos.y -= 2;\r\n                menu_frame.size.y += 2;\r\n            }\r\n            SkinGradient_DrawVertical(&Skins_GetCurrentSkin()->gradient_menu, gui_buffer, &menu_frame);\r\n        }\r\n\r\n        // Draw menu entries\r\n        int x = menu->start_pos_x + MENUS_PADDING_X;\r\n        int y = menu->start_pos_y + MENUS_PADDING_Y;\r\n        for (int i = 0; i < menu->n_entry; i++)\r\n        {\r\n            t_menu_item* item = menu->entry[i];\r\n\r\n            if (item->type == MENU_ITEM_TYPE_SEPARATOR)\r\n            {\r\n                al_draw_hline(menu->start_pos_x, y-1, menu->start_pos_x + menu->size_x, COLOR_SKIN_MENU_BORDER);\r\n                y += MENUS_PADDING_Y;\r\n                continue;\r\n            }\r\n\r\n            if ((item->mouse_over) && (item->flags & MENU_ITEM_FLAG_ACTIVE))\r\n            {\r\n                gui_menu_highlight(n_menu, i);\r\n                if (item->type == MENU_ITEM_TYPE_SUB_MENU)\r\n                    gui_draw_menu(item->submenu_id, n_menu, i);\r\n            }\r\n            ALLEGRO_COLOR color;\r\n            if (item->flags & MENU_ITEM_FLAG_ACTIVE)\r\n                color = COLOR_SKIN_MENU_TEXT;\r\n            else\r\n                color = COLOR_SKIN_MENU_TEXT_UNACTIVE;\r\n\r\n            Font_SetCurrent(font_id);\r\n            Font_Print(FONTID_CUR, item->label, x, y, color);\r\n\r\n            if (item->shortcut != NULL)\r\n            {\r\n                const int shortcut_x = menu->start_pos_x + menu->size_x - MENUS_PADDING_CHECK_X - Font_TextWidth(FONTID_MEDIUM, item->shortcut);\r\n                const int shortcut_y = y + label_to_shortcut_y_offset;\r\n                Font_Print(FONTID_MEDIUM, item->shortcut, shortcut_x, shortcut_y, color);\r\n            }\r\n\r\n            switch (item->type)\r\n            {\r\n            case MENU_ITEM_TYPE_SUB_MENU:\r\n                {\r\n                    // FIXME: draw shape\r\n                    Font_Print(FONTID_CUR, MEKA_FONT_STR_ARROW, menu->start_pos_x + menu->size_x - (int)(Font_TextWidth(FONTID_CUR, MEKA_FONT_STR_ARROW)*1.3f), y, color);\r\n                }\r\n                break;\r\n            case MENU_ITEM_TYPE_CALLBACK:\r\n                if (item->flags & MENU_ITEM_FLAG_CHECKED)\r\n                {\r\n                    // FIXME: draw shape\r\n                    Font_Print(FONTID_CUR, MEKA_FONT_STR_CHECKED, menu->start_pos_x + menu->size_x - (int)(Font_TextWidth(FONTID_CUR, MEKA_FONT_STR_CHECKED)*1.3f), y, color);\r\n                }\r\n                break;\r\n            }\r\n            y += Font_Height(font_id) + MENUS_PADDING_Y;\r\n        }\r\n    }\r\n}\r\n\r\nvoid    gui_redraw_menus()\r\n{\r\n    gui_redraw_bars();\r\n\r\n    // initial panning animation\r\n    if (menus_opt.spacing_render > menus_opt.spacing)\r\n    {\r\n        menus_opt.spacing_render -= 14;\r\n        menus_opt.spacing_render = MIN(menus_opt.spacing, menus_opt.spacing_render);\r\n        gui.info.must_redraw = true;\r\n    }\r\n\r\n    gui_draw_menu(menus_ID.root, -1, -1);\r\n}\r\n\r\nvoid    gui_update_menus()\r\n{\r\n    menus_opt.c_somewhere = 0;\r\n    gui_update_menu(menus_ID.root, 0, 0, 0);\r\n    if ((gui.mouse.buttons & 1) && (menus_opt.c_somewhere == 0)\r\n        && (menus_opt.c_menu == -1)\r\n        && (menus_opt.c_entry == -1)\r\n        && (menus_opt.c_generation == -1))\r\n    {\r\n        gui_menu_un_mouse_over (0);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/g_menu.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_menu.h\r\n// GUI Menus - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\ntypedef int t_menu_id;\r\n\r\n#define MAX_MENUS           (256)\r\n#define MAX_MENUS_ENTRY     (96)\r\n\r\n#define MENU_ID_MAIN        ((t_menu_id)0)\r\n\r\n#define MENUS_PADDING_X         (8)\r\n#define MENUS_PADDING_Y         (4)\r\n#define MENUS_PADDING_CHECK_X   (12)\r\n\r\nenum t_menu_item_type\r\n{\r\n    MENU_ITEM_TYPE_UNKNOWN  = 0,\r\n    MENU_ITEM_TYPE_SUB_MENU = 1,\r\n    MENU_ITEM_TYPE_CALLBACK = 2,\r\n    MENU_ITEM_TYPE_SEPARATOR = 3,\r\n};\r\n\r\n// Definitions for Menus Attributes\r\nenum t_menu_item_flags\r\n{\r\n    MENU_ITEM_FLAG_ACTIVE   = 1<<0,\r\n    MENU_ITEM_FLAG_CHECKED  = 1<<1,\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    gui_init_menu();\r\nvoid    gui_redraw_menus();\r\n\r\nvoid    gui_draw_menu(int n_menu, int n_parent, int n_parent_entry);\r\nvoid    gui_update_menu(int n_menu, int n_parent, int n_parent_entry, int generation);\r\nvoid    gui_update_menus();\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data (NEW)\r\n// FIXME: Finish and obsolete old API\r\n//-----------------------------------------------------------------------------\r\n\r\n// WIP\r\n/*\r\nstruct t_menu\r\n{\r\n    t_list *            items;\r\n    // FIXME\r\n};\r\n\r\nenum t_menu_item_type\r\n{\r\n    MENU_ITEM_TYPE_SINGLE       = 1,\r\n    MENU_ITEM_TYPE_MENU         = 2,\r\n    MENU_ITEM_TYPE_SEPARATOR    = 3\r\n};\r\n\r\nenum t_menu_item_attr\r\n{\r\n    MENU_ITEM_ATTR_ACTIVE       = 0x0001,\r\n    MENU_ITEM_ATTR_CHECKED      = 0x0002,\r\n};\r\n\r\nstruct t_menu_item\r\n{\r\n    char *              label;                                      // Menu item label\r\n    int                 label_msg_ref;                              // Reference to MSG ID For localization purpose // FIXME: How to handle dynamic message with format strings?\r\n    t_menu_item_type    type;                                       // Menu item type (single/submenu/separator)\r\n    t_menu_item_attr    attributes;                                 // Attributes\r\n    int                 group_id;                                   // Group ID (only 1 of a group can be checked)\r\n    union\r\n    {\r\n        struct\r\n        {\r\n            void        (*callback)(struct t_menu_item *, void *, bool);   // Callback\r\n        } data_single;\r\n        struct\r\n        {\r\n            t_menu *    menu;\r\n        } data_menu;\r\n    };\r\n    void *              user_data;\r\n};\r\n\r\nstruct t_menu_event\r\n{\r\n    t_menu *            menu;\r\n    t_menu_item *       menu_item;\r\n    int                 menu_item_idx;      // FIXME: Make obsolete only menu API doesn't need this crap anymore\r\n    void *              user_data;\r\n};\r\n*/\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_gui_status_bar\r\n{\r\n    char  message[1024];\r\n    int   x;\r\n    int   timeleft;\r\n};\r\n\r\nextern t_gui_status_bar g_gui_status;\r\n\r\nstruct t_gui_menus_id\r\n{\r\n    t_menu_id   root;\r\n    t_menu_id   file;\r\n    t_menu_id   machine, power, region, tvtype;\r\n    t_menu_id   video, themes, blitters, layers, flickering, glasses, screenshots;\r\n    t_menu_id   inputs, rapidfire;\r\n    t_menu_id   sound, volume, rate, channels, fm;\r\n    t_menu_id   tools;\r\n    t_menu_id   debug, dump, dump_cfg, watch;\r\n    t_menu_id   help;\r\n    t_menu_id   languages;\r\n    t_menu_id   sound_log;\r\n};\r\n\r\nextern t_gui_menus_id menus_ID;\r\n\r\nstruct t_menu_event;\r\n\r\ntypedef void (*t_menu_callback)(t_menu_event*);\r\n\r\nstruct t_menu_item\r\n{\r\n    char *              label;\r\n    char *              shortcut;\r\n    t_menu_item_type    type;\r\n    unsigned int        flags;\r\n    bool                mouse_over;\r\n    t_menu_id           submenu_id;         // id of sub-menu if (action == 1)\r\n    t_menu_callback     callback;           // pointer to function to execute if (action == 2)\r\n    void *              user_data;\r\n};\r\n\r\nstruct t_menu\r\n{\r\n    t_menu_id           id;\r\n    t_menu_item *       entry[MAX_MENUS_ENTRY];\r\n    int                 n_entry;\r\n    int                 generation;\r\n    int                 start_pos_x, start_pos_y;\r\n    int                 size_x, size_y;\r\n};\r\n\r\nstruct  gui_type_menus_opt\r\n{\r\n    int   spacing_render;\r\n    int   spacing;\r\n    int   c_menu, c_entry;\r\n    int   c_somewhere;\r\n    int   c_generation;\r\n};\r\n\r\nextern gui_type_menus_opt menus_opt;\r\nextern t_menu *menus[MAX_MENUS];\r\n\r\nstruct t_menu_event\r\n{\r\n    t_menu *        menu;\r\n    int             menu_idx;           // FIXME: Make obsolete once menu API doesn't need this crap anymore\r\n    t_menu_item *   menu_item;\r\n    int             menu_item_idx;      // FIXME: Make obsolete once menu API doesn't need this crap anymore\r\n    void *          user_data;\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/g_menu_i.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_menu_i.c\r\n// GUI Menus Initialization - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_about.h\"\r\n#include \"app_cheatfinder.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"app_mapview.h\"\r\n#include \"app_memview.h\"\r\n#include \"app_options.h\"\r\n#include \"app_palview.h\"\r\n#include \"app_techinfo.h\"\r\n#include \"app_textview.h\"\r\n#include \"app_tileview.h\"\r\n#include \"blitintf.h\"\r\n#include \"capture.h\"\r\n#include \"datadump.h\"\r\n#include \"debugger.h\"\r\n#include \"file.h\"\r\n#include \"sound/fmunit.h\"\r\n#include \"glasses.h\"\r\n#include \"inputs_c.h\"\r\n#include \"rapidfir.h\"\r\n#include \"saves.h\"\r\n#include \"sk1100.h\"\r\n#include \"textbox.h\"\r\n#include \"tvtype.h\"\r\n#include \"vmachine.h\"\r\n#include \"sound/s_misc.h\"\r\n#include \"sound/sound_logging.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// FUNCTIONS\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void Debug_ReloadSymbols_Callback(t_menu_event*)\r\n{\r\n    Debugger_Symbols_Load();\r\n}\r\n\r\nstatic void Debug_StepFrame_Callback(t_menu_event*)\r\n{\r\n    g_machine_pause_requests = (g_machine_flags & MACHINE_PAUSED) ? 2 : 1;\r\n}\r\n\r\nstatic void Debug_LoadStateAndContinue_Callback(t_menu_event*)\r\n{\r\n\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n// Initialize and create GUI menus\r\nvoid    gui_menus_init()\r\n{\r\n    char buffer[256];\r\n\r\n    t_font_id font_id = (t_font_id)g_config.font_menus;\r\n\r\n    g_gui_status.x = 10;\r\n    Msg(MSGT_USER_LOG, Msg_Get(MSG_Welcome), MEKA_NAME_VERSION, MEKA_DATE \" \" MEKA_AUTHORS);\r\n    Msg(MSGT_STATUS_BAR, Msg_Get(MSG_Welcome), MEKA_NAME_VERSION, MEKA_DATE \" \" MEKA_AUTHORS);\r\n    menus_opt.spacing = Font_TextWidth(font_id, \"  \");\r\n    menus_opt.spacing_render = gui.info.screen.x - 40;\r\n    menus_opt.c_menu = -1;\r\n    menus_opt.c_entry = -1;\r\n\r\n    //-------------------------------------------------------------------------\r\n    // <ROOT>\r\n    //-------------------------------------------------------------------------\r\n    menus_ID.root     = menu_new();\r\n    menus_ID.file     = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Main),    MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.machine  = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Machine), MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.video    = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Video),   MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.sound    = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Sound),   MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.inputs   = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Inputs),  MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.tools    = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Tools),   MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.debug    = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Debug),   MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.help     = menu_add_menu (menus_ID.root, Msg_Get(MSG_Menu_Help),    MENU_ITEM_FLAG_ACTIVE);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // MAIN\r\n    //-------------------------------------------------------------------------\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_LoadROM),           \"Alt+L\",    MENU_ITEM_FLAG_ACTIVE | Is_Checked (FB.active), (t_menu_callback)FB_Switch, NULL);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_FreeROM),           NULL,       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Free_ROM, NULL);\r\n    menu_add_separator(menus_ID.file);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_SaveState_Save),    \"F5\",       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)SaveState_Save, NULL);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_SaveState_Load),    \"F7\",       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)SaveState_Load, NULL);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_SaveState_PrevSlot), \"F6\",      MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)SaveState_SetPrevSlot, NULL);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_SaveState_NextSlot), \"F8\",      MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)SaveState_SetNextSlot, NULL);\r\n    menu_add_separator(menus_ID.file);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_Options),           \"Alt+O\",    MENU_ITEM_FLAG_ACTIVE | Is_Checked (Options.active), (t_menu_callback)Options_Switch, NULL);\r\n    Langs_Menu_Add    (menus_ID.file);\r\n    menu_add_item     (menus_ID.file, Msg_Get(MSG_Menu_Main_Quit),              \"Alt+F4\",   MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Action_Quit, NULL);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // DEBUG\r\n    //-------------------------------------------------------------------------\r\n#ifdef MEKA_Z80_DEBUGGER\r\n    menu_add_item (menus_ID.debug,  Msg_Get(MSG_Menu_Debug_Enabled),        \"Scroll Lock\",  MENU_ITEM_FLAG_ACTIVE | Is_Checked (Debugger.active), (t_menu_callback)Debugger_Switch, NULL);\r\n    menu_add_item (menus_ID.debug,  Msg_Get(MSG_Menu_Debug_ReloadROM),      NULL,           MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Reload_ROM, NULL);\r\n    menu_add_item (menus_ID.debug,  Msg_Get(MSG_Menu_Debug_ReloadSymbols),  NULL,           MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Debug_ReloadSymbols_Callback, NULL);\r\n    menu_add_item (menus_ID.debug,  Msg_Get(MSG_Menu_Debug_StepFrame),      \"Ctrl+F12\",     MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Debug_StepFrame_Callback, NULL);\r\n    menu_add_item (menus_ID.debug,  Msg_Get(MSG_Menu_Debug_LoadStateAndContinue),\"Ctrl+F7\", MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Debug_LoadStateAndContinue_Callback, NULL);\r\n    menus_ID.dump  = menu_add_menu (menus_ID.debug, Msg_Get(MSG_Menu_Debug_Dump),           MENU_ITEM_FLAG_ACTIVE);\r\n    DataDump_Init_Menus (menus_ID.dump);\r\n    //menus_ID.watch = menu_add_menu (menus_ID.debug, Msg_Get(MSG_Menu_Debug_Watch),      0);\r\n#endif // MEKA_Z80_DEBUGGER\r\n\r\n    //-------------------------------------------------------------------------\r\n    // MACHINE\r\n    //-------------------------------------------------------------------------\r\n    menus_ID.power    = menu_add_menu (menus_ID.machine, Msg_Get(MSG_Menu_Machine_Power),  MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.region   = menu_add_menu (menus_ID.machine, Msg_Get(MSG_Menu_Machine_Region), MENU_ITEM_FLAG_ACTIVE);\r\n    menus_ID.tvtype   = menu_add_menu (menus_ID.machine, Msg_Get(MSG_Menu_Machine_TVType), MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item     (menus_ID.machine,  Msg_Get(MSG_Menu_Machine_PauseEmulation),        \"F12\",           MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Machine_Pause, NULL);\r\n    menu_add_item     (menus_ID.machine,  Msg_Get(Msg_Menu_Machine_ResetEmulation),        \"Alt+Backspace\", MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Machine_Reset, NULL);\r\n    // MACHINE -> POWER\r\n    menu_add_item     (menus_ID.power,    Msg_Get(MSG_Menu_Machine_Power_On),              NULL,            MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Machine_ON, NULL);\r\n    menu_add_item     (menus_ID.power,    Msg_Get(MSG_Menu_Machine_Power_Off),             NULL,            MENU_ITEM_FLAG_ACTIVE /* | AM_Checked */, (t_menu_callback)Machine_OFF, NULL);\r\n    // MACHINE -> COUNTRY\r\n    menu_add_item     (menus_ID.region,   Msg_Get(MSG_Menu_Machine_Region_Export),         NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (g_config.country == COUNTRY_EXPORT), (t_menu_callback)Set_Country_Export, NULL);\r\n    menu_add_item     (menus_ID.region,   Msg_Get(MSG_Menu_Machine_Region_Japan),          NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (g_config.country == COUNTRY_JAPAN),  (t_menu_callback)Set_Country_Japan, NULL);\r\n    // MACHINE -> TV TYPE\r\n    menu_add_item     (menus_ID.tvtype,   Msg_Get(MSG_Menu_Machine_TVType_NTSC),           NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (TV_Type_User->id == TVTYPE_NTSC), (t_menu_callback)TVType_Set_NTSC, NULL);\r\n    menu_add_item     (menus_ID.tvtype,   Msg_Get(MSG_Menu_Machine_TVType_PALSECAM),       NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (TV_Type_User->id == TVTYPE_PAL_SECAM), (t_menu_callback)TVType_Set_PAL_SECAM, NULL);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // VIDEO\r\n    //-------------------------------------------------------------------------\r\n    menu_add_item     (menus_ID.video,    Msg_Get(MSG_Menu_Video_FullScreen),              \"Escape\",        MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Action_Switch_Mode, NULL);\r\n\r\n    // VIDEO -> CAPTURE\r\n    menus_ID.screenshots = menu_add_menu (menus_ID.video, Msg_Get(Msg_Menu_Video_ScreenCapture),    MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item(menus_ID.screenshots, Msg_Get(Msg_Menu_Video_ScreenCapture_Capture),      \"PrintScreen\",  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Capture_MenuHandler_Capture, NULL);\r\n    menu_add_item(menus_ID.screenshots, Msg_Get(Msg_Menu_Video_ScreenCapture_CaptureRepeat),NULL,           MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Capture_MenuHandler_AllFrames, NULL);\r\n    menu_add_item(menus_ID.screenshots, Msg_Get(Msg_Menu_Video_ScreenCapture_IncludeGui),   NULL,           MENU_ITEM_FLAG_ACTIVE | Is_Checked(g_config.capture_include_gui), (t_menu_callback)Capture_MenuHandler_IncludeGui, NULL);\r\n    // VIDEO -> THEMES\r\n    menus_ID.themes   = menu_add_menu (menus_ID.video, Msg_Get(MSG_Menu_Video_Themes),     MENU_ITEM_FLAG_ACTIVE);\r\n    Skins_MenuInit (menus_ID.themes);\r\n    // VIDEO -> BLITTERS\r\n    menus_ID.blitters = menu_add_menu (menus_ID.video, Msg_Get(MSG_Menu_Video_Blitters),   MENU_ITEM_FLAG_ACTIVE);\r\n    Blitters_Menu_Init(menus_ID.blitters);\r\n    // VIDEO -> LAYERS\r\n    menus_ID.layers   = menu_add_menu (menus_ID.video, Msg_Get(MSG_Menu_Video_Layers),     MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item     (menus_ID.layers,   Msg_Get(MSG_Menu_Video_Layers_Sprites),          \"F11\",           MENU_ITEM_FLAG_ACTIVE | MENU_ITEM_FLAG_CHECKED, (t_menu_callback)Action_Switch_Layer_Sprites, NULL);\r\n    menu_add_item     (menus_ID.layers,   Msg_Get(MSG_Menu_Video_Layers_Background),       \"Ctrl+F11\",      MENU_ITEM_FLAG_ACTIVE | MENU_ITEM_FLAG_CHECKED, (t_menu_callback)Action_Switch_Layer_Background, NULL);\r\n    // VIDEO -> FLICKERING\r\n    menus_ID.flickering = menu_add_menu (menus_ID.video, Msg_Get(MSG_Menu_Video_Flickering), MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item     (menus_ID.flickering, Msg_Get(MSG_Menu_Video_Flickering_Auto),       NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (g_config.sprite_flickering & SPRITE_FLICKERING_AUTO), (t_menu_callback)Action_Switch_Flickering_Auto, NULL);\r\n    menu_add_item     (menus_ID.flickering, Msg_Get(MSG_Menu_Video_Flickering_Yes),        NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (!(g_config.sprite_flickering & SPRITE_FLICKERING_AUTO) && (g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED)), (t_menu_callback)Action_Switch_Flickering_Yes, NULL);\r\n    menu_add_item     (menus_ID.flickering, Msg_Get(MSG_Menu_Video_Flickering_No),         NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (!(g_config.sprite_flickering & SPRITE_FLICKERING_AUTO) && !(g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED)), (t_menu_callback)Action_Switch_Flickering_No, NULL);\r\n    // VIDEO -> GLASSES (3-D)\r\n    menus_ID.glasses  = menu_add_menu (menus_ID.video, Msg_Get(MSG_Menu_Video_3DGlasses),  MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item     (menus_ID.glasses,  Msg_Get(MSG_Menu_Video_3DGlasses_Enabled),       NULL,            MENU_ITEM_FLAG_ACTIVE | Is_Checked (Glasses.Enabled), (t_menu_callback)Glasses_Switch_Enable, NULL);\r\n    menu_add_item     (menus_ID.glasses,  Msg_Get(MSG_Menu_Video_3DGlasses_ShowBothSides), NULL,            Is_Active (Glasses.Enabled) | Is_Checked (Glasses.Mode == GLASSES_MODE_SHOW_BOTH), (t_menu_callback)Glasses_Switch_Mode_Show_Both, NULL);\r\n    menu_add_item     (menus_ID.glasses,  Msg_Get(MSG_Menu_Video_3DGlasses_ShowLeftSide),  NULL,            Is_Active (Glasses.Enabled) | Is_Checked (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT), (t_menu_callback)Glasses_Switch_Mode_Show_Left, NULL);\r\n    menu_add_item     (menus_ID.glasses,  Msg_Get(MSG_Menu_Video_3DGlasses_ShowRightSide), NULL,            Is_Active (Glasses.Enabled) | Is_Checked (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_RIGHT), (t_menu_callback)Glasses_Switch_Mode_Show_Right, NULL);\r\n    menu_add_item     (menus_ID.glasses,  Msg_Get(MSG_Menu_Video_3DGlasses_UsesCOMPort),   NULL,            Is_Active (Glasses.Enabled) | Is_Checked (Glasses.Mode == GLASSES_MODE_COM_PORT), (t_menu_callback)Glasses_Switch_Mode_Com_Port, NULL);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // SOUND\r\n    //-------------------------------------------------------------------------\r\n    // SOUND -> FM\r\n    menus_ID.fm       = menu_add_menu (menus_ID.sound, Msg_Get(MSG_Menu_Sound_FM),        MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item     (menus_ID.fm,       Msg_Get(MSG_Menu_Sound_FM_Enabled),             NULL,         MENU_ITEM_FLAG_ACTIVE | Is_Checked (Sound.FM_Enabled == TRUE),     (t_menu_callback)FM_Enable, NULL);\r\n    menu_add_item     (menus_ID.fm,       Msg_Get(MSG_Menu_Sound_FM_Disabled),            NULL,         MENU_ITEM_FLAG_ACTIVE | Is_Checked (Sound.FM_Enabled == FALSE ),   (t_menu_callback)FM_Disable, NULL);\r\n    // menu_add_item  (menus_ID.fm,       Msg_Get(MSG_Menu_Sound_FM_Editor),              AM_Active | Is_Checked (apps.active.FM_Editor),     (t_menu_callback)FM_Editor_Switch, NULL);\r\n    // SOUND -> VOLUME\r\n    menus_ID.volume   = menu_add_menu (menus_ID.sound, Msg_Get(MSG_Menu_Sound_Volume),    MENU_ITEM_FLAG_ACTIVE);\r\n    Sound_Volume_Menu_Init(menus_ID.volume);\r\n    // SOUND -> CHANNELS\r\n    menus_ID.channels = menu_add_menu (menus_ID.sound, Msg_Get(MSG_Menu_Sound_Channels), MENU_ITEM_FLAG_ACTIVE);\r\n    for (int i = 0; i < 3; i++)\r\n    {\r\n        snprintf(buffer, countof(buffer), Msg_Get(MSG_Menu_Sound_Channels_Tone), i+1);\r\n        menu_add_item  (menus_ID.channels, buffer, NULL, MENU_ITEM_FLAG_ACTIVE | MENU_ITEM_FLAG_CHECKED, (t_menu_callback)Sound_Channels_Menu_Handler, (void *)i);\r\n    }\r\n    menu_add_item     (menus_ID.channels, Msg_Get(MSG_Menu_Sound_Channels_Noises),        NULL, MENU_ITEM_FLAG_ACTIVE | MENU_ITEM_FLAG_CHECKED, (t_menu_callback)Sound_Channels_Menu_Handler, (void *)3);\r\n    // SOUND -> LOGGING\r\n    menus_ID.sound_log = menu_add_menu (menus_ID.sound, Msg_Get(MSG_Menu_Sound_Capture),        MENU_ITEM_FLAG_ACTIVE);\r\n    menu_add_item     (menus_ID.sound_log, Msg_Get(MSG_Menu_Sound_Capture_VGM_Start),           \"Alt+V\",    MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Sound_LogVGM_Start, NULL);\r\n    menu_add_item     (menus_ID.sound_log, Msg_Get(MSG_Menu_Sound_Capture_VGM_Stop),            \"Alt+V\",    0, (t_menu_callback)Sound_LogVGM_Stop, NULL);\r\n    menu_add_item     (menus_ID.sound_log, Msg_Get(MSG_Menu_Sound_Capture_VGM_SampleAccurate), NULL,    MENU_ITEM_FLAG_ACTIVE | Is_Checked (Sound.LogVGM_Logging_Accuracy == VGM_LOGGING_ACCURACY_SAMPLE), (t_menu_callback)Sound_LogVGM_Accuracy_Switch, NULL);\r\n    menu_add_item     (menus_ID.sound_log, Msg_Get(MSG_Menu_Sound_Capture_WAV_Start),           NULL,   MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Sound_LogWAV_Start, NULL);\r\n    menu_add_item     (menus_ID.sound_log, Msg_Get(MSG_Menu_Sound_Capture_WAV_Stop),            NULL,   0, (t_menu_callback)Sound_LogWAV_Stop, NULL);\r\n\r\n    SoundDebugApp_InstallMenuItems(menus_ID.sound);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // INPUTS\r\n    //-------------------------------------------------------------------------\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_Joypad),          \"F9\",       MENU_ITEM_FLAG_ACTIVE | MENU_ITEM_FLAG_CHECKED, (t_menu_callback)Inputs_Switch_Joypad, NULL);\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_LightPhaser),     NULL,       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Inputs_Switch_LightPhaser, NULL);\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_PaddleControl),   NULL,       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Inputs_Switch_PaddleControl, NULL);\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_SportsPad),       NULL,       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Inputs_Switch_SportsPad, NULL);\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_GraphicBoard),    NULL,       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Inputs_Switch_GraphicBoard, NULL);\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_GraphicBoardV2),  NULL,       MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)Inputs_Switch_GraphicBoardV2, NULL);\r\n    menu_add_separator(menus_ID.inputs);\r\n    menu_add_item     (menus_ID.inputs,   Msg_Get(MSG_Menu_Inputs_SK1100),          \"CTRL+F9\",  MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)SK1100_Switch, NULL);\r\n    menu_add_separator(menus_ID.inputs);\r\n    // INPUTS -> RAPID FIRE\r\n    menus_ID.rapidfire = menu_add_menu (menus_ID.inputs, Msg_Get(MSG_Menu_Inputs_RapidFire), MENU_ITEM_FLAG_ACTIVE);\r\n    snprintf          (buffer, countof(buffer), Msg_Get(MSG_Menu_Inputs_RapidFire_PxBx), 1, 1);\r\n    menu_add_item     (menus_ID.rapidfire, buffer, NULL, MENU_ITEM_FLAG_ACTIVE | Is_Checked (RapidFire & RAPIDFIRE_J1B1), (t_menu_callback)RapidFire_Switch_J1B1, NULL);\r\n    snprintf          (buffer, countof(buffer), Msg_Get(MSG_Menu_Inputs_RapidFire_PxBx), 1, 2);\r\n    menu_add_item     (menus_ID.rapidfire, buffer, NULL, MENU_ITEM_FLAG_ACTIVE | Is_Checked (RapidFire & RAPIDFIRE_J1B2), (t_menu_callback)RapidFire_Switch_J1B2, NULL);\r\n    snprintf          (buffer, countof(buffer), Msg_Get(MSG_Menu_Inputs_RapidFire_PxBx), 2, 1);\r\n    menu_add_item     (menus_ID.rapidfire, buffer, NULL, MENU_ITEM_FLAG_ACTIVE | Is_Checked (RapidFire & RAPIDFIRE_J2B1), (t_menu_callback)RapidFire_Switch_J2B1, NULL);\r\n    snprintf          (buffer, countof(buffer), Msg_Get(MSG_Menu_Inputs_RapidFire_PxBx), 2, 2);\r\n    menu_add_item     (menus_ID.rapidfire, buffer, NULL, MENU_ITEM_FLAG_ACTIVE | Is_Checked (RapidFire & RAPIDFIRE_J2B2), (t_menu_callback)RapidFire_Switch_J2B2, NULL);\r\n    // INPUTS (misc)\r\n    menu_add_item     (menus_ID.inputs,    Msg_Get(MSG_Menu_Inputs_Configuration), NULL,    MENU_ITEM_FLAG_ACTIVE | Is_Checked (Inputs_CFG.active), (t_menu_callback)Inputs_CFG_Switch, NULL);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // TOOLS\r\n    //-------------------------------------------------------------------------\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_Messages),      \"Alt+M\",  MENU_ITEM_FLAG_ACTIVE | Is_Checked (TB_Message.active),                  (t_menu_callback)TB_Message_Switch,                  NULL);\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_Palette),       \"Alt+P\",  MENU_ITEM_FLAG_ACTIVE | Is_Checked (PaletteViewer.active),               (t_menu_callback)PaletteViewer_Switch,               NULL);\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_TilesViewer),   \"Alt+T\",  MENU_ITEM_FLAG_ACTIVE | Is_Checked (TileViewer.active),                  (t_menu_callback)TileViewer_Switch,                  NULL);\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_TilemapViewer), NULL,     MENU_ITEM_FLAG_ACTIVE | Is_Checked (TilemapViewer_MainInstance->active), (t_menu_callback)TilemapViewer_SwitchMainInstance,   NULL);\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_MemoryEditor),  NULL,     MENU_ITEM_FLAG_ACTIVE | Is_Checked (MemoryViewer_MainInstance->active),  (t_menu_callback)MemoryViewer_SwitchMainInstance,    NULL);\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_CheatFinder),   NULL,     MENU_ITEM_FLAG_ACTIVE | Is_Checked (g_CheatFinder_MainInstance->active), (t_menu_callback)CheatFinder_SwitchMainInstance,    NULL);\r\n    menu_add_item     (menus_ID.tools,     Msg_Get(MSG_Menu_Tools_TechInfo),      \"Alt+I\",  MENU_ITEM_FLAG_ACTIVE | Is_Checked (TechInfo.active),                    (t_menu_callback)TechInfo_Switch,                    NULL);\r\n\r\n    //-------------------------------------------------------------------------\r\n    // HELP\r\n    //-------------------------------------------------------------------------\r\n    menu_add_item     (menus_ID.help,      Msg_Get(MSG_Menu_Help_Documentation),  NULL,     MENU_ITEM_FLAG_ACTIVE | Is_Checked (TextViewer.active), (t_menu_callback)TextViewer_Switch_Doc_Main, NULL);\r\n    menu_add_item     (menus_ID.help,      Msg_Get(MSG_Menu_Help_Compat),         NULL,     MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)TextViewer_Switch_Doc_Compat, NULL);\r\n    menu_add_item     (menus_ID.help,      Msg_Get(MSG_Menu_Help_Multiplayer_Games),NULL,   MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)TextViewer_Switch_Doc_Multiplayer_Games, NULL);\r\n    menu_add_item     (menus_ID.help,      Msg_Get(MSG_Menu_Help_Changes),        NULL,     MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)TextViewer_Switch_Doc_Changes, NULL);\r\n#ifdef MEKA_Z80_DEBUGGER\r\n    menu_add_item     (menus_ID.help,      Msg_Get(MSG_Menu_Help_Debugger),       NULL,     MENU_ITEM_FLAG_ACTIVE, (t_menu_callback)TextViewer_Switch_Doc_Debugger, NULL);\r\n#endif // MEKA_Z80_DEBUGGER\r\n    menu_add_item     (menus_ID.help,      Msg_Get(MSG_Menu_Help_About),          NULL,     MENU_ITEM_FLAG_ACTIVE | Is_Checked (AboutBox.active), (t_menu_callback)AboutBox_Switch, NULL);\r\n\r\n    // ...\r\n    gui_menu_un_mouse_over(menus_ID.root);\r\n    gui_menus_update_size();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/g_menu_i.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_menu_i.h\n// GUI Menus Initialization - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    gui_menus_init();\n\n#define Is_Active(test)         ((test) ? MENU_ITEM_FLAG_ACTIVE : 0)\n#define Is_Checked(test)        ((test) ? MENU_ITEM_FLAG_CHECKED : 0)\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_menu_t.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_menu_t.c\n// GUI Menus Tools - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n\n//-----------------------------------------------------------------------------\n// Functions - Old API, rewrite and make this obsolete\n//-----------------------------------------------------------------------------\n\nvoid    gui_menu_highlight(int menu_id, int entry_id)\n{\n    int    x1, x2;\n    int    y1, y2;\n\n    gui_menu_return_entry_pos (menu_id, entry_id, &x1, &y1, &x2, &y2);\n    al_set_target_bitmap(gui_buffer);\n    al_draw_filled_rectangle(x1 - 2, y1, x2 + 2+1, y2+1, COLOR_SKIN_MENU_SELECTION);\n}\n\nvoid    gui_menu_return_children_pos(int p_menu, int p_entry, int *x, int *y)\n{\n    int    x1, x2;\n    int    y1, y2;\n\n    gui_menu_return_entry_pos(p_menu, p_entry, &x1, &y1, &x2, &y2);\n    if (p_menu == MENU_ID_MAIN)\n    {\n        *x = x1;\n        *y = y2 + 5;\n    }\n    else\n    {\n        *x = x2 + 5;\n        *y = y1 - 1;\n    }\n}\n\nvoid    gui_menu_return_entry_pos(int menu_id, int n_entry, int *x1, int *y1, int *x2, int *y2)\n{\n    t_font_id font_id = (t_font_id)g_config.font_menus;\n\n    t_menu* menu = menus[menu_id];\n    if (menu_id == MENU_ID_MAIN)\n    {\n        *y1 = 1;\n        *y2 = gui.info.bars_height - 1;\n        *x1 = menus_opt.spacing_render;\n        for (int i = 0; i < n_entry; i ++)\n        {\n            t_menu_item* item = menu->entry[i];\n            *x1 += Font_TextWidth(font_id, item->label) + menus_opt.spacing_render;\n        }\n        *x1 -= (menus_opt.spacing / 2);\n        *x2 = *x1 + menus_opt.spacing + Font_TextWidth(font_id, menu->entry[n_entry]->label);\n    }\n    else\n    {\n        *x1 = menu->start_pos_x + 2;\n        *x2 = menu->start_pos_x + menu->size_x - 2;\n        int y = menu->start_pos_y + MENUS_PADDING_Y;\n        for (int i = 0; i < n_entry; i ++)\n        {\n            t_menu_item* item = menu->entry[i];\n            y += item->type == MENU_ITEM_TYPE_SEPARATOR ? MENUS_PADDING_Y : Font_Height(font_id)+MENUS_PADDING_Y;\n        }\n\n        t_menu_item* item = menu->entry[n_entry];\n        *y1 = y;\n        *y2 = y + (item->type == MENU_ITEM_TYPE_SEPARATOR ? 0 : Font_Height(font_id));\n        *y1 -= 3;\n    }\n}\n\n// UPDATE THE SIZE OF A MENU --------------------------------------------------\nvoid    gui_menu_update_size(int menu_id)\n{\n    t_font_id font_id = (t_font_id)g_config.font_menus;\n\n    int size_x = 0;\n    int size_y = 0;\n    t_menu* menu = menus[menu_id];\n    for (int i = 0; i < menu->n_entry; i ++)\n    {\n        t_menu_item* item = menu->entry[i];\n        if (item->type == MENU_ITEM_TYPE_SEPARATOR)\n        {\n            size_y += MENUS_PADDING_Y;\n            continue;\n        }\n        else\n        {\n            const int text_w = Font_TextWidth(font_id, item->label);\n            const int shortcut_w = item->shortcut ? Font_TextWidth(FONTID_MEDIUM, item->shortcut) : 0;\n\n            size_x = MAX(size_x, text_w + MENUS_PADDING_X + shortcut_w + MENUS_PADDING_CHECK_X);\n            size_y += Font_Height(font_id) + MENUS_PADDING_Y;\n        }\n    }\n    menu->size_x = size_x + (3 * MENUS_PADDING_X);\n    menu->size_y = size_y;\n}\n\nvoid gui_menus_update_size (void)\n{\n    for (int i = 0; i < MAX_MENUS; i++)\n    {\n        if (menus[i])\n        {\n            gui_menu_update_size (i);\n        }\n    }\n}\n\n// CREATE A NEW MENU ----------------------------------------------------------\nint     menu_new (void)\n{\n    // Look for next un-allocated menu\n    int    menu_id;\n    for (menu_id = 0; menu_id < MAX_MENUS; menu_id ++)\n        if (menus[menu_id] == NULL)\n            break;\n    if (menu_id == MAX_MENUS)\n        return (0);\n\n    // Allocate new menu and initialize it with default values\n    t_menu* menu = (t_menu *)malloc(sizeof (t_menu));\n    menus[menu_id] = menu;\n    menu->id = menu_id;\n    menu->start_pos_x = menus[menu_id]->start_pos_y = 0;\n    menu->size_x = menus[menu_id]->size_y = 0;\n    menu->n_entry = 0;\n    menu->generation = -1;\n\n    return (menu_id);\n}\n\nint     menu_add_menu (int menu_id, const char *label, int flags)\n{\n    t_menu* menu = menus[menu_id];\n    if (menu->n_entry >= MAX_MENUS_ENTRY)\n    {\n        return (0);\n    }\n\n    const int submenu_id = menu_new();\n    t_menu_item* entry = menu->entry[menu->n_entry] = (t_menu_item *)malloc(sizeof (t_menu_item));\n\n    entry->label = strdup(label);\n    entry->shortcut = NULL;\n    entry->type = MENU_ITEM_TYPE_SUB_MENU;\n    entry->flags = flags;\n    entry->mouse_over = false;\n    entry->submenu_id = submenu_id;\n\n    menu->n_entry++;\n    return (submenu_id);\n}\n\nint menu_add_item(int menu_id, const char* label, const char* shortcut, int flags, t_menu_callback callback, void *user_data)\n{\n    t_menu* menu = menus [menu_id];\n    if (menu->n_entry >= MAX_MENUS_ENTRY)\n    {\n        return (0);\n    }\n\n    t_menu_item* entry = menu->entry[menu->n_entry] = (t_menu_item *)malloc(sizeof (t_menu_item));\n    entry->label = strdup(label);\n    entry->shortcut = shortcut ? strdup(shortcut) : NULL;\n    entry->type = MENU_ITEM_TYPE_CALLBACK;\n    entry->flags = flags;\n    entry->mouse_over = false;\n    entry->callback = (t_menu_callback)callback;\n    entry->user_data = user_data;\n    return (menu->n_entry ++);\n}\n\nint menu_add_separator(int menu_id)\n{\n    t_menu* menu = menus [menu_id];\n    if (menu->n_entry >= MAX_MENUS_ENTRY)\n    {\n        return (0);\n    }\n\n    t_menu_item* entry = menu->entry[menu->n_entry] = (t_menu_item *)malloc(sizeof (t_menu_item));\n    entry->label = NULL;\n    entry->shortcut = NULL;\n    entry->type = MENU_ITEM_TYPE_SEPARATOR;\n    entry->flags = 0;\n    entry->mouse_over = false;\n    entry->callback = NULL;\n    entry->user_data = NULL;\n    return (menu->n_entry ++);\n}\n\n// SET ALL \"MOUSE_OVER\" VARIABLE TO ZERO, RECURSIVELY -------------------------\n// FIXME: Make obsolete\nvoid    gui_menu_un_mouse_over (int menu_id)\n{\n    t_menu  *menu = menus [menu_id];\n    for (int i = 0; i < menu->n_entry; i ++)\n    {\n        if (menu->entry[i]->mouse_over)\n        {\n            gui.info.must_redraw = TRUE;\n            menu->entry[i]->mouse_over = false;\n            if ((menu->entry[i]->type == MENU_ITEM_TYPE_SUB_MENU) && (menu->entry[i]->flags & MENU_ITEM_FLAG_ACTIVE))\n            {\n                gui_menu_un_mouse_over (menu->entry[i]->submenu_id);\n            }\n        }\n    }\n}\n\n// SET ALL \"CHECKED\" ATTRIBUTES TO ZERO, RECURSIVELY --------------------------\n// FIXME: Make obsolete\nvoid    gui_menu_uncheck_all(int menu_id)\n{\n    t_menu  *menu = menus [menu_id];\n    for (int i = 0; i < menu->n_entry; i ++)\n    {\n        menu->entry[i]->flags &= (~MENU_ITEM_FLAG_CHECKED);\n        if ((menu->entry[i]->type == MENU_ITEM_TYPE_SUB_MENU) && (menu->entry[i]->flags & MENU_ITEM_FLAG_ACTIVE))\n        {\n            gui_menu_uncheck_all (menu->entry[i]->submenu_id);\n        }\n    }\n}\n\n// SET ALL \"CHECKED\" ATTRIBUTES TO ZERO, RECURSIVELY --------------------------\n// FIXME: Make obsolete\nvoid    gui_menu_uncheck_range(int menu_id, int start, int end)\n{\n    t_menu  *menu = menus [menu_id];\n    for (int i = start; i <= end; i ++)\n    {\n        menu->entry[i]->flags &= (~MENU_ITEM_FLAG_CHECKED);\n        if ((menu->entry[i]->type == MENU_ITEM_TYPE_SUB_MENU) && (menu->entry[i]->flags & MENU_ITEM_FLAG_ACTIVE))\n        {\n            gui_menu_uncheck_all (menu->entry[i]->submenu_id);\n        }\n    }\n}\n\n// FIXME: Make obsolete\nvoid    gui_menu_active(int active, int menu_id, int menu_item)\n{\n    t_menu  *menu = menus [menu_id];\n\n    assert(menu_item >= 0 && menu_item < menu->n_entry);\n    if (active)\n        menu->entry[menu_item]->flags |= (MENU_ITEM_FLAG_ACTIVE);\n    else\n        menu->entry[menu_item]->flags &= (~MENU_ITEM_FLAG_ACTIVE);\n}\n\n// FIXME: Make obsolete\nvoid    gui_menu_active_range(int active, int menu_id, int start, int end)\n{\n    t_menu  *menu = menus [menu_id];\n    for (int i = start; i <= end; i ++)\n    {\n        if (active)\n            menu->entry[i]->flags |= (MENU_ITEM_FLAG_ACTIVE);\n        else\n            menu->entry[i]->flags &= (~MENU_ITEM_FLAG_ACTIVE);\n    }\n}\n\nvoid    gui_menu_check(int menu_id, int n_entry)\n{\n    menus [menu_id]->entry [n_entry]->flags |= MENU_ITEM_FLAG_CHECKED;\n}\n\n// FIXME: Make obsolete\nvoid    gui_menu_toggle_check (int menu_id, int n_entry)\n{\n    menus [menu_id]->entry [n_entry]->flags ^= MENU_ITEM_FLAG_CHECKED;\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_menu_t.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_menu_t.h\n// GUI Menus Tools - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n// new names\nint     menu_new();\nint     menu_add_menu(int n_menu, const char *label, int attr);\nint     menu_add_item(int n_menu, const char *label, const char* hotkey, int attr, t_menu_callback callback, void *user_data);\nint     menu_add_separator(int n_menu);\n\n// old names\nvoid    gui_menu_highlight              (int menu_id, int entry_id);\nvoid    gui_menu_return_children_pos    (int p_menu, int p_entry, int *x, int *y);\nvoid    gui_menu_return_entry_pos       (int menu_id, int n_entry, int *x1, int *y1, int *x2, int *y2);\nvoid    gui_menu_update_size            (int menu_id);\nvoid    gui_menus_update_size           ();\n\nvoid    gui_menu_uncheck_all            (int menu_id);\nvoid    gui_menu_uncheck_range          (int menu_id, int start, int end);\nvoid    gui_menu_check                  (int menu_id, int n_entry);\nvoid    gui_menu_toggle_check           (int menu_id, int n_entry);\n\nvoid    gui_menu_active                 (int active, int menu_id, int menu_item);\nvoid    gui_menu_active_range           (int active, int menu_id, int start, int end);\n\nvoid    gui_menu_un_mouse_over          (int menu_id);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_mouse.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_mouse.c\n// GUI Mouse related things - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    gui_init_mouse()\n{\n    gui.mouse.x = 0;\n    gui.mouse.y = 0;\n    gui.mouse.x_prev = 0;\n    gui.mouse.y_prev = 0;\n    gui.mouse.buttons = 0;\n    gui.mouse.buttons_prev = 0;\n    gui.mouse.double_clicked = 0;\n    gui.mouse.wheel_rel = 0;\n    gui.mouse.wheel_abs = 0;\n    gui.mouse.focus = GUI_FOCUS_NONE;\n    gui.mouse.focus_box = NULL;\n    gui.mouse.focus_widget = NULL;\n    gui.mouse.focus_is_resizing = false;\n    gui.mouse.last_click_button = 0;\n    gui.mouse.last_click_time_elapsed = 9999.0f;\n}\n\nbool    gui_is_mouse_hovering_area(int x1, int y1, int x2, int y2)\n{\n    return ((gui.mouse.x >= x1) && (gui.mouse.y >= y1) && (gui.mouse.x <= x2) && (gui.mouse.y <= y2));\n}\n\nbool    gui_is_mouse_hovering_area(const t_frame* frame)\n{\n    return ((gui.mouse.x >= frame->pos.x) && (gui.mouse.y >= frame->pos.y) && (gui.mouse.x <= frame->pos.x+frame->size.x) && (gui.mouse.y <= frame->pos.y+frame->size.y));\n}\n\n\nvoid    gui_update_mouse()\n{\n    if (g_env.mouse_installed == -1)\n        return;\n\n    gui.mouse.x_prev = gui.mouse.x;\n    gui.mouse.y_prev = gui.mouse.y;\n    gui.mouse.buttons_prev = gui.mouse.buttons;\n\n    gui.mouse.x = g_mouse_state.x;\n    gui.mouse.y = g_mouse_state.y;\n    gui.mouse.buttons = g_mouse_state.buttons;\n    // Msg(MSGT_DEBUG, \"gui_mouse_button = %d\", mouse_b);\n\n    gui.mouse.wheel_rel = g_mouse_state.z - gui.mouse.wheel_abs;\n    gui.mouse.wheel_abs = g_mouse_state.z;\n\n    // Uncomment to bypass Allegro 3 button emulation\n    // if (gui_mouse.button == 4) gui_mouse.button = 3;\n\n    for (size_t i = 0; i < 3; i++)\n    {\n        if ((gui.mouse.buttons & (1<<i)) && !(gui.mouse.buttons_prev & (1<<i)))\n        {\n            if (gui.mouse.last_click_button == (1<<i) && gui.mouse.last_click_time_elapsed < DOUBLE_CLICK_SPEED)\n            {\n                gui.mouse.double_clicked |= (1<<i);\n                gui.mouse.last_click_time_elapsed = 9999.0f;    // So that 3rd click doesn't become a double-click\n            }\n            else\n            {\n                gui.mouse.last_click_time_elapsed = 0;\n            }\n            gui.mouse.last_click_button = (1<<i);\n        }\n        else\n        {\n            gui.mouse.double_clicked &= ~(1<<i);\n        }\n    }\n    if (gui.mouse.last_click_button)\n    {\n        gui.mouse.last_click_time_elapsed++;\n    }\n\n    if (gui.mouse.buttons == 0)\n    {\n        gui.mouse.focus = GUI_FOCUS_NONE;\n        gui.mouse.focus_box = NULL;\n        gui.mouse.focus_widget = NULL;\n\n        menus_opt.c_menu = -1;\n        menus_opt.c_entry = -1;\n        menus_opt.c_generation = -1;\n    }\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/g_mouse.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_mouse.h\n// GUI Mouse related things - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\nenum t_gui_focus\n{\n    GUI_FOCUS_NONE          = 0,\n    GUI_FOCUS_DESKTOP       = 1,\n    GUI_FOCUS_BOX           = 2,\n    GUI_FOCUS_MENUS         = 3,\n    GUI_FOCUS_WIDGET        = 4,\n};\n\n/*\n#define  PRESSED_ON_NOTHING   (-1)\n#define  PRESSED_ON_DESKTOP   (0)\n#define  PRESSED_ON_BOX       (1)\n#define  PRESSED_ON_MENUS     (2)\n#define  PRESSED_ON_WIDGET    (3)\n*/\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    gui_init_mouse();\nvoid    gui_update_mouse();\nbool    gui_is_mouse_hovering_area(int x1, int y1, int x2, int y2);\nbool    gui_is_mouse_hovering_area(const t_frame* frame);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_tools.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_tools.c\r\n// GUI Tools - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"g_tools.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    gui_frame_clear(ALLEGRO_BITMAP *dst, const t_frame *frame, ALLEGRO_COLOR color)\r\n{\r\n    al_set_target_bitmap(dst);\r\n    al_draw_filled_rectangle(frame->pos.x, frame->pos.y, frame->pos.x + frame->size.x, frame->pos.y + frame->size.y, color);\r\n}\r\n\r\nvoid    gui_rect(int look, int x1, int y1, int x2, int y2, ALLEGRO_COLOR c_fg)\r\n{\r\n    switch (look)\r\n    {\r\n    case LOOK_THIN:\r\n        al_draw_rectangle(x1 + 1.5f, y1 + 1.5f, x2 - 0.5f, y2 - 0.5f, c_fg, 1);\r\n        break;\r\n    case LOOK_ROUND:\r\n        al_draw_rectangle(x1 + 1.5f, y1 + 0.5f, x2 - 0.5f, y2 + 0.5f, c_fg, 1);\r\n        al_draw_rectangle(x1 + 0.5f, y1 + 1.5f, x2 + 0.5f, y2 - 0.5f, c_fg, 1);\r\n        break;\r\n    default:\r\n        assert(0);\r\n    }\r\n}\r\n\r\nvoid    gui_rect_titled (char *Text, t_font_id font_id,\r\n                         int look, int x1, int y1, int x2, int y2,\r\n                         ALLEGRO_COLOR c_fg, ALLEGRO_COLOR c_bg, ALLEGRO_COLOR c_text)\r\n{\r\n    int lx, ly;\r\n    gui_rect(look, x1, y1, x2, y2, c_fg);\r\n    lx = Font_TextWidth(font_id, Text) + (2 * GUI_LOOK_FRAME_PAD_HEAD2_X) + 3;\r\n    ly = Font_Height(font_id) / 2;\r\n\r\n    al_draw_filled_rectangle(x1 + GUI_LOOK_FRAME_PAD_HEAD1_X, y1 - ly, x1 + GUI_LOOK_FRAME_PAD_HEAD1_X + lx + 1, y1 + ly + 1, c_bg);\r\n    al_draw_line(x1 + GUI_LOOK_FRAME_PAD_HEAD1_X, y1 - ly + 1, x1 + GUI_LOOK_FRAME_PAD_HEAD1_X, y1 + ly, c_fg, 0);\r\n    al_draw_line(x1 + lx + GUI_LOOK_FRAME_PAD_HEAD1_X + 1, y1 - ly + 1, x1 + lx + GUI_LOOK_FRAME_PAD_HEAD1_X + 1, y1 + ly, c_fg, 0);\r\n    Font_Print(font_id, Text, 2 + x1 + GUI_LOOK_FRAME_PAD_HEAD1_X + GUI_LOOK_FRAME_PAD_HEAD2_X, y1 - ly, c_text);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/g_tools.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_tools.h\n// GUI Tools - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define LOOK_UNKNOWN_   (-1)\n#define LOOK_THIN       (0)\n#define LOOK_ROUND      (1)\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    gui_frame_clear(ALLEGRO_BITMAP* dst, const t_frame* frame, ALLEGRO_COLOR color);\n\nvoid    gui_rect(int look, int x1, int y1, int x2, int y2, ALLEGRO_COLOR c_fg);\nvoid    gui_rect_titled(char *Text, t_font_id font_id, int look, int x1, int y1, int x2, int y2, ALLEGRO_COLOR c_fg, ALLEGRO_COLOR c_bg, ALLEGRO_COLOR c_font);\n\nstatic INLINE\nbool    frame_contains_point(const t_frame *frame, int point_x, int point_y)\n{\n    return (point_x >= frame->pos.x && point_y >= frame->pos.y && point_x < frame->pos.x + frame->size.x && point_y < frame->pos.y + frame->size.y);\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/g_update.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_update.c\r\n// GUI Update - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: the whole updating process is an hardcored mess.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_about.h\"\r\n#include \"app_cheatfinder.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"app_mapview.h\"\r\n#include \"app_memview.h\"\r\n#include \"app_palview.h\"\r\n#include \"app_techinfo.h\"\r\n#include \"app_textview.h\"\r\n#include \"app_tileview.h\"\r\n#include \"app_options.h\"\r\n#include \"debugger.h\"\r\n#include \"g_widget.h\"\r\n#include \"inputs_t.h\"\r\n#include \"skin_fx.h\"\r\n#include \"textbox.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    gui_update_applets();\r\nvoid    gui_update_applets_after_redraw();\r\n\r\n// Update the differents GUI applets\r\nvoid    gui_update_applets()\r\n{\r\n    // Update Memory Editors first,\r\n    // because it allows changing tile data/palette so we want that to be reflected\r\n    // (especially since dirty flags are being cleared each frame)\r\n    MemoryViewers_Update();\r\n    PROFILE_STEP(\"- MemoryViewers_Update\");\r\n\r\n    TilemapViewers_Update();\r\n    PROFILE_STEP(\"- TilemapViewers_Update\");\r\n\r\n    CheatFinders_Update();\r\n    PROFILE_STEP(\"- CheatFinders_Update\");\r\n\r\n    // Tile Viewer flag appropriate decoded VRAM tiles before emulation run\r\n    TileViewer_Update(&TileViewer);\r\n    PROFILE_STEP(\"- TileViewer_Update\");\r\n\r\n    PaletteViewer_Update();\r\n    PROFILE_STEP(\"- PaletteViewer_Update\");\r\n\r\n    //if (TB_Message.Active)\r\n    //    TB_Update (TB_Message.TB);\r\n    //if (apps.active.FM_Editor)\r\n    //    gui.box [apps.id.FM_Editor]->update();\r\n\r\n    TechInfo_Update();\r\n    FB_Update();\r\n    Options_Update();\r\n    AboutBox_Update();\r\n    TB_Message_Update();\r\n    TextViewer_Update(&TextViewer);\r\n    PROFILE_STEP(\"- misc\");\r\n\r\n    #ifdef SOUND_DEBUG_APPLET\r\n        SoundDebugApp_Update();\r\n    #endif\r\n\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n        Debugger_Update();\r\n    #endif\r\n}\r\n\r\nvoid    gui_update_applets_after_redraw()\r\n{\r\n    // Theme effects (blood/snow/hearts) : restoring data to the framebuffer\r\n    if (Skins_GetCurrentSkin()->effect != SKIN_EFFECT_NONE)\r\n        special_effects_update_after();\r\n}\r\n\r\nvoid    gui_update()\r\n{\r\n    // Theme effects (blood/snow/hearts) : saving data from the framebuffer\r\n    if (Skins_GetCurrentSkin()->effect != SKIN_EFFECT_NONE)\r\n        special_effects_update_before();\r\n\r\n    // Skins update\r\n    Skins_Update();\r\n\r\n    // Menus update\r\n    // Note: must be done before updating applets\r\n    gui_update_menus();\r\n\r\n    // Boxes update (move / compute dirtyness)\r\n    gui_update_boxes();\r\n    PROFILE_STEP(\"gui_update_boxes()\");\r\n\r\n    // Process box deletion\r\n    for (t_list* boxes = gui.boxes; boxes != NULL; )\r\n    {\r\n        t_gui_box* box = (t_gui_box*)boxes->elem;\r\n        boxes = boxes->next;\r\n        if (box->flags & GUI_BOX_FLAGS_DELETE)\r\n            gui_box_delete(box);\r\n    }\r\n\r\n    // Widgets update\r\n    widgets_call_update();\r\n    PROFILE_STEP(\"widgets_call_update()\");\r\n\r\n    // Call applets handlers\r\n    // Note: Must be done after updating widgets\r\n    gui_update_applets();\r\n    PROFILE_STEP(\"gui_update_applets()\");\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/g_update.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - g_update.h\n// GUI Update - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    gui_update();\nvoid    gui_update_applets_after_redraw();\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/g_widget.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_widget.c\r\n// GUI Widgets - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"g_tools.h\"\r\n#include \"g_widget.h\"\r\n#include \"inputs_t.h\"\r\n#include \"keyinfo.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define WIDGET_SCROLLBAR_MOUSE_TOLERANCE    (9999)      // In pixels\r\n\r\n//-----------------------------------------------------------------------------\r\n// Private Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_widget_data_closebox\r\n{\r\n    int                 active;\r\n    t_widget_callback   callback;\r\n};\r\n\r\nstruct t_widget_data_button\r\n{\r\n    char *                      label;\r\n    t_font_id                   font_id;\r\n    int                         highlight_on_click;\r\n    bool                        grayed_out;\r\n    t_widget_callback           callback;\r\n};\r\n\r\nstruct t_widget_data_scrollbar\r\n{\r\n    t_widget_scrollbar_type     scrollbar_type;\r\n    const int *                 v_max;\r\n    int *                       v_start;\r\n    int                         v_step_per_page;\r\n    void                        (*callback)(t_widget*);\r\n};\r\n\r\nstruct t_widget_data_checkbox\r\n{\r\n    bool *                      pvalue;\r\n    void                        (*callback)(t_widget*);\r\n} ;\r\n\r\nstruct t_widget_data_textbox_line\r\n{\r\n    const ALLEGRO_COLOR *       pcolor;\r\n    char *                      text;\r\n};\r\n\r\nstruct t_widget_data_textbox\r\n{\r\n    int                         lines_num;\r\n    int                         lines_max;\r\n    t_widget_data_textbox_line* lines;\r\n    t_font_id                   font_id;\r\n    const ALLEGRO_COLOR *       pcurrent_color;\r\n};\r\n\r\n// FIXME: add focus parameters: update inputs on box OR widget focus\r\n// FIXME: Do not show cursor without focus ?\r\nstruct t_widget_data_inputbox\r\n{\r\n    int                         flags;          // enum t_widget_inputbox_flags // FIXME-ENUM\r\n    t_widget_content_type       content_type;\r\n    bool                        overwrite_mode;\r\n    char *                      text;\r\n    char *                      tmp_buffer;\r\n    int                         length;\r\n    int                         length_max;\r\n    int                         sel_begin;\r\n    int                         sel_end;        // == cursor_pos\r\n    t_font_id                   font_id;\r\n    int                         cursor_blink_timer;\r\n    void                        (*callback_edit)(t_widget *inputbox);\r\n    void                        (*callback_enter)(t_widget *inputbox);\r\n    bool                        (*callback_completion)(t_widget *inputbox);\r\n    bool                        (*callback_history)(t_widget *inputbox, int level);\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic t_widget *  widget_new(t_gui_box *box, t_widget_type type, const t_frame *frame);\r\n\r\nvoid    widget_button_destroy(t_widget* w);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nbool    widgets_update_box(t_gui_box *b, int mouse_x, int mouse_y)\r\n{\r\n    bool widget_active = false;\r\n\r\n    for (t_list *widgets = b->widgets; widgets != NULL; widgets = widgets->next)\r\n    {\r\n        t_widget *w = (t_widget *)widgets->elem;\r\n        if (!w->enabled)\r\n            continue;\r\n\r\n        w->mouse_x = (mouse_x - w->frame.pos.x);\r\n        w->mouse_y = (mouse_y - w->frame.pos.y);\r\n        w->mouse_action = WIDGET_MOUSE_ACTION_NONE;\r\n        w->mouse_buttons = gui.mouse.buttons;\r\n        w->mouse_buttons_previous = gui.mouse.buttons_prev;\r\n        if ((w->mouse_x >= 0) && (w->mouse_y >= 0) && (w->mouse_x < w->frame.size.x) && (w->mouse_y < w->frame.size.y))\r\n        {\r\n            w->mouse_action |= WIDGET_MOUSE_ACTION_HOVER;\r\n\r\n            // FIXME-FOCUS\r\n            //if (gui_mouse.pressed_on == PRESSED_ON_NOTHING || gui_mouse.pressed_on == PRESSED_ON_WIDGET)\r\n            if (gui.mouse.focus == GUI_FOCUS_NONE || (gui.mouse.focus == GUI_FOCUS_WIDGET && gui.mouse.focus_widget == w))\r\n            {\r\n                if (w->mouse_buttons & w->mouse_buttons_mask)\r\n                {\r\n                    // FIXME-FOCUS\r\n                    //gui_mouse.pressed_on = PRESSED_ON_WIDGET;\r\n                    gui.mouse.focus = GUI_FOCUS_WIDGET;\r\n                    gui.mouse.focus_box = w->box;\r\n                    gui.mouse.focus_widget = w;\r\n                    w->mouse_action |= WIDGET_MOUSE_ACTION_CLICK;\r\n                    widget_active = true;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    return widget_active;\r\n}\r\n\r\nvoid    widgets_call_update()\r\n{\r\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\r\n    {\r\n        t_gui_box* b = (t_gui_box*)boxes->elem;\r\n        for (t_list* widgets = b->widgets; widgets != NULL; widgets = widgets->next)\r\n        {\r\n            t_widget* w = (t_widget *)widgets->elem;\r\n            if (w->enabled && w->update_func != NULL)\r\n                w->update_func(w);\r\n        }\r\n    }\r\n}\r\n\r\n// Create a new widget in given box\r\nt_widget *  widget_new(t_gui_box *box, t_widget_type type, const t_frame *frame)\r\n{\r\n    t_widget *w;\r\n\r\n    // Create widget\r\n    w = (t_widget *)malloc(sizeof (t_widget));\r\n\r\n    // Setup base members and clear all others\r\n    w->type                     = type;\r\n    w->enabled                  = true;\r\n    w->highlight                = false;\r\n    w->box                      = box;\r\n    w->frame                    = *frame;\r\n    w->mouse_x                  = -1;\r\n    w->mouse_y                  = -1;\r\n    w->mouse_buttons            = 0;\r\n    w->mouse_buttons_previous   = 0;\r\n    w->mouse_buttons_mask       = 0x00;\r\n    w->mouse_buttons_activation = 0;\r\n    w->destroy_func             = NULL;\r\n    w->redraw_func              = NULL;\r\n    w->update_func              = NULL;\r\n    w->data                     = NULL;\r\n    w->user_data                = NULL;\r\n\r\n    // Add to box\r\n    list_add_to_end(&box->widgets, w);\r\n\r\n    return (w);\r\n}\r\n\r\n// Note: caller is responsible for removing from list\r\nvoid        widget_destroy(t_widget *w)\r\n{\r\n    if (w->destroy_func != NULL)\r\n        w->destroy_func(w);\r\n    if (w->data != NULL)\r\n        free(w->data);\r\n    free(w);\r\n}\r\n\r\nvoid        widget_set_enabled(t_widget *w, bool v)\r\n{\r\n    if (w->enabled != v)\r\n    {\r\n        w->enabled = v;\r\n        w->box->flags |= GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n    }\r\n}\r\n\r\nvoid        widget_set_highlight(t_widget *w, bool v)\r\n{\r\n    w->highlight = v;\r\n}\r\n\r\nvoid        widget_set_mouse_buttons_mask(t_widget *w, int mouse_buttons_mask)\r\n{\r\n    w->mouse_buttons_mask = mouse_buttons_mask;\r\n}\r\n\r\nvoid *      widget_get_user_data(t_widget *w)\r\n{\r\n    // Check parameters\r\n    assert(w != NULL);\r\n\r\n    // Get user data\r\n    return (w->user_data);\r\n}\r\n\r\nvoid        widget_set_user_data(t_widget *w, void *user_data)\r\n{\r\n    // Check parameters\r\n    assert(w != NULL);\r\n\r\n    // Set user data\r\n    w->user_data = user_data;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nt_widget *  widget_closebox_add(t_gui_box *box, t_widget_callback callback)\r\n{\r\n    t_font_id font_id = (t_font_id)g_config.font_menus;\r\n\r\n    t_frame frame;\r\n    frame.size.x = Font_Height(font_id) - 5;\r\n    frame.size.y = Font_Height(font_id) - 5;\r\n    frame.pos.x = box->frame.size.x - (frame.size.x + 3);\r\n    frame.pos.y = -(frame.size.y + 5);\r\n\r\n    t_widget *w = widget_new(box, WIDGET_TYPE_CLOSEBOX, &frame);\r\n    widget_set_mouse_buttons_mask(w, 1);\r\n\r\n    w->redraw_func = widget_closebox_redraw;\r\n    w->update_func = widget_closebox_update;\r\n\r\n    w->data = malloc(sizeof (t_widget_data_closebox));\r\n    t_widget_data_closebox *wd = (t_widget_data_closebox*)w->data;\r\n    wd->active = false;\r\n    wd->callback = callback;\r\n\r\n    return w;\r\n}\r\n\r\nvoid        widget_closebox_redraw(t_widget *w)\r\n{\r\n    t_widget_data_closebox* wd = (t_widget_data_closebox*)w->data;\r\n\r\n    w->frame.pos.x = w->box->frame.size.x - (w->frame.size.x + 1);\r\n    w->frame.pos.y = -(w->frame.size.y + 5);\r\n\r\n    // Get appropriate color\r\n    // Note: using titlebar text active/inactive color to display the closebox star\r\n    ALLEGRO_COLOR color = (w->mouse_action & WIDGET_MOUSE_ACTION_HOVER) ? COLOR_SKIN_WINDOW_TITLEBAR_TEXT : COLOR_SKIN_WINDOW_TITLEBAR_TEXT_UNACTIVE;\r\n\r\n    // Draw box-closing star using the LARGE font\r\n    al_set_target_bitmap(gui_buffer);\r\n    al_draw_filled_rectangle(\r\n        w->box->frame.pos.x + w->frame.pos.x + 2,                   w->box->frame.pos.y + w->frame.pos.y + 2, \r\n        w->box->frame.pos.x + w->frame.pos.x + w->frame.size.x - 2, w->box->frame.pos.y + w->frame.pos.y + w->frame.size.y - 2, color);\r\n    al_draw_rectangle(\r\n        w->box->frame.pos.x + w->frame.pos.x + 2,                   w->box->frame.pos.y + w->frame.pos.y + 2, \r\n        w->box->frame.pos.x + w->frame.pos.x + w->frame.size.x - 2, w->box->frame.pos.y + w->frame.pos.y + w->frame.size.y - 2, COLOR_SKIN_WINDOW_BACKGROUND, 1);\r\n}\r\n\r\nvoid        widget_closebox_update(t_widget *w)\r\n{\r\n    t_widget_data_closebox* wd = (t_widget_data_closebox*)w->data;\r\n\r\n    // Mouse handling\r\n    if (!wd->active)\r\n    {\r\n        if ((w->mouse_action & WIDGET_MOUSE_ACTION_HOVER) && (w->mouse_buttons & 1))\r\n            wd->active = true;\r\n    }\r\n    else\r\n    {\r\n        if (!(w->mouse_action & WIDGET_MOUSE_ACTION_HOVER))\r\n        {\r\n            wd->active = false;\r\n        }\r\n        else\r\n        {\r\n            if ((w->mouse_buttons_previous & 1) && !(w->mouse_buttons & 1))\r\n            {\r\n                wd->active = false;\r\n                wd->callback(w);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Keyboard\r\n    // CTRL-F4 close window\r\n    if (gui_box_has_focus(w->box))\r\n    {\r\n        if ((g_keyboard_modifiers & ALLEGRO_KEYMOD_CTRL) && Inputs_KeyPressed(ALLEGRO_KEY_F4, FALSE))\r\n            wd->callback(w);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nt_widget *  widget_button_add(t_gui_box *box, const t_frame *frame, int mouse_buttons_mask, t_widget_callback callback, t_font_id font_id, const char *label, void* user_data)\r\n{\r\n    t_widget* w = widget_new(box, WIDGET_TYPE_BUTTON, frame);\r\n    widget_set_mouse_buttons_mask(w, mouse_buttons_mask);\r\n\r\n    w->destroy_func = widget_button_destroy;\r\n    w->redraw_func = widget_button_redraw;\r\n    w->update_func = widget_button_update;\r\n\r\n    w->data = malloc(sizeof (t_widget_data_button));\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n    wd->label = label ? strdup(label) : NULL;\r\n    wd->font_id = font_id;\r\n    wd->highlight_on_click = 0;\r\n    wd->grayed_out = FALSE;\r\n    wd->callback = callback;\r\n\r\n    if (user_data != NULL)\r\n        w->user_data = user_data;\r\n    \r\n    return w;\r\n}\r\n\r\nvoid    widget_button_destroy(t_widget* w)\r\n{\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n    if (wd->label)\r\n        free(wd->label);\r\n}\r\n\r\nvoid    widget_button_update(t_widget *w)\r\n{\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n\r\n    // Check if we need to fire the callback\r\n    bool clicked = false;\r\n    if (!wd->grayed_out)\r\n        if ((w->mouse_action & WIDGET_MOUSE_ACTION_CLICK) && (w->mouse_buttons & w->mouse_buttons_mask) && !(w->mouse_buttons_previous & w->mouse_buttons_mask))\r\n            clicked = true;\r\n\r\n    // Update mouse buttons\r\n    // w->mouse_buttons_previous = w->mouse_buttons;\r\n    w->mouse_buttons_activation = w->mouse_buttons;\r\n    w->mouse_buttons = 0;\r\n    if (wd->highlight_on_click > 0)\r\n        wd->highlight_on_click--;\r\n\r\n    // Fire the callback. Note that it is done AFTER updating the mouse buttons, this\r\n    // is to avoid recursive calls if the callback ask for a GUI update (something\r\n    // which the file browser does when clicking on \"Load Names\").\r\n    if (clicked)\r\n        widget_button_trigger(w);\r\n}\r\n\r\nvoid    widget_button_trigger(t_widget* w)\r\n{\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n    wd->highlight_on_click = 6;\r\n    if (wd->callback)\r\n        wd->callback(w);\r\n}\r\n\r\nvoid        widget_button_redraw(t_widget *w)\r\n{\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n    \r\n    if (wd->font_id == FONTID_NONE)\r\n        return;\r\n\r\n    const ALLEGRO_COLOR bg_color = (w->highlight || wd->highlight_on_click>0) ? COLOR_SKIN_WIDGET_GENERIC_SELECTION : COLOR_SKIN_WIDGET_GENERIC_BACKGROUND;\r\n    const ALLEGRO_COLOR text_color = wd->grayed_out ? COLOR_SKIN_WIDGET_GENERIC_TEXT_UNACTIVE : COLOR_SKIN_WIDGET_GENERIC_TEXT;\r\n    const t_frame *frame = &w->frame;\r\n\r\n    al_set_target_bitmap(w->box->gfx_buffer);\r\n    al_draw_filled_rectangle(frame->pos.x + 2, frame->pos.y + 2, frame->pos.x + frame->size.x - 1, frame->pos.y + frame->size.y - 1, bg_color);\r\n    if (Font_Height(wd->font_id) > 11)\r\n        gui_rect(LOOK_ROUND, frame->pos.x, frame->pos.y, frame->pos.x + frame->size.x, frame->pos.y + frame->size.y, COLOR_SKIN_WIDGET_GENERIC_BORDER);\r\n    else\r\n        gui_rect(LOOK_THIN, frame->pos.x, frame->pos.y, frame->pos.x + frame->size.x, frame->pos.y + frame->size.y, COLOR_SKIN_WIDGET_GENERIC_BORDER);\r\n    if (wd->label)\r\n        Font_Print(wd->font_id, wd->label, frame->pos.x + ((frame->size.x - Font_TextWidth(wd->font_id, wd->label)) / 2), frame->pos.y + ((frame->size.y - Font_Height(wd->font_id)) / 2) + 1, text_color);\r\n}\r\n\r\nvoid    widget_button_set_grayed_out(t_widget *w, bool grayed_out)\r\n{\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n    if (wd->grayed_out != grayed_out)\r\n    {\r\n        wd->grayed_out = grayed_out;\r\n    }\r\n}\r\n\r\nvoid    widget_button_set_label(t_widget *w, const char* label)\r\n{\r\n    t_widget_data_button* wd = (t_widget_data_button*)w->data;\r\n    if (wd->label)\r\n        free(wd->label);\r\n    wd->label = label ? strdup(label) : NULL;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nt_widget *  widget_scrollbar_add(t_gui_box *box, t_widget_scrollbar_type scrollbar_type, const t_frame *frame, const int *v_max, int *v_start, int v_step_per_page, t_widget_callback callback)\r\n{\r\n    t_widget* w = widget_new(box, WIDGET_TYPE_SCROLLBAR, frame);\r\n    widget_set_mouse_buttons_mask(w, 1);\r\n\r\n    w->redraw_func = widget_scrollbar_redraw;\r\n    w->update_func = widget_scrollbar_update;\r\n\r\n    w->data = (t_widget_data_scrollbar *)malloc (sizeof (t_widget_data_scrollbar));\r\n    t_widget_data_scrollbar* wd = (t_widget_data_scrollbar*)w->data;\r\n    wd->scrollbar_type = scrollbar_type;\r\n    wd->v_max = v_max;\r\n    wd->v_start = v_start;\r\n    wd->v_step_per_page = v_step_per_page;\r\n    wd->callback = callback;\r\n\r\n    return w;\r\n}\r\n\r\nvoid    widget_scrollbar_update(t_widget *w)\r\n{\r\n    t_widget_data_scrollbar* wd = (t_widget_data_scrollbar*)w->data;\r\n\r\n    const int mx = w->mouse_x;\r\n    const int my = w->mouse_y;\r\n\r\n    if (!(w->mouse_buttons & w->mouse_buttons_mask))\r\n        return;\r\n\r\n    // First click needs to be inside. After, we tolerate moving a little outside.\r\n    if (gui.mouse.focus_widget != w)\r\n        return;\r\n\r\n    if ((w->mouse_buttons_previous & w->mouse_buttons_mask) == 0)\r\n        return;\r\n\r\n    if (wd->scrollbar_type == WIDGET_SCROLLBAR_TYPE_VERTICAL)\r\n    {\r\n        if (mx < 0-WIDGET_SCROLLBAR_MOUSE_TOLERANCE || mx >= w->frame.size.x + WIDGET_SCROLLBAR_MOUSE_TOLERANCE)\r\n            return;\r\n        if (my < 0 || my >= w->frame.size.y)\r\n            return;\r\n    }\r\n    else if (wd->scrollbar_type == WIDGET_SCROLLBAR_TYPE_HORIZONTAL)\r\n    {\r\n        if (mx < 0 || mx >= w->frame.size.x)\r\n            return;\r\n        if (my < 0-WIDGET_SCROLLBAR_MOUSE_TOLERANCE || my >= w->frame.size.y + WIDGET_SCROLLBAR_MOUSE_TOLERANCE)\r\n           return;\r\n    }\r\n\r\n    // Move\r\n    int v_start;\r\n    switch (wd->scrollbar_type)\r\n    {\r\n    case WIDGET_SCROLLBAR_TYPE_VERTICAL:\r\n        v_start = ((my * *wd->v_max) / w->frame.size.y) - (wd->v_step_per_page / 2);\r\n        break;\r\n    case WIDGET_SCROLLBAR_TYPE_HORIZONTAL:\r\n        v_start = ((mx * *wd->v_max) / w->frame.size.x) - (wd->v_step_per_page / 2);\r\n        break;\r\n    }\r\n\r\n    // Clamp\r\n    if (v_start > *wd->v_max - wd->v_step_per_page) \r\n        v_start = *wd->v_max - wd->v_step_per_page;\r\n    if (v_start < 0) \r\n        v_start = 0;\r\n    *wd->v_start = v_start;\r\n\r\n    // Callback\r\n    if (wd->callback != NULL)\r\n        wd->callback(w);\r\n}\r\n\r\nvoid        widget_scrollbar_redraw(t_widget *w)\r\n{\r\n    t_widget_data_scrollbar* wd = (t_widget_data_scrollbar*)w->data;\r\n\r\n    // Clear bar\r\n    al_set_target_bitmap(w->box->gfx_buffer);\r\n    al_draw_filled_rectangle(w->frame.pos.x, w->frame.pos.y, w->frame.pos.x + w->frame.size.x + 1, w->frame.pos.y + w->frame.size.y + 1, COLOR_SKIN_WIDGET_SCROLLBAR_BACKGROUND);\r\n    al_draw_rectangle(w->frame.pos.x - 0.5f, w->frame.pos.y - 0.5f, w->frame.pos.x + w->frame.size.x + 1.5f, w->frame.pos.y + w->frame.size.y + 1.5f, COLOR_SKIN_WINDOW_SEPARATORS, 1.0f);\r\n\r\n    // Draw position box\r\n    float max = *wd->v_max;\r\n    if (max < wd->v_step_per_page) \r\n        max = wd->v_step_per_page;\r\n\r\n    switch (wd->scrollbar_type)\r\n    {\r\n    case WIDGET_SCROLLBAR_TYPE_VERTICAL:\r\n        {\r\n            const float pos = w->frame.pos.y + ((*wd->v_start * w->frame.size.y) / max);\r\n            const float size = (wd->v_step_per_page * w->frame.size.y) / max;\r\n            al_draw_filled_rectangle(w->frame.pos.x, pos, w->frame.pos.x + w->frame.size.x + 1, pos + size + 1, COLOR_SKIN_WIDGET_SCROLLBAR_SCROLLER);\r\n            break;\r\n        }\r\n    case WIDGET_SCROLLBAR_TYPE_HORIZONTAL:\r\n        {\r\n            const float pos = w->frame.pos.x + ((*wd->v_start * w->frame.size.x) / max);\r\n            const float size = (wd->v_step_per_page * w->frame.size.x) / max;\r\n            al_draw_filled_rectangle(pos, w->frame.pos.y, pos + size + 1, w->frame.pos.y + w->frame.size.y + 1, COLOR_SKIN_WIDGET_SCROLLBAR_SCROLLER);\r\n            break;\r\n        }\r\n    }\r\n}\r\n\r\nvoid    widget_scrollbar_set_page_step(t_widget *w, int page_step)\r\n{\r\n    t_widget_data_scrollbar* wd = (t_widget_data_scrollbar*)w->data;\r\n    wd->v_step_per_page = page_step;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nt_widget *  widget_checkbox_add(t_gui_box *box, const t_frame *frame, bool *pvalue, t_widget_callback callback)\r\n{\r\n    t_widget* w = widget_new(box, WIDGET_TYPE_CHECKBOX, frame);\r\n    widget_set_mouse_buttons_mask(w, 1);\r\n\r\n    w->redraw_func = widget_checkbox_redraw;\r\n    w->update_func = widget_checkbox_update;\r\n\r\n    w->data = malloc(sizeof (t_widget_data_checkbox));\r\n    t_widget_data_checkbox* wd = (t_widget_data_checkbox*)w->data;\r\n    wd->pvalue = pvalue;\r\n    wd->callback = callback;\r\n\r\n    return w;\r\n}\r\n\r\n// FIXME: potential bug there, if wd->pvalue is NULL..\r\nvoid        widget_checkbox_update(t_widget *w)\r\n{\r\n    t_widget_data_checkbox *wd = (t_widget_data_checkbox*)w->data;\r\n\r\n    if ((w->mouse_buttons & w->mouse_buttons_mask) && (w->mouse_buttons_previous == 0) && (w->mouse_action & WIDGET_MOUSE_ACTION_CLICK))\r\n    {\r\n        *(wd->pvalue) ^= 1; // inverse flag\r\n        if (wd->callback != NULL)\r\n            wd->callback(w);\r\n    }\r\n    //w->mouse_buttons_previous = w->mouse_buttons;\r\n    //w->mouse_buttons = 0;\r\n}\r\n\r\nvoid        widget_checkbox_redraw(t_widget *w)\r\n{\r\n    t_widget_data_checkbox* wd = (t_widget_data_checkbox*)w->data;\r\n\r\n    al_set_target_bitmap(w->box->gfx_buffer);\r\n    al_draw_rectangle(w->frame.pos.x + 0.5f, w->frame.pos.y + 0.5f, w->frame.pos.x + w->frame.size.x + 0.5f, w->frame.pos.y + w->frame.size.y + 0.5f, COLOR_SKIN_WIDGET_GENERIC_BORDER, 1.0f);\r\n    al_draw_filled_rectangle(w->frame.pos.x + 1, w->frame.pos.y + 1, w->frame.pos.x + w->frame.size.x, w->frame.pos.y + w->frame.size.y, COLOR_SKIN_WIDGET_GENERIC_BACKGROUND);\r\n    if (wd->pvalue && *(wd->pvalue))\r\n    {\r\n        // Note: using widget generic text color to display the cross\r\n        al_draw_line(w->frame.pos.x + 2, w->frame.pos.y + 2, w->frame.pos.x + w->frame.size.x - 1, w->frame.pos.y + w->frame.size.y - 1, COLOR_SKIN_WIDGET_GENERIC_TEXT, 0);\r\n        al_draw_line(w->frame.pos.x + w->frame.size.x - 1, w->frame.pos.y + 2, w->frame.pos.x + 2, w->frame.pos.y + w->frame.size.y - 1, COLOR_SKIN_WIDGET_GENERIC_TEXT, 0);\r\n    }\r\n}\r\n\r\nvoid        widget_checkbox_set_pvalue(t_widget *w, bool *pvalue)\r\n{\r\n    t_widget_data_checkbox* wd = (t_widget_data_checkbox*)w->data;\r\n    wd->pvalue = pvalue;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid        widget_textbox_destroy(t_widget *w);\r\n\r\nt_widget *  widget_textbox_add(t_gui_box *box, const t_frame *frame, t_font_id font_id)\r\n{\r\n    // Create widget\r\n    t_widget* w = widget_new(box, WIDGET_TYPE_TEXTBOX, frame);\r\n    w->destroy_func = widget_textbox_destroy;\r\n    w->redraw_func = widget_textbox_redraw;\r\n    w->update_func = NULL;\r\n\r\n    // Setup values & parameters\r\n    w->data = malloc(sizeof (t_widget_data_textbox));\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n    wd->lines_num       = 0;\r\n    wd->lines_max       = 100;\r\n    wd->font_id         = font_id;\r\n    wd->pcurrent_color  = &COLOR_SKIN_WINDOW_TEXT;\r\n\r\n    wd->lines = (t_widget_data_textbox_line*)malloc(sizeof(t_widget_data_textbox_line) * wd->lines_max);\r\n    for (int i = 0; i < wd->lines_max; i++)\r\n    {\r\n        wd->lines[i].pcolor = wd->pcurrent_color;\r\n        wd->lines[i].text = NULL;\r\n    }\r\n\r\n    // Return newly created widget\r\n    return (w);\r\n}\r\n\r\nvoid        widget_textbox_destroy(t_widget *w)\r\n{\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n    for (int i = 0; i < wd->lines_max; i++)\r\n        free(wd->lines[i].text);\r\n    free(wd->lines);\r\n}\r\n\r\nvoid        widget_textbox_redraw(t_widget *w)\r\n{\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n\r\n    const int fh = Font_Height(wd->font_id);\r\n    const int x = w->frame.pos.x;\r\n    int y = w->frame.pos.y + w->frame.size.y;\r\n\r\n    al_set_target_bitmap(w->box->gfx_buffer);\r\n    al_draw_filled_rectangle(w->frame.pos.x, w->frame.pos.y, w->frame.pos.x + w->frame.size.x + 1, w->frame.pos.y + w->frame.size.y + 1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n    for (int i = 0; i < wd->lines_num; i++)\r\n    {\r\n        if (y < w->frame.pos.y - fh)\r\n            break;\r\n        \r\n        t_widget_data_textbox_line* entry = &wd->lines[i];\r\n\r\n        const int wrap_width = w->frame.size.x;\r\n        const int h = Font_TextHeight(wd->font_id, entry->text, wrap_width);\r\n        y -= h;\r\n\r\n        if (wd->lines[i].text[0] == EOSTR)\r\n            continue;\r\n        Font_Print(wd->font_id, entry->text, x, y, *entry->pcolor, wrap_width);\r\n    }\r\n}\r\n\r\nvoid        widget_textbox_clear(t_widget *w)\r\n{\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n\r\n    for (int i = 0; i < wd->lines_num; i++)\r\n        wd->lines[i].text[0] = EOSTR;\r\n    wd->lines_num = 0;\r\n}\r\n\r\nvoid        widget_textbox_set_current_color(t_widget *w, const ALLEGRO_COLOR *pcurrent_color)\r\n{\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n    wd->pcurrent_color = pcurrent_color;\r\n}\r\n\r\nvoid        widget_textbox_print_scroll(t_widget *w, bool wrap, const char *line)\r\n{\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n\r\n    // Shift all lines by one position\r\n    // FIXME-OPT: circular queue\r\n    if (wd->lines_num > 0)\r\n    {\r\n        if (wd->lines[wd->lines_max - 1].text)\r\n        {\r\n            free(wd->lines[wd->lines_max - 1].text);\r\n            wd->lines[wd->lines_max - 1].text = NULL;\r\n        }\r\n\r\n        for (int n = wd->lines_max - 1; n > 0; n--)\r\n            wd->lines[n] = wd->lines[n - 1];\r\n        wd->lines[0].text = NULL;\r\n    }\r\n\r\n    // Increment number of lines counter\r\n    if (wd->lines_num < wd->lines_max)\r\n        wd->lines_num++;\r\n\r\n    // Copy new line\r\n    if (wd->lines_max > 0)\r\n    {\r\n        wd->lines[0].text = strdup(line);\r\n        wd->lines[0].pcolor = wd->pcurrent_color;\r\n    }\r\n}\r\n\r\n/*\r\nvoid        widget_textbox_print_scroll(t_widget *w, int wrap, const char *line)\r\n{\r\n    t_widget_data_textbox* wd = (t_widget_data_textbox*)w->data;\r\n\r\n    int     pos;\r\n    char    buf [MSG_MAX_LEN];\r\n    const char *    src;\r\n\r\n    if (!wrap || line[0] == EOSTR || Font_TextLength(wd->font_id, line) <= w->frame.size.x)\r\n    {\r\n        widget_textbox_print_scroll_nowrap(w, line);\r\n        return;\r\n    }\r\n\r\n    pos = 0;\r\n    src = line;\r\n    while (*src != EOSTR)\r\n    {\r\n        // Add one character\r\n        buf[pos] = *src;\r\n        buf[pos+1] = EOSTR;\r\n\r\n        // Compute length\r\n        // FIXME-OPT: Dumb\r\n        const int char_w = Font_TextLength(wd->font_id, buf);\r\n        if (char_w > w->frame.size.x)\r\n        {\r\n            char *blank = strrchr (buf, ' ');\r\n            if (blank != NULL)\r\n            {\r\n                int d = buf + pos - blank;\r\n                src -= d; // rewind\r\n                pos -= d;\r\n                buf[pos] = EOSTR;\r\n            }\r\n            else\r\n            {\r\n                // No blank... cut a current character\r\n                buf[pos] = EOSTR;\r\n                src--; // Rewind by one to display the character later\r\n                pos--;\r\n            }\r\n            widget_textbox_print_scroll_nowrap(w, buf);\r\n            pos = 0;\r\n        }\r\n        else\r\n        {\r\n            pos++;\r\n        }\r\n        src++;\r\n    }\r\n\r\n    // Some text left, print it\r\n    if (pos != 0)\r\n        widget_textbox_print_scroll_nowrap(w, buf);\r\n}\r\n*/\r\n\r\nvoid        widget_textbox_printf_scroll(t_widget *w, bool wrap, const char* fmt, ...)\r\n{\r\n    char buf[1024];\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    vsnprintf(buf, countof(buf), fmt, args);\r\n    va_end(args);\r\n    widget_textbox_print_scroll(w, wrap, buf);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    widget_inputbox_destroy(t_widget *w);\r\n\r\nt_widget *  widget_inputbox_add(t_gui_box *box, const t_frame *frame, int length_max, t_font_id font_id, void (*callback_enter)(t_widget *))\r\n{\r\n    t_widget *w;\r\n    t_widget_data_inputbox *wd;\r\n\r\n    // Get and verify size\r\n    int size_x = frame->size.x;\r\n    int size_y = frame->size.y;\r\n    assert(size_x != -1);\r\n    if (size_y == -1)\r\n       size_y = Font_Height(font_id) + 4;\r\n\r\n    // Create widget\r\n    w = widget_new(box, WIDGET_TYPE_INPUTBOX, frame);\r\n    w->frame.size.y = size_y;\r\n    widget_set_mouse_buttons_mask(w, 1);\r\n\r\n    w->destroy_func = widget_inputbox_destroy;\r\n    w->redraw_func = widget_inputbox_redraw;\r\n    w->update_func = widget_inputbox_update;\r\n\r\n    // Setup values & parameters\r\n    w->data = malloc(sizeof (t_widget_data_inputbox));\r\n    wd = (t_widget_data_inputbox*)w->data;\r\n    wd->flags               = WIDGET_INPUTBOX_FLAGS_DEFAULT;\r\n    wd->content_type        = WIDGET_CONTENT_TYPE_TEXT;\r\n    wd->overwrite_mode      = false;\r\n    wd->length_max          = length_max;\r\n    assert(length_max != -1); // Currently, length must be fixed\r\n    wd->text                = new char[length_max + 1];\r\n    strcpy(wd->text, \"\");\r\n    wd->tmp_buffer          = new char[length_max + 1];\r\n    wd->length              = 0;\r\n    wd->sel_begin = wd->sel_end = 0;\r\n    wd->font_id             = font_id;\r\n    wd->cursor_blink_timer  = 0;\r\n    wd->callback_enter      = callback_enter;\r\n    wd->callback_edit       = NULL;\r\n    wd->callback_completion = NULL;\r\n    wd->callback_history    = NULL;\r\n\r\n    // Return newly created widget\r\n    return (w);\r\n}\r\n\r\nvoid    widget_inputbox_destroy(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    delete[] wd->text;\r\n    delete[] wd->tmp_buffer;\r\n}\r\n\r\nvoid    widget_inputbox_delete_selection(t_widget* w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n\r\n    // Delete selection\r\n    if (widget_inputbox_has_selection(w))\r\n    {\r\n        const int sel_len = MAX(wd->sel_begin, wd->sel_end) - MIN(wd->sel_begin, wd->sel_end);\r\n        for (int i = MAX(wd->sel_begin, wd->sel_end); i < wd->length; i++)\r\n            wd->text[i - sel_len] = wd->text[i];\r\n        wd->sel_begin = wd->sel_end = MIN(wd->sel_begin, wd->sel_end);\r\n        wd->length -= sel_len;\r\n    }\r\n}\r\n\r\nbool    widget_inputbox_insert_chars(t_widget* w, const char* str)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n\r\n    widget_inputbox_delete_selection(w);\r\n    assert(!widget_inputbox_has_selection(w));\r\n\r\n    // How much can we fit?\r\n    int str_len = strlen(str);\r\n    if (wd->overwrite_mode)\r\n    {\r\n        str_len = MIN(str_len, wd->length_max - wd->sel_end);\r\n        assert(wd->sel_end + str_len <= wd->length_max);\r\n    }\r\n    else\r\n    {\r\n        str_len = MIN(str_len, wd->length_max - wd->length);\r\n        assert(wd->length + str_len <= wd->length_max);\r\n    }\r\n\r\n    if (str_len == 0)\r\n        return false;\r\n    //const char* str_end = str + str_len;\r\n\r\n    if (!wd->overwrite_mode)\r\n    {\r\n        // Shift everything that is after cursor pos\r\n        for (int i = wd->length; i > wd->sel_end; i--)\r\n            wd->text[i] = wd->text[i-str_len];\r\n    }\r\n\r\n    // Insert at cursor pos\r\n    for (int i = 0; i < str_len; i++)\r\n        wd->text[wd->sel_end + i] = str[i];\r\n    wd->sel_begin = wd->sel_end = wd->sel_end + str_len;\r\n    wd->length += str_len;\r\n    wd->text[wd->length] = '\\0';\r\n\r\n    // Edit callback\r\n    if (wd->callback_edit)\r\n        wd->callback_edit(w);\r\n\r\n    // Set dirty flag\r\n    wd->cursor_blink_timer = 0;\r\n\r\n    return true;\r\n}\r\n\r\nvoid    widget_inputbox_delete_current_char(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n\r\n    wd->cursor_blink_timer = 0;\r\n\r\n    assert(!widget_inputbox_has_selection(w));\r\n\r\n    // Shift everything that is after cursor\r\n    for (int i = wd->sel_end; i < wd->length; i++)\r\n        wd->text[i-1] = wd->text[i];\r\n    wd->sel_begin = wd->sel_end = wd->sel_end - 1;\r\n    wd->length--;\r\n    wd->text[wd->length] = '\\0';\r\n}\r\n\r\nstatic char widget_inputbox_translate_char(t_widget* w, char c)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n\r\n    if (!isprint(c))\r\n        return 0;\r\n\r\n    if (wd->content_type == WIDGET_CONTENT_TYPE_DECIMAL)\r\n    {\r\n        if (!(c >= '0' && c <= '9'))\r\n            return 0;\r\n    }\r\n    else if (wd->content_type == WIDGET_CONTENT_TYPE_HEXADECIMAL)\r\n    {\r\n        if (c >= 'a' && c <= 'f')\r\n            c += 'A' - 'a';\r\n        if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))\r\n            return 0;\r\n    }\r\n    else if (wd->content_type == WIDGET_CONTENT_TYPE_DEC_HEX_BIN)\r\n    {\r\n        if (c >= 'a' && c <= 'f')\r\n            c += 'A' - 'a';\r\n        if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c == '$' || c == '%' || c == '#')))\r\n            return 0;\r\n    }\r\n    return c;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// widget_inputbox_update (t_widget *)\r\n// Update input box based on user keyboard inputs\r\n//-----------------------------------------------------------------------------\r\nvoid        widget_inputbox_update(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n\r\n    const int tm_delay = 15;\r\n    const int tm_rate = 1;\r\n\r\n    const bool is_ctrl_pressed = (g_keyboard_modifiers & ALLEGRO_KEYMOD_CTRL) != 0;\r\n    const bool is_shift_pressed = (g_keyboard_modifiers & ALLEGRO_KEYMOD_SHIFT) != 0;\r\n\r\n    bool edited = false;\r\n\r\n    // Check if we have focus\r\n    // FIXME: This is completely a hack since it checks BOX focus (and not Widget focus,\r\n    // which is not possible right now). So if there's more than one inputbox in the same\r\n    // box, currently both will be updated.\r\n    if (!gui_box_has_focus(w->box))\r\n    {\r\n        wd->cursor_blink_timer = 0;\r\n        return;\r\n    }\r\n    wd->cursor_blink_timer = (wd->cursor_blink_timer + 1) % 70;\r\n\r\n    // Msg(MSGT_DEBUG, \"cascii = %c, cscan = %04x\", Inputs.KeyPressed.ascii, Inputs.KeyPressed.scancode);\r\n\r\n    // Mouse click set position\r\n    if (!(wd->flags & WIDGET_INPUTBOX_FLAGS_NO_MOVE_CURSOR))\r\n    {\r\n        if ((w->mouse_buttons & w->mouse_buttons_mask) && (w->mouse_buttons_previous == 0) && (w->mouse_action & WIDGET_MOUSE_ACTION_CLICK))\r\n        {\r\n            //const int mx = w->mouse_x -= (2 + 3); \r\n            int mx = w->mouse_x - (2 + 3); // 2+3=start of text entry, see _Redraw() // FIXME\r\n            if (mx <= 0)\r\n            {\r\n                widget_inputbox_set_cursor_pos(w, 0);\r\n            }\r\n            else\r\n            {\r\n                // Locate clicked-on character\r\n                int i;\r\n                char s[2] = { EOSTR, EOSTR };\r\n                for (i = 0; i < wd->length; i++)\r\n                {\r\n                    s[0] = wd->text[i];\r\n                    mx -= Font_TextWidth(wd->font_id, s);\r\n                    if (mx <= 0)\r\n                        break;\r\n                }\r\n                widget_inputbox_set_cursor_pos(w, i);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Check for printable input keys\r\n    t_list *keypress_queue = Inputs.KeyPressedQueue;\r\n    while (keypress_queue != NULL)\r\n    {\r\n        t_key_press* keypress = (t_key_press*)keypress_queue->elem;\r\n        keypress_queue = keypress_queue->next;\r\n\r\n        if (isprint(keypress->ascii))\r\n        {\r\n            const char c = widget_inputbox_translate_char(w, keypress->ascii);\r\n            if (c != 0)\r\n            {\r\n                // Insert character\r\n                char sc[2];\r\n                sc[0] = c;\r\n                sc[1] = '\\0';\r\n                widget_inputbox_insert_chars(w, sc);\r\n                Inputs_KeyPressQueue_Remove(keypress);\r\n                return;\r\n            }\r\n        }\r\n    }\r\n\r\n    // Clipboard Copy\r\n    if (is_ctrl_pressed && Inputs_KeyPressed(ALLEGRO_KEY_C, true))\r\n    {\r\n        if (wd->flags & WIDGET_INPUTBOX_FLAGS_NO_SELECTION)\r\n        {\r\n            OSD_ClipboardSetText(wd->text, wd->text + wd->length);\r\n        }\r\n        else if (wd->sel_begin != wd->sel_end)\r\n        {\r\n            OSD_ClipboardSetText(wd->text + MIN(wd->sel_begin, wd->sel_end), wd->text + MAX(wd->sel_begin, wd->sel_end));\r\n        }\r\n    }\r\n\r\n    // Clipboard Paste (slower repeat rate)\r\n    if (is_ctrl_pressed && Inputs_KeyPressed_Repeat(ALLEGRO_KEY_V, false, tm_delay, tm_rate*3))\r\n    {\r\n        if (char* s = OSD_ClipboardGetText())\r\n        {\r\n            bool allowed = true;\r\n            for (int i = 0; s[i]; i++)\r\n            {\r\n                if (widget_inputbox_translate_char(w, s[i]) == 0)\r\n                {\r\n                    allowed = false;\r\n                    break;\r\n                }\r\n            }\r\n            if (allowed)\r\n                widget_inputbox_insert_chars(w, s);\r\n            free(s);\r\n        }\r\n    }\r\n\r\n    if (!(wd->flags & WIDGET_INPUTBOX_FLAGS_NO_DELETE))\r\n    {\r\n        // Clipboard Cut\r\n        if (is_ctrl_pressed && Inputs_KeyPressed(ALLEGRO_KEY_X, true))\r\n        {\r\n            if (wd->sel_begin != wd->sel_end)\r\n            {\r\n                OSD_ClipboardSetText(wd->text + MIN(wd->sel_begin, wd->sel_end), wd->text + MAX(wd->sel_begin, wd->sel_end));\r\n                widget_inputbox_delete_selection(w);\r\n            }\r\n        }\r\n\r\n        // Backspace\r\n        if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_BACKSPACE, FALSE, tm_delay, tm_rate))\r\n        {\r\n            if (widget_inputbox_has_selection(w))\r\n            {\r\n                widget_inputbox_delete_selection(w);\r\n            }\r\n            else if (wd->sel_end > 0)\r\n            {\r\n                // Delete previous character\r\n                widget_inputbox_delete_current_char(w);\r\n                edited = TRUE;\r\n            }\r\n\r\n            // HACK: This avoid resetting while backspacing in the widget\r\n            if (Inputs_KeyPressed(ALLEGRO_KEY_BACKSPACE, FALSE))\r\n                Inputs_KeyEat(ALLEGRO_KEY_BACKSPACE);\r\n        }\r\n\r\n        // Delete\r\n        if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_DELETE, TRUE, tm_delay, tm_rate))\r\n        {\r\n            if (widget_inputbox_has_selection(w))\r\n            {\r\n                widget_inputbox_delete_selection(w);\r\n            }\r\n            else if (wd->sel_end < wd->length)\r\n            {\r\n                // Delete next character\r\n                wd->sel_begin++;\r\n                wd->sel_end++;\r\n                widget_inputbox_delete_current_char(w);\r\n                edited = TRUE;\r\n            }\r\n        }\r\n    }\r\n\r\n    if (!(wd->flags & WIDGET_INPUTBOX_FLAGS_NO_MOVE_CURSOR))\r\n    {\r\n        // Left/Right arrows: move cursor\r\n        const char* word_delimiters = \" \\t\\r\\n,:;\";\r\n        if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_LEFT, FALSE, tm_delay, tm_rate))\r\n        {\r\n            int offset = -1;\r\n            if (is_ctrl_pressed)\r\n            {\r\n                int i = wd->sel_end - 1;\r\n                while (i >= 0 && strchr(word_delimiters, wd->text[i]))\r\n                    i--;\r\n                while (i >= 0 && !strchr(word_delimiters, wd->text[i]))\r\n                    i--;\r\n                offset = i - wd->sel_end + 1;\r\n            }\r\n            widget_inputbox_set_selection_end(w, wd->sel_end + offset);\r\n            if (!is_shift_pressed)\r\n                wd->sel_begin = wd->sel_end;\r\n        }\r\n        if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_RIGHT, FALSE, tm_delay, tm_rate))\r\n        {\r\n            int offset = +1;\r\n            if (is_ctrl_pressed)\r\n            {\r\n                int i = wd->sel_end;\r\n                while (i < wd->length && !strchr(word_delimiters, wd->text[i]))\r\n                    i++;\r\n                while (i < wd->length && strchr(word_delimiters, wd->text[i]))\r\n                    i++;\r\n                offset = i - wd->sel_end;\r\n            }\r\n            widget_inputbox_set_selection_end(w, wd->sel_end + offset);\r\n            if (!is_shift_pressed)\r\n                wd->sel_begin = wd->sel_end;\r\n        }\r\n\r\n        // Home/End: set cursor to beginning/end of input box\r\n        if (Inputs_KeyPressed(ALLEGRO_KEY_HOME, FALSE))\r\n        {\r\n            widget_inputbox_set_selection_end(w, 0);\r\n            if (!is_shift_pressed)\r\n                wd->sel_begin = wd->sel_end;\r\n        }\r\n        if (Inputs_KeyPressed(ALLEGRO_KEY_END, FALSE))\r\n        {\r\n            widget_inputbox_set_selection_end(w, wd->length);\r\n            if (!is_shift_pressed)\r\n                wd->sel_begin = wd->sel_end;\r\n        }\r\n    }\r\n\r\n    // Completion callback\r\n    if (wd->flags & WIDGET_INPUTBOX_FLAGS_COMPLETION)\r\n    {\r\n        if (Inputs_KeyPressed(ALLEGRO_KEY_TAB, false))\r\n        {\r\n            // Completion\r\n            assert(wd->callback_completion != NULL);\r\n            wd->callback_completion(w);\r\n        }\r\n    }\r\n\r\n    // History callback\r\n    if (wd->flags & WIDGET_INPUTBOX_FLAGS_HISTORY)\r\n    {\r\n        if (Inputs_KeyPressed(ALLEGRO_KEY_UP, false))\r\n        {\r\n            // History Up\r\n            assert(wd->callback_history != NULL);\r\n            wd->callback_history(w, +1);\r\n        }\r\n        if (Inputs_KeyPressed(ALLEGRO_KEY_DOWN, false))\r\n        {\r\n            // History Down\r\n            assert(wd->callback_history != NULL);\r\n            wd->callback_history(w, -1);\r\n        }\r\n    }\r\n\r\n    // Edit callback\r\n    if (edited && wd->callback_edit)\r\n        wd->callback_edit(w);\r\n\r\n    // Enter: validate\r\n    if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_ENTER, FALSE, 30, 3) || Inputs_KeyPressed_Repeat(ALLEGRO_KEY_PAD_ENTER, FALSE, 30, 3))\r\n        if (wd->callback_enter)\r\n            wd->callback_enter(w);\r\n}\r\n\r\nvoid        widget_inputbox_redraw(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n\r\n    ALLEGRO_BITMAP *gfx_buffer = w->box->gfx_buffer;\r\n\r\n    const bool draw_cursor = !(wd->flags & WIDGET_INPUTBOX_FLAGS_NO_CURSOR) && (wd->cursor_blink_timer < 50);\r\n    const bool highlight_all = !(wd->flags & WIDGET_INPUTBOX_FLAGS_HIGHLIGHT_CURRENT_CHAR);\r\n\r\n    // Draw border & fill text area\r\n    al_set_target_bitmap(gfx_buffer);\r\n    al_draw_rectangle(w->frame.pos.x + 0.5f, w->frame.pos.y + 0.5f, w->frame.pos.x + w->frame.size.x + 0.5f, w->frame.pos.y + w->frame.size.y + 0.5f, COLOR_SKIN_WIDGET_GENERIC_BORDER, 1.0f);\r\n\r\n    const ALLEGRO_COLOR bg_color = (w->highlight) ? COLOR_SKIN_WIDGET_GENERIC_SELECTION : COLOR_SKIN_WIDGET_GENERIC_BACKGROUND;\r\n    al_draw_filled_rectangle(w->frame.pos.x + 1, w->frame.pos.y + 1, w->frame.pos.x + w->frame.size.x, w->frame.pos.y + w->frame.size.y, bg_color);\r\n\r\n    int x = w->frame.pos.x + 2 + 3; // Note: +3 to center font\r\n    const int y = w->frame.pos.y + (w->frame.size.y - Font_Height(wd->font_id)) / 2 + 1;\r\n\r\n    // Selection\r\n    if (wd->sel_begin != wd->sel_end)\r\n    {\r\n        const int sel_min = MIN(wd->sel_begin, wd->sel_end);\r\n        const int sel_max = MAX(wd->sel_begin, wd->sel_end);\r\n\r\n        sprintf(wd->tmp_buffer, \"%.*s\", sel_min, wd->text);\r\n        const int sel_min_x = Font_TextWidth(wd->font_id, wd->tmp_buffer);\r\n\r\n        sprintf(wd->tmp_buffer, \"%.*s\", sel_max - sel_min, wd->text + sel_min);\r\n        const int sel_max_x = sel_min_x + Font_TextWidth(wd->font_id, wd->tmp_buffer);\r\n\r\n        const ALLEGRO_COLOR inv_color = COLOR_SKIN_WINDOW_BACKGROUND;\r\n        al_draw_filled_rectangle(x + sel_min_x, w->frame.pos.y + 1+1, x + sel_max_x, w->frame.pos.y + w->frame.size.y-1, inv_color);\r\n    }\r\n\r\n    // Draw text & cursor\r\n    for (int i = 0; i < wd->length + 1; i++)\r\n    {\r\n        if (draw_cursor && (i == wd->sel_end))\r\n        {\r\n            // Draw cursor line\r\n            int cursor_y1 = w->frame.pos.y + 2;\r\n            int cursor_y2 = cursor_y1 + w->frame.size.y - 2*2;\r\n            al_draw_vline(x, cursor_y1, cursor_y2, COLOR_SKIN_WIDGET_GENERIC_TEXT);\r\n        }\r\n        if (i < wd->length)\r\n        {\r\n            // Draw one character\r\n            ALLEGRO_COLOR color = (highlight_all || i == wd->sel_end) ? COLOR_SKIN_WIDGET_GENERIC_TEXT : COLOR_SKIN_WIDGET_GENERIC_TEXT_UNACTIVE;\r\n            char ch[2];\r\n            ch[0] = wd->text[i];\r\n            ch[1] = '\\0';\r\n            Font_Print(wd->font_id, ch, x, y, color);\r\n            x += Font_TextWidth(wd->font_id, ch); // A bit slow\r\n        }\r\n    }\r\n}\r\n\r\nconst char *widget_inputbox_get_value(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    return (wd->text);\r\n}\r\n\r\nint         widget_inputbox_get_value_length(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    return (wd->length);\r\n}\r\n\r\nvoid        widget_inputbox_set_value(t_widget *w, const char *value)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    int     len;\r\n    \r\n    // Copy new value\r\n    len = strlen(value);\r\n    if (len < wd->length_max)\r\n    {\r\n        strcpy(wd->text, value);\r\n        wd->length = len;\r\n    }\r\n    else\r\n    {\r\n        strncpy (wd->text, value, wd->length_max);\r\n        wd->text[wd->length_max] = '\\0';\r\n        wd->length = wd->length_max;\r\n    }\r\n\r\n    // Set cursor to end of text\r\n    wd->sel_begin = wd->sel_end = wd->length;\r\n}\r\n\r\nint         widget_inputbox_get_cursor_pos(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    return (wd->sel_end);\r\n}\r\n\r\nvoid        widget_inputbox_set_cursor_pos(t_widget *w, int cursor_pos)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->cursor_blink_timer = 0;\r\n    wd->sel_begin = wd->sel_end = Clamp<int>(cursor_pos, 0, wd->length);\r\n}\r\n\r\nbool        widget_inputbox_has_selection(t_widget *w)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    return wd->sel_begin != wd->sel_end;\r\n}\r\n\r\nvoid        widget_inputbox_set_selection(t_widget *w, int sel_begin, int sel_end)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->cursor_blink_timer = 0;\r\n    wd->sel_begin = Clamp<int>(sel_begin, 0, wd->length);\r\n    wd->sel_end = Clamp<int>(sel_end, 0, wd->length);\r\n}\r\n\r\nvoid        widget_inputbox_set_selection_end(t_widget *w, int sel_end)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->cursor_blink_timer = 0;\r\n    wd->sel_end = Clamp<int>(sel_end, 0, wd->length);\r\n}\r\n\r\nvoid        widget_inputbox_set_callback_enter(t_widget *w, void (*callback_enter)(t_widget *))\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->callback_enter = callback_enter;\r\n}\r\n\r\nvoid        widget_inputbox_set_callback_edit(t_widget *w, void (*callback_edit)(t_widget *))\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->callback_edit = callback_edit;\r\n}\r\n\r\nvoid        widget_inputbox_set_flags(t_widget *w, int/*t_widget_inputbox_flags*/ flags, bool enable)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    if (enable)\r\n        wd->flags |= flags;\r\n    else\r\n        wd->flags &= ~flags;\r\n    // FIXME: changing NO_CURSOR dynamically won't refresh\r\n}\r\n\r\nvoid        widget_inputbox_set_content_type(t_widget *w, t_widget_content_type content_type)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->content_type = content_type;\r\n}\r\n\r\nvoid        widget_inputbox_set_overwrite_mode(t_widget *w, bool overwrite_mode)\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    wd->overwrite_mode = overwrite_mode;\r\n}\r\n\r\nvoid        widget_inputbox_set_callback_completion(t_widget *w, bool (*callback_completion)(t_widget *widget))\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    assert(callback_completion != NULL);\r\n    wd->callback_completion = callback_completion;\r\n}\r\n\r\nvoid        widget_inputbox_set_callback_history(t_widget *w, bool (*callback_history)(t_widget *widget, int level))\r\n{\r\n    t_widget_data_inputbox* wd = (t_widget_data_inputbox*)w->data;\r\n    assert(callback_history != NULL);\r\n    wd->callback_history = callback_history;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/g_widget.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - g_widget.h\r\n// GUI Widgets - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\nenum t_widget_type\r\n{\r\n    WIDGET_TYPE_CLOSEBOX,\r\n    WIDGET_TYPE_BUTTON,\r\n    WIDGET_TYPE_SCROLLBAR,\r\n    WIDGET_TYPE_CHECKBOX,\r\n    WIDGET_TYPE_TEXTBOX,\r\n    WIDGET_TYPE_INPUTBOX,\r\n};\r\n\r\nenum t_widget_content_type\r\n{\r\n    WIDGET_CONTENT_TYPE_TEXT        = 0,\r\n    WIDGET_CONTENT_TYPE_DECIMAL     = 1,\r\n    WIDGET_CONTENT_TYPE_HEXADECIMAL = 2,\r\n    WIDGET_CONTENT_TYPE_DEC_HEX_BIN = 3,\r\n};\r\n\r\nenum t_widget_inputbox_flags\r\n{\r\n    WIDGET_INPUTBOX_FLAGS_DEFAULT                   = 0,\r\n    WIDGET_INPUTBOX_FLAGS_NO_CURSOR                 = 0x0001,\r\n    WIDGET_INPUTBOX_FLAGS_NO_MOVE_CURSOR            = 0x0002,\r\n    WIDGET_INPUTBOX_FLAGS_NO_DELETE                 = 0x0004,\r\n    WIDGET_INPUTBOX_FLAGS_HIGHLIGHT_CURRENT_CHAR    = 0x0008,\r\n    WIDGET_INPUTBOX_FLAGS_COMPLETION                = 0x0010,\r\n    WIDGET_INPUTBOX_FLAGS_HISTORY                   = 0x0020,\r\n    WIDGET_INPUTBOX_FLAGS_NO_SELECTION              = 0x0040,\r\n};\r\n\r\nenum t_widget_scrollbar_type\r\n{\r\n    WIDGET_SCROLLBAR_TYPE_VERTICAL                  = 0,\r\n    WIDGET_SCROLLBAR_TYPE_HORIZONTAL                = 1,\r\n};\r\n\r\nenum t_widget_mouse_action\r\n{\r\n    WIDGET_MOUSE_ACTION_NONE    = 0,\r\n    WIDGET_MOUSE_ACTION_HOVER   = 0x0001,\r\n    WIDGET_MOUSE_ACTION_CLICK   = 0x0002,\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\ntypedef void (*t_widget_callback)(t_widget*);\r\n\r\nstruct t_widget\r\n{\r\n    t_widget_type           type;\r\n    bool                    enabled;\r\n    bool                    highlight;\r\n    t_gui_box *             box;\r\n    t_frame                 frame;\r\n    void *                  data;\r\n\r\n    // Mouse data\r\n    int                     mouse_x;\r\n    int                     mouse_y;\r\n    int                     mouse_buttons;\r\n    int                     mouse_buttons_previous;\r\n    int                     mouse_buttons_mask;\r\n    int                     mouse_buttons_activation;\r\n    int                     mouse_action;               // (enum t_widget_mouse_action) // FIXME-ENUM\r\n\r\n    // Handlers\r\n    void                    (*destroy_func)(t_widget* w);\r\n    void                    (*redraw_func)(t_widget* w);\r\n    void                    (*update_func)(t_widget* w);\r\n\r\n    // User data\r\n    void *                  user_data;\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Updating functions ---------------------------------------------------------\r\nbool        widgets_update_box              (t_gui_box *box, int cx, int cy);\r\nvoid        widgets_call_update             ();\r\n\r\n// Widget: generics -----------------------------------------------------------\r\nvoid        widget_destroy                  (t_widget* w);\r\nvoid        widget_set_enabled              (t_widget* w, bool v);\r\nvoid        widget_set_highlight            (t_widget* w, bool v);\r\nvoid        widget_set_mouse_buttons_mask   (t_widget* w, int mouse_buttons_mask);\r\nvoid *      widget_get_user_data            (t_widget* w);\r\nvoid        widget_set_user_data            (t_widget* w, void *user_data);\r\n//-----------------------------------------------------------------------------\r\n\r\n// Widget: star button at the top right of a box ------------------------------\r\nt_widget *  widget_closebox_add             (t_gui_box *box, t_widget_callback callback);\r\nvoid        widget_closebox_update          (t_widget* w);\r\nvoid        widget_closebox_redraw          (t_widget* w);\r\n//-----------------------------------------------------------------------------\r\n\r\n// Widget: button -------------------------------------------------------------\r\nt_widget *  widget_button_add               (t_gui_box* box, const t_frame* frame, int mouse_buttons_mask, t_widget_callback callback, t_font_id style, const char* label, void* user_data = NULL);\r\nvoid        widget_button_update            (t_widget* w);\r\nvoid        widget_button_redraw            (t_widget* w);\r\nvoid        widget_button_set_grayed_out    (t_widget* w, bool grayed_out);\r\nvoid        widget_button_set_label         (t_widget* w, const char* label);\r\nvoid        widget_button_trigger           (t_widget* w);\r\n//-----------------------------------------------------------------------------\r\n\r\n// Widget: scroll bar ---------------------------------------------------------\r\nt_widget *  widget_scrollbar_add            (t_gui_box *box, t_widget_scrollbar_type scrollbar_type, const t_frame *frame, const int *v_max, int *v_start, int v_step, t_widget_callback callback);\r\nvoid        widget_scrollbar_update         (t_widget* w);\r\nvoid        widget_scrollbar_redraw         (t_widget* w);\r\nvoid        widget_scrollbar_set_page_step  (t_widget* w, int page_step);\r\n//-----------------------------------------------------------------------------\r\n\r\n// Widget: check box ----------------------------------------------------------\r\nt_widget *  widget_checkbox_add                     (t_gui_box *box, const t_frame *frame, bool *pvalue, t_widget_callback callback);\r\nvoid        widget_checkbox_update                  (t_widget* w);\r\nvoid        widget_checkbox_redraw                  (t_widget* w);\r\nvoid        widget_checkbox_set_pvalue              (t_widget* w, bool *pvalue);\r\n//-----------------------------------------------------------------------------\r\n\r\n// Widget: text box -----------------------------------------------------------\r\nt_widget *  widget_textbox_add                      (t_gui_box *box, const t_frame *frame, t_font_id font_id);\r\nvoid        widget_textbox_redraw                   (t_widget* w);\r\nvoid        widget_textbox_clear                    (t_widget* w);\r\nvoid        widget_textbox_set_current_color        (t_widget* w, const ALLEGRO_COLOR *pcurrent_color);\r\nvoid        widget_textbox_print_scroll             (t_widget* w, bool wrap, const char *line);\r\nvoid        widget_textbox_printf_scroll            (t_widget* w, bool wrap, const char *format, ...);\r\n//-----------------------------------------------------------------------------\r\n\r\n// Widget: input box ----------------------------------------------------------\r\nt_widget *  widget_inputbox_add                     (t_gui_box *box, const t_frame *frame, int length_max, t_font_id font_id, t_widget_callback callback_enter);\r\nvoid        widget_inputbox_update                  (t_widget* w);\r\nvoid        widget_inputbox_redraw                  (t_widget* w);\r\nconst char *widget_inputbox_get_value               (t_widget* w);\r\nint         widget_inputbox_get_value_length        (t_widget* w);\r\nvoid        widget_inputbox_set_value               (t_widget* w, const char *value);\r\nint         widget_inputbox_get_cursor_pos          (t_widget* w);\r\nvoid        widget_inputbox_set_cursor_pos          (t_widget* w, int cursor_pos);\r\nbool        widget_inputbox_has_selection           (t_widget* w);\r\nvoid        widget_inputbox_set_selection           (t_widget* w, int sel_begin, int sel_end);\r\nvoid        widget_inputbox_set_selection_end       (t_widget* w, int sel_end);\r\nvoid        widget_inputbox_set_callback_enter      (t_widget* w, void (*callback_enter)(t_widget *));\r\nvoid        widget_inputbox_set_callback_edit       (t_widget* w, void (*callback_edit)(t_widget *));\r\nvoid        widget_inputbox_set_flags               (t_widget* w, int /*t_widget_inputbox_flags*/ flags, bool enable);  // FIXME-ENUM\r\nvoid        widget_inputbox_set_content_type        (t_widget* w, t_widget_content_type content_type);\r\nvoid        widget_inputbox_set_overwrite_mode      (t_widget* w, bool overwrite_mode);\r\nvoid        widget_inputbox_set_callback_completion (t_widget* w, bool (*callback_completion)(t_widget *));\r\nvoid        widget_inputbox_set_callback_history    (t_widget* w, bool (*callback_history)(t_widget *, int level));\r\nbool        widget_inputbox_insert_chars            (t_widget* w, const char *str);\r\nvoid        widget_inputbox_delete_selection        (t_widget* w);\r\nvoid        widget_inputbox_delete_current_char     (t_widget* w);\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/glasses.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - glasses.c\r\n// 3D Glasses Support and Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"blit.h\"\r\n#include \"blitintf.h\"\r\n#include \"glasses.h\"\r\n#include \"inputs_c.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_glasses   Glasses;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nint     Glasses_ComPort_Initialize();\r\nvoid    Glasses_ComPort_Close();\r\nvoid    Glasses_ComPort_Write(int left_enable, int right_enable);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Glasses_Init_Values()\r\n{\r\n    Glasses.Enabled = FALSE;\r\n    Glasses_Set_Mode (GLASSES_MODE_SHOW_ONLY_RIGHT);\r\n    // Note: RIGHT being the default is better because when ran in Japanese\r\n    // mode, Space Harrier and Maze Walker keep only this side enabled for\r\n    // one or two seconds.\r\n\r\n#ifdef ARCH_WIN32\r\n    Glasses.ComHandle = INVALID_HANDLE_VALUE;\r\n    Glasses_Set_ComPort (1);\r\n#else\r\n    // MS-DOS users are likely to have a mouse and use COM 2 by default\r\n    Glasses_Set_ComPort (2);\r\n#endif\r\n}\r\n\r\nvoid    Glasses_Close()\r\n{\r\n    if (Glasses.Enabled && Glasses.Mode == GLASSES_MODE_COM_PORT)\r\n    {\r\n        Glasses_ComPort_Write (FALSE, FALSE);\r\n        Glasses_ComPort_Close();\r\n    }\r\n}\r\n\r\nint     Glasses_Must_Skip_Frame()\r\n{\r\n    static int security_cnt = 0;\r\n    // Msg(MSGT_DEBUG, \"%02X-%02X-%02X-%02X\", RAM[0x1FF8], RAM[0x1FF9], RAM[0x1FFA], RAM[0x1FFB]);\r\n\r\n    const int side = (sms.Glasses_Register & 1);\r\n    const bool ret = (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT && !side) || (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_RIGHT && side);\r\n    if (ret == FALSE)\r\n    {\r\n        security_cnt = 0;\r\n    }\r\n    else\r\n    {\r\n        if (++security_cnt >= 180) // Arbitrary value (180 updates, should be 3 seconds)\r\n        {\r\n            security_cnt = 0;\r\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Glasses_Unsupported));\r\n            // Msg(MSGT_USER_BOX, \"%s\", Msg_Get(MSG_Glasses_Unsupported2));\r\n            Glasses_Switch_Enable();\r\n        }\r\n    }\r\n    return (ret);\r\n}\r\n\r\nvoid    Glasses_Set_Mode(int mode)\r\n{\r\n    if (Glasses.Mode == GLASSES_MODE_COM_PORT && mode != GLASSES_MODE_COM_PORT)\r\n        Glasses_ComPort_Close();\r\n    Glasses.Mode = mode;\r\n    if (Glasses.Mode == GLASSES_MODE_COM_PORT)\r\n        if (!Glasses_ComPort_Initialize ())\r\n        {\r\n            Msg(MSGT_USER, Msg_Get(MSG_Glasses_Com_Port_Open_Error), Glasses.ComPort);\r\n        }\r\n}\r\n\r\nvoid    Glasses_Set_ComPort(int port)\r\n{\r\n    Glasses.ComPort = port;\r\n    if (Glasses.Mode == GLASSES_MODE_COM_PORT)\r\n        if (!Glasses_ComPort_Initialize())\r\n        {\r\n            Msg(MSGT_USER, Msg_Get(MSG_Glasses_Com_Port_Open_Error), Glasses.ComPort);\r\n        }\r\n}\r\n\r\nint     Glasses_ComPort_Initialize()\r\n{\r\n#ifdef ARCH_DOS\r\n\r\n    int base = (Glasses.ComPort == 1) ? 0x3F0 : 0x2F0;\r\n\r\n    // IER : Disable all interrupts\r\n    asm volatile (\"cli\");\r\n    outportb (base + 0x09, 0x00);\r\n    asm volatile (\"sti\");\r\n    // LCR : Set to 8 bits, 1 stop bit, no parity\r\n    asm volatile (\"cli\");\r\n    outportb (base + 0x0B, 0x83);\r\n    asm volatile (\"sti\");\r\n    // MCR : Set to zero, will be set again later\r\n    asm volatile (\"cli\");\r\n    outportb (base + 0x0C, 0x00);\r\n    asm volatile (\"sti\");\r\n\r\n    return true;\r\n\r\n#elif ARCH_WIN32\r\n\r\n    HANDLE  handle;\r\n    DCB     dcb;\r\n    char *  com_device_name;\r\n\r\n    // Close previously opened COM device\r\n    if (Glasses.ComHandle != INVALID_HANDLE_VALUE)\r\n        Glasses_ComPort_Close();\r\n\r\n    // Find COM device name\r\n    if (Glasses.ComPort == 1)\r\n        com_device_name = \"COM1\";\r\n    else if (Glasses.ComPort == 2)\r\n        com_device_name = \"COM2\";\r\n    else\r\n        return false;\r\n\r\n    // Open COM device\r\n    handle = CreateFile(com_device_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);\r\n    if (handle == INVALID_HANDLE_VALUE)\r\n        return false;\r\n\r\n    // Get current state\r\n    if (!GetCommState(handle, &dcb))\r\n    {\r\n        CloseHandle (handle);\r\n        return false;\r\n    }\r\n\r\n    // Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit.\r\n    dcb.BaudRate    = CBR_57600;    // set the baud rate\r\n    dcb.ByteSize    = 8;            // data size, xmit, and rcv\r\n    dcb.Parity      = NOPARITY;     // no parity bit\r\n    dcb.StopBits    = ONESTOPBIT;   // one stop bit\r\n\r\n    // Set new state\r\n    if (!SetCommState(handle, &dcb))\r\n    {\r\n        CloseHandle (handle);\r\n        return false;\r\n    }\r\n\r\n    Glasses.ComHandle = handle;\r\n    return true;\r\n\r\n#else\r\n\r\n    return true;\r\n\r\n#endif\r\n}\r\n\r\nvoid    Glasses_ComPort_Close()\r\n{\r\n#ifdef ARCH_WIN32\r\n    if (Glasses.ComHandle == INVALID_HANDLE_VALUE)\r\n        return;\r\n    CloseHandle (Glasses.ComHandle);\r\n    Glasses.ComHandle = INVALID_HANDLE_VALUE;\r\n#endif\r\n}\r\n\r\nvoid    Glasses_ComPort_Write(int left_enable, int right_enable)\r\n{\r\n#ifdef ARCH_DOS\r\n\r\n    int address = (Glasses.ComPort == 1) ? 0x3FC : 0x2FC;\r\n    int data;\r\n    if (left_enable)\r\n        data = 0x03; // MCR = DTR | RTS\r\n    else if (right_enable)\r\n        data = 0x01; // MCR = DTR\r\n    else\r\n        data = 0x00;\r\n\r\n    asm volatile (\"cli\");\r\n    outportb (address, data);\r\n    asm volatile (\"sti\");\r\n\r\n#elif ARCH_WIN32\r\n\r\n    DCB dcb;\r\n    if (Glasses.ComHandle == INVALID_HANDLE_VALUE)\r\n        return;\r\n    if (!GetCommState(Glasses.ComHandle, &dcb))\r\n        return;\r\n    if (left_enable)\r\n    {\r\n        dcb.fDtrControl = DTR_CONTROL_ENABLE;\r\n        dcb.fRtsControl = RTS_CONTROL_ENABLE;\r\n    }\r\n    else if (right_enable)\r\n    {\r\n        dcb.fDtrControl = DTR_CONTROL_ENABLE;\r\n        dcb.fRtsControl = RTS_CONTROL_DISABLE;\r\n    }\r\n    else\r\n    {\r\n        dcb.fDtrControl = DTR_CONTROL_DISABLE;\r\n        dcb.fRtsControl = RTS_CONTROL_DISABLE;\r\n    }\r\n    if (!SetCommState(Glasses.ComHandle, &dcb))\r\n        return;\r\n\r\n#else\r\n    // Other systems (UNIX) yet unsupported\r\n#endif\r\n}\r\n\r\nvoid    Glasses_Update()\r\n{\r\n    if (Glasses.Mode == GLASSES_MODE_COM_PORT)\r\n    {\r\n        if (sms.Glasses_Register & 1)\r\n            Glasses_ComPort_Write (TRUE, FALSE);\r\n        else\r\n            Glasses_ComPort_Write (FALSE, TRUE);\r\n    }\r\n}\r\n\r\nvoid    Glasses_Switch_Enable()\r\n{\r\n    Glasses_Close();\r\n    Glasses.Enabled ^= 1;\r\n    if (Glasses.Enabled)\r\n    {\r\n        gui_menu_check (menus_ID.glasses, 0);\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Glasses_Enabled));\r\n    }\r\n    else\r\n    {\r\n        gui_menu_uncheck_range(menus_ID.glasses, 0, 0);\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Glasses_Disabled));\r\n    }\r\n    gui_menu_active_range (Glasses.Enabled, menus_ID.glasses, 1, 4);\r\n    Inputs_CFG_Peripherals_Draw();\r\n}\r\n\r\nvoid    Glasses_Switch_Mode_Show_Both()\r\n{\r\n    Glasses_Close();\r\n    Glasses.Mode = GLASSES_MODE_SHOW_BOTH;\r\n    gui_menu_uncheck_range (menus_ID.glasses, 1, 4);\r\n    gui_menu_check (menus_ID.glasses, 1);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Glasses_Show_Both));\r\n}\r\n\r\nvoid    Glasses_Switch_Mode_Show_Left()\r\n{\r\n    Glasses_Close();\r\n    Glasses.Mode = GLASSES_MODE_SHOW_ONLY_LEFT;\r\n    gui_menu_uncheck_range (menus_ID.glasses, 1, 4);\r\n    gui_menu_check (menus_ID.glasses, 2);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Glasses_Show_Left));\r\n}\r\n\r\nvoid    Glasses_Switch_Mode_Show_Right()\r\n{\r\n    Glasses_Close();\r\n    Glasses.Mode = GLASSES_MODE_SHOW_ONLY_RIGHT;\r\n    gui_menu_uncheck_range (menus_ID.glasses, 1, 4);\r\n    gui_menu_check (menus_ID.glasses, 3);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Glasses_Show_Right));\r\n}\r\n\r\nvoid    Glasses_Switch_Mode_Com_Port()\r\n{\r\n    Glasses.Mode = GLASSES_MODE_COM_PORT;\r\n    gui_menu_uncheck_range (menus_ID.glasses, 1, 4);\r\n    gui_menu_check (menus_ID.glasses, 4);\r\n    Msg(MSGT_USER, Msg_Get(MSG_Glasses_Com_Port), Glasses.ComPort);\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Glasses_Com_Port2));\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/glasses.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - glasses.h\n// 3D Glasses Support and Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define GLASSES_MODE_SHOW_BOTH          (0)\n#define GLASSES_MODE_SHOW_ONLY_LEFT     (1)\n#define GLASSES_MODE_SHOW_ONLY_RIGHT    (2)\n#define GLASSES_MODE_COM_PORT           (3)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_glasses\n{\n    bool        Enabled;\n    int         Mode;\n    int         ComPort;\n#ifdef ARCH_WIN32\n    HANDLE      ComHandle;\n#endif\n};\n\nextern t_glasses   Glasses;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Glasses_Init_Values();\nvoid    Glasses_Close();\nvoid    Glasses_Set_Mode(int mode);\nvoid    Glasses_Set_ComPort(int port);\nvoid    Glasses_Write(int LeftEnable, int RightEnable);\nvoid    Glasses_Update();\n\nint     Glasses_Must_Skip_Frame();\n\nvoid    Glasses_Switch_Enable();\nvoid    Glasses_Switch_Mode_Show_Both();\nvoid    Glasses_Switch_Mode_Show_Left();\nvoid    Glasses_Switch_Mode_Show_Right();\nvoid    Glasses_Switch_Mode_Com_Port();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/gui.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - gui.h\n// Graphical User Interface (GUI) - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"blit.h\"\n#include \"app_game.h\"\n#include \"g_tools.h\"\n#include \"g_widget.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_gui gui;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nDrawCursor::DrawCursor(v2i _pos, int font_id)\n{\n    this->pos = _pos;\n    this->x_base = this->pos.x;\n    this->y_spacing = Font_Height((t_font_id)font_id)+2;\n\n    ALLEGRO_BITMAP* bitmap = al_get_target_bitmap();\n    this->viewport_min.Set(0,0);\n    this->viewport_max.Set(al_get_bitmap_width(bitmap),al_get_bitmap_height(bitmap));\n}\n\nvoid    DrawCursor::HorizontalSeparator()\n{\n    this->pos.y += 2;\n    al_draw_line(viewport_min.x, this->pos.y+0.5f, viewport_max.x, this->pos.y+0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\n    this->pos.y += 2;\n}\n\nvoid    DrawCursor::VerticalSeparator()\n{\n    this->pos.x += 2;\n    al_draw_line(this->pos.x+0.5f, viewport_min.y, this->pos.x+0.5f, viewport_max.y, COLOR_SKIN_WINDOW_SEPARATORS, 0);\n    this->pos.x += 2;\n}\n\n//-----------------------------------------------------------------------------\n\nvoid    gui_redraw_everything_now_once()\n{\n    gui_update();\n    gui_draw();\n    Blit_GUI();\n}\n\nvoid    gui_draw_background()\n{\n    al_set_target_bitmap(gui_buffer);\n    al_draw_bitmap(gui_background, 0, 0, 0x0000);\n}\n\nvoid    gui_draw()\n{\n    // If we were asked to redraw everything, redraw the background as well\n    if (gui.info.must_redraw == TRUE)\n        gui_draw_background();\n\n    al_set_target_bitmap(gui_buffer);\n    for (int i = gui.boxes_count - 1; i >= 0; i--)\n    {\n        t_gui_box* b = gui.boxes_z_ordered[i];\n        const t_frame bb = b->frame;\n        const v2i bb_min = bb.GetMin();\n        const v2i bb_max = bb.GetMax();\n\n        if (!(b->flags & GUI_BOX_FLAGS_ACTIVE))\n            continue;\n\n        // Draw widgets\n        for (t_list* widgets = b->widgets; widgets != NULL; widgets = widgets->next)\n        {\n            t_widget *w = (t_widget *)widgets->elem;\n            if (w->enabled && w->type != WIDGET_TYPE_CLOSEBOX)\n                if (w->redraw_func != NULL)\n                    w->redraw_func(w);\n        }\n\n        // Blit content\n        switch (b->type)\n        {\n        case GUI_BOX_TYPE_STANDARD: \n            al_set_target_bitmap(gui_buffer);\n            al_draw_bitmap_region(b->gfx_buffer, 0, 0, bb.size.x + 1, bb.size.y + 1, bb.pos.x, bb.pos.y, 0x0000);\n            break;\n        case GUI_BOX_TYPE_GAME: \n            gamebox_draw(b, screenbuffer);\n            break;\n        }\n\n        // Draw borders\n        al_set_target_bitmap(gui_buffer);\n        gui_rect(LOOK_ROUND, bb.pos.x - 2, bb.pos.y - 20, bb.pos.x + bb.size.x + 2, bb.pos.y + bb.size.y + 2, COLOR_SKIN_WINDOW_BORDER);\n        al_draw_line(bb.pos.x, bb.pos.y - 1.5f, bb.pos.x + bb.size.x + 1, bb.pos.y - 1.5f, COLOR_SKIN_WINDOW_BORDER, 0);\n        al_draw_line(bb.pos.x, bb.pos.y - 0.5f, bb.pos.x + bb.size.x + 1, bb.pos.y - 0.5f, COLOR_SKIN_WINDOW_BORDER, 0);\n\n        // Draw resize widget (invisible for game window)\n        if (b->flags & GUI_BOX_FLAGS_ALLOW_RESIZE)\n        {\n            const bool is_resizing = (gui.mouse.focus == GUI_FOCUS_BOX && gui.mouse.focus_box == b && gui.mouse.focus_is_resizing);\n            if (b->type != GUI_BOX_TYPE_GAME || is_resizing)\n            {\n                const int sz = 9; // display size is 9, interaction is 12\n                const ALLEGRO_COLOR color = is_resizing ? COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT : COLOR_SKIN_WINDOW_TITLEBAR_TEXT_UNACTIVE;\n                al_draw_filled_triangle(bb_max.x+2, bb_max.y+2, bb_max.x+2-sz, bb_max.y+2, bb_max.x+2, bb_max.y+2-sz, color);\n            }\n        }\n\n        // Draw title bar\n        {\n            t_frame titlebar_frame;\n            titlebar_frame.pos.x  = bb.pos.x;\n            titlebar_frame.pos.y  = bb.pos.y - 18;\n            titlebar_frame.size.x = bb.size.x;\n            titlebar_frame.size.y = 15;\n            SkinGradient_DrawHorizontal(&Skins_GetCurrentSkin()->gradient_window_titlebar, gui_buffer, &titlebar_frame);\n\n            // Draw title bar text, with wrapping\n            // Is window the focused one?\n            const ALLEGRO_COLOR color = (i == 0) ? COLOR_SKIN_WINDOW_TITLEBAR_TEXT : COLOR_SKIN_WINDOW_TITLEBAR_TEXT_UNACTIVE;\n            Font_SetCurrent(FONTID_LARGE);\n            if (Font_TextWidth(FONTID_CUR, b->title) <= (bb.size.x - 8))\n            {\n                Font_Print (FONTID_CUR, b->title, bb.pos.x + 4, bb.pos.y - 17, color);\n            }\n            else\n            {\n                // FIXME-OPT: shit code.\n                char title[256];\n                int len = strlen(b->title);\n                strcpy(title, b->title);\n                while (Font_TextWidth(FONTID_CUR, title) > (bb.size.x - 17))\n                    title[--len] = EOSTR;\n                strcat(title, \"..\");\n                Font_Print(FONTID_CUR, title, bb.pos.x + 4, bb.pos.y - 17, color);\n            }\n\n            // Draw widgets\n            for (t_list* widgets = b->widgets; widgets != NULL; widgets = widgets->next)\n            {\n                t_widget *w = (t_widget *)widgets->elem;\n                if (w->enabled && w->type == WIDGET_TYPE_CLOSEBOX)\n                    if (w->redraw_func != NULL)\n                        w->redraw_func(w);\n            }\n        }\n    }\n\n    // Redraw menus on top of the desktop\n    gui_redraw_menus();\n\n    // Update applets that comes after the redraw\n    gui_update_applets_after_redraw();\n\n    // Clear global redrawing flag and makes mouse reappear\n    gui.info.must_redraw = FALSE;\n}\n\nvoid    gui_relayout_all()\n{\n    for (t_list* boxes = gui.boxes; boxes != NULL; boxes = boxes->next)\n    {\n        t_gui_box* box = (t_gui_box*)boxes->elem;\n        box->flags |= GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\n    }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/gui.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - gui.h\r\n// Graphical User Interface (GUI) - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n#pragma once\r\n\r\n//-----------------------------------------------------------------------------\r\n// Basic type\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_gui_box;\r\nstruct t_list;\r\n\r\nstruct v2i\r\n{\r\n    int   x;\r\n    int   y;\r\n\r\n    v2i()\r\n    {\r\n        x = y = -1;\r\n    }\r\n    v2i(int _x, int _y)\r\n    {\r\n        Set(_x, _y);\r\n    }\r\n\r\n    void Set(int _x, int _y)\r\n    {\r\n        x = _x;\r\n        y = _y;\r\n    }\r\n\r\n    v2i operator+(const v2i& rhs) const     { return v2i(x+rhs.x,y+rhs.y); }\r\n    v2i operator-(const v2i& rhs) const     { return v2i(x-rhs.x,y-rhs.y); }\r\n\r\n    const v2i& operator+=(const v2i& rhs)   { x+=rhs.x; y+=rhs.y; return *this; }\r\n};\r\n\r\nstruct t_frame\r\n{\r\n    v2i  pos;\r\n    v2i  size;\r\n\r\n    t_frame()\r\n    {\r\n    }\r\n\r\n    t_frame(v2i _pos, v2i _size)\r\n    {\r\n        Set(_pos, _size);\r\n    }\r\n    void Set(v2i _pos, v2i _size)\r\n    {\r\n        pos = _pos;\r\n        size = _size;\r\n    }\r\n    void SetPos(v2i _pos)\r\n    {\r\n        pos = _pos;\r\n    }\r\n    void SetPos(int x, int y)\r\n    {\r\n        pos.x = x;\r\n        pos.y = y;\r\n    }\r\n    void SetSize(v2i _size)\r\n    {\r\n        size = _size;\r\n    }\r\n    void SetSize(int x, int y)\r\n    {\r\n        size.x = x;\r\n        size.y = y;\r\n    }\r\n    v2i GetMin() const\r\n    {\r\n        return pos;\r\n    }\r\n    v2i GetMax() const\r\n    {\r\n        v2i pe;\r\n        pe.x = pos.x+size.x;\r\n        pe.y = pos.y+size.y;\r\n        return pe;\r\n    }\r\n};\r\n\r\nstruct DrawCursor\r\n{\r\n    v2i pos;\r\n    int x_base;\r\n    int y_spacing;\r\n    v2i viewport_min;\r\n    v2i viewport_max;\r\n\r\n    DrawCursor(v2i _pos, int font_id = -1);\r\n\r\n    void NewLine()\r\n    {\r\n        pos.x = x_base;\r\n        pos.y += y_spacing;\r\n    }\r\n    void HorizontalSeparator();\r\n    void VerticalSeparator();\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Includes other GUI files\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"g_action.h\"\r\n#include \"g_box.h\"\r\n#include \"g_action.h\"\r\n#include \"g_mouse.h\"\r\n#include \"g_update.h\"\r\n\r\n#include \"g_init.h\"\r\n#include \"g_menu.h\"\r\n#include \"g_menu_i.h\"\r\n#include \"g_menu_t.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define DOUBLE_CLICK_SPEED          (20)    // FIXME: this is time dependent rendered-frames!!\r\n\r\n// Frames\r\n#define GUI_LOOK_FRAME_PAD_HEAD1_X  (6)\r\n#define GUI_LOOK_FRAME_PAD_HEAD2_X  (2)\r\n#define GUI_LOOK_FRAME_PAD_X        (6)\r\n#define GUI_LOOK_FRAME_PAD1_Y       (8)\r\n#define GUI_LOOK_FRAME_PAD2_Y       (2)\r\n#define GUI_LOOK_FRAME_SPACING_X    (7)\r\n#define GUI_LOOK_FRAME_SPACING_Y    (6)\r\n// Texts\r\n#define GUI_LOOK_LINES_SPACING_Y    (0) /* 1 or  2 */\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n#define GUI_BOX_MAX                 (128)\r\n\r\nenum t_gui_box_type\r\n{\r\n    GUI_BOX_TYPE_STANDARD           = 0,\r\n    GUI_BOX_TYPE_GAME               = 1,\r\n};\r\n\r\nenum t_gui_box_flags\r\n{\r\n    GUI_BOX_FLAGS_ACTIVE                    = 0x0001,\r\n    GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT   = 0x0004,\r\n    GUI_BOX_FLAGS_FOCUS_INPUTS_EXCLUSIVE    = 0x0008,   // When set and the box has focus, inputs are exclusive to this box\r\n    GUI_BOX_FLAGS_DELETE                    = 0x0010,\r\n    GUI_BOX_FLAGS_TAB_STOP                  = 0x0020,\r\n    GUI_BOX_FLAGS_ALLOW_RESIZE              = 0x0040,\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    gui_draw();\r\nvoid    gui_redraw_everything_now_once();\r\n\r\nvoid    gui_draw_background();\r\nvoid    gui_relayout_all();\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\ntypedef void (*t_gui_box_update_handler)();\r\ntypedef void (*t_gui_box_destroy_handler)(void *);\r\n\r\nstruct t_gui_box\r\n{\r\n    t_frame         frame;                      // Frame (position & size)\r\n    char*           title;                      // Title\r\n    t_gui_box_type  type;                       // Type\r\n    int             flags;                      // Flags (t_gui_box_flags) // FIXME-ENUM\r\n    ALLEGRO_BITMAP* gfx_buffer;                 // Graphics buffer holding content render\r\n    t_list*         widgets;                    // Widgets\r\n    v2i             size_min, size_max;         // Resize limits\r\n    v2i             size_step;\r\n    bool            size_fixed_ratio;\r\n\r\n    // Handlers\r\n    void            (*update)();\r\n    void            (*destroy)(void *user_data);\r\n\r\n    // User data\r\n    void *          user_data;\r\n};\r\n\r\nstruct t_gui_info\r\n{\r\n  bool              must_redraw;\r\n  int               bars_height;\r\n  int               grid_distance;\r\n  int               dirty_x, dirty_y;\r\n  v2i               screen;\r\n  v2i               screen_pad;\r\n};\r\n\r\nstruct t_gui_mouse\r\n{\r\n    int             x;\r\n    int             x_prev;\r\n    int             y;\r\n    int             y_prev;\r\n    int             buttons;\r\n    int             buttons_prev;\r\n    int             double_clicked;\r\n    int             last_click_button;\r\n    int             last_click_time_elapsed;\r\n\r\n    t_gui_focus     focus;\r\n    t_gui_box*      focus_box;\r\n    t_widget*       focus_widget;\r\n    bool            focus_is_resizing;\r\n    v2i             focus_pivot;            // in local box coordinates\r\n\r\n    int             wheel_rel;\r\n    int             wheel_abs;\r\n};\r\n\r\nstruct t_gui\r\n{\r\n    t_list *        boxes;\r\n    t_gui_box *     boxes_z_ordered[GUI_BOX_MAX];\r\n    int             boxes_count;\r\n    t_gui_info      info;\r\n    t_gui_mouse     mouse;\r\n};\r\n\r\nextern t_gui        gui;\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/hq2x.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - hq2x.c\r\n// HQ2X filter initialization and interface.\r\n//-----------------------------------------------------------------------------\r\n// Based on hq2x.cpp from HQ2X distribution.\r\n//-----------------------------------------------------------------------------\r\n\r\n//----------------------------------------------------------\r\n//Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )\r\n//\r\n//This program is free software; you can redistribute it and/or\r\n//modify it under the terms of the GNU General Public License\r\n//as published by the Free Software Foundation; either\r\n//version 2 of the License, or (at your option) any later\r\n//version.\r\n//\r\n//This program is distributed in the hope that it will be useful,\r\n//but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n//GNU General Public License for more details.\r\n//\r\n//You should have received a copy of the GNU General Public License\r\n//along with this program; if not, write to the Free Software\r\n//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r\n\r\n#include \"shared.h\"\r\n#include \"hq2x.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n// Note: 512 KB goes here\r\nextern \"C\"\r\n{\r\nunsigned int   HQ2X_LUT16to32[65536];\r\nunsigned int   HQ2X_RGBtoYUV[65536];\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    HQ2X_Init()\r\n{\r\n    int i, j, k, r, g, b, Y, u, v;\r\n\r\n    for (i=0; i<65536; i++)\r\n        HQ2X_LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3);\r\n\r\n    for (i=0; i<32; i++)\r\n        for (j=0; j<64; j++)\r\n            for (k=0; k<32; k++)\r\n            {\r\n                r = i << 3;\r\n                g = j << 2;\r\n                b = k << 3;\r\n                Y = (r + g + b) >> 2;\r\n                u = 128 + ((r - b) >> 2);\r\n                v = 128 + ((-r + 2*g -b)>>3);\r\n                HQ2X_RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v;\r\n            }\r\n\r\n    /*\r\n    int nMMXsupport = 0;\r\n\r\n    __asm\r\n    {\r\n        mov  eax, 1\r\n            cpuid\r\n            and  edx, 0x00800000\r\n            mov  nMMXsupport, edx\r\n    }\r\n\r\n    return nMMXsupport;\r\n    */\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/hq2x.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - hq2x.h\r\n// HQ2X filter initialization and interface.\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nextern \"C\"\r\n{\r\nextern unsigned int   HQ2X_LUT16to32[65536];\r\nextern unsigned int   HQ2X_RGBtoYUV[65536];\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nextern \"C\"\r\n{\r\nvoid    hq2x_16(unsigned char*, unsigned char*, int, int, int);\r\nvoid    hq2x_32(unsigned char*, unsigned char*, int, int, int);\r\n}\r\n\r\nvoid    HQ2X_Init();\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/hq2x16.asm",
    "content": "; Copied under custom license. See SOURCES.TXT.\r\n;hq2x filter\r\n;16bpp output\r\n;----------------------------------------------------------\r\n;Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )\r\n;\r\n;This program is free software; you can redistribute it and/or\r\n;modify it under the terms of the GNU General Public License\r\n;as published by the Free Software Foundation; either\r\n;version 2 of the License, or (at your option) any later\r\n;version.\r\n;\r\n;This program is distributed in the hope that it will be useful,\r\n;but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n;GNU General Public License for more details.\r\n;\r\n;You should have received a copy of the GNU General Public License\r\n;along with this program; if not, write to the Free Software\r\n;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r\n\r\n%IFDEF ASM_SYMBOLS_REQUIRE_UNDERSCORE\r\n%DEFINE  _hq2x_16              hq2x_16\r\n%DEFINE  _HQ2X_LUT16to32       HQ2X_LUT16to32\r\n%DEFINE  _HQ2X_RGBtoYUV        HQ2X_RGBtoYUV\r\n%ENDIF ; ASM_SYMBOLS_REQUIRE_UNDERSCORE\r\n\r\nGLOBAL _hq2x_16\r\n\r\nEXTERN _HQ2X_LUT16to32\r\nEXTERN _HQ2X_RGBtoYUV\r\n\r\nSECTION .bss\r\nlinesleft resd 1\r\nxcounter  resd 1\r\ncross     resd 1\r\nnextline  resd 1\r\nprevline  resd 1\r\nw1        resd 1\r\nw2        resd 1\r\nw3        resd 1\r\nw4        resd 1\r\nw5        resd 1\r\nw6        resd 1\r\nw7        resd 1\r\nw8        resd 1\r\nw9        resd 1\r\n\r\nSECTION .data\r\n\r\nreg_blank    dd  0,0\r\nconst3       dd  0x00030003,0x00000003\r\nconst5       dd  0x00050005,0x00000005\r\nconst6       dd  0x00060006,0x00000006\r\nconst14      dd  0x000E000E,0x0000000E\r\nthreshold    dd  0x00300706,0x00000000\r\nzerolowbits  dd  0xF7DEF7DE\r\n\r\nSECTION .text\r\n\r\n%macro TestDiff 2\r\n    xor     ecx,ecx\r\n    mov     edx,[%1]\r\n    cmp     edx,[%2]\r\n    je      %%fin\r\n    mov     ecx,_HQ2X_RGBtoYUV\r\n    movd    mm1,[ecx+edx*4]\r\n    movq    mm5,mm1\r\n    mov     edx,[%2]\r\n    movd    mm2,[ecx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    ecx,mm1\r\n%%fin:\r\n%endmacro\r\n\r\n%macro DiffOrNot 4\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz   %%same\r\n   %3\r\n   jmp %%fin\r\n%%same:\r\n   %4\r\n%%fin\r\n%endmacro\r\n\r\n%macro DiffOrNot 6\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz   %%same\r\n   %3\r\n   %4\r\n   jmp %%fin\r\n%%same:\r\n   %5\r\n   %6\r\n%%fin\r\n%endmacro\r\n\r\n%macro DiffOrNot 8\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz   %%same\r\n   %3\r\n   %4\r\n   %5\r\n   jmp %%fin\r\n%%same:\r\n   %6\r\n   %7\r\n   %8\r\n%%fin\r\n%endmacro\r\n\r\n%macro DiffOrNot 10\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz %%same\r\n   %3\r\n   %4\r\n   %5\r\n   %6\r\n   jmp %%fin\r\n%%same:\r\n   %7\r\n   %8\r\n   %9\r\n   %10\r\n%%fin\r\n%endmacro\r\n\r\n%macro Interp1 3\r\n    mov edx,%2\r\n    mov ecx,%3\r\n    cmp edx,ecx\r\n    je  %%fin\r\n    and edx,[zerolowbits]\r\n    and ecx,[zerolowbits]\r\n    add ecx,edx\r\n    shr ecx,1\r\n    add ecx,0x0821\r\n    and ecx,[zerolowbits]\r\n    add edx,ecx\r\n    shr edx,1\r\n%%fin\r\n    mov %1,dx\r\n%endmacro\r\n\r\n%macro Interp2 4\r\n    mov edx,%3\r\n    mov ecx,%4\r\n    cmp edx,ecx\r\n    je  %%fin1\r\n    and edx,[zerolowbits]\r\n    and ecx,[zerolowbits]\r\n    add ecx,edx\r\n    shr ecx,1\r\n    add ecx,0x0821\r\n%%fin1\r\n    mov edx,%2\r\n    cmp edx,ecx\r\n    je  %%fin2\r\n    and ecx,[zerolowbits]\r\n    and edx,[zerolowbits]\r\n    add edx,ecx\r\n    shr edx,1\r\n%%fin2\r\n    mov %1,dx\r\n%endmacro\r\n\r\n%macro Interp5 3\r\n    mov edx,%2\r\n    mov ecx,%3\r\n    cmp edx,ecx\r\n    je  %%fin\r\n    and edx,[zerolowbits]\r\n    and ecx,[zerolowbits]\r\n    add edx,ecx\r\n    shr edx,1\r\n%%fin\r\n    mov %1,dx\r\n%endmacro\r\n\r\n%macro Interp6 3\r\n    mov        ecx, _HQ2X_LUT16to32\r\n    movd       mm1, [ecx+eax*4]\r\n    mov        edx, %2\r\n    movd       mm2, [ecx+edx*4]\r\n    mov        edx, %3\r\n    movd       mm3, [ecx+edx*4]\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    pmullw     mm1, [const5]\r\n    psllw      mm2, 1\r\n    paddw      mm1, mm3\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 5\r\n    packuswb   mm1, [reg_blank]\r\n    movd       edx, mm1\r\n    shl        dl,  2\r\n    shr        edx, 1\r\n    shl        dx,  3\r\n    shr        edx, 5\r\n    mov        %1,  dx\r\n%endmacro\r\n\r\n%macro Interp7 3\r\n    mov        ecx, _HQ2X_LUT16to32\r\n    movd       mm1, [ecx+eax*4]\r\n    mov        edx, %2\r\n    movd       mm2, [ecx+edx*4]\r\n    mov        edx, %3\r\n    movd       mm3, [ecx+edx*4]\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    pmullw     mm1, [const6]\r\n    paddw      mm2, mm3\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 5\r\n    packuswb   mm1, [reg_blank]\r\n    movd       edx, mm1\r\n    shl        dl,  2\r\n    shr        edx, 1\r\n    shl        dx,  3\r\n    shr        edx, 5\r\n    mov        %1,  dx\r\n%endmacro\r\n\r\n%macro Interp9 3\r\n    mov        ecx, _HQ2X_LUT16to32\r\n    movd       mm1, [ecx+eax*4]\r\n    mov        edx, %2\r\n    movd       mm2, [ecx+edx*4]\r\n    mov        edx, %3\r\n    movd       mm3, [ecx+edx*4]\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    psllw      mm1, 1\r\n    paddw      mm2, mm3\r\n    pmullw     mm2, [const3]\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 5\r\n    packuswb   mm1, [reg_blank]\r\n    movd       edx, mm1\r\n    shl        dl,  2\r\n    shr        edx, 1\r\n    shl        dx,  3\r\n    shr        edx, 5\r\n    mov        %1,  dx\r\n%endmacro\r\n\r\n%macro Interp10 3\r\n    mov        ecx, _HQ2X_LUT16to32\r\n    movd       mm1, [ecx+eax*4]\r\n    mov        edx, %2\r\n    movd       mm2, [ecx+edx*4]\r\n    mov        edx, %3\r\n    movd       mm3, [ecx+edx*4]\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    pmullw     mm1, [const14]\r\n    paddw      mm2, mm3\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 6\r\n    packuswb   mm1, [reg_blank]\r\n    movd       edx, mm1\r\n    shl        dl,  2\r\n    shr        edx, 1\r\n    shl        dx,  3\r\n    shr        edx, 5\r\n    mov        %1,  dx\r\n%endmacro\r\n\r\n%macro PIXEL00_0 0\r\n    mov [edi],ax\r\n%endmacro\r\n\r\n%macro PIXEL00_10 0\r\n    Interp1 [edi],eax,[w1]\r\n%endmacro\r\n\r\n%macro PIXEL00_11 0\r\n    Interp1 [edi],eax,[w4]\r\n%endmacro\r\n\r\n%macro PIXEL00_12 0\r\n    Interp1 [edi],eax,[w2]\r\n%endmacro\r\n\r\n%macro PIXEL00_20 0\r\n    Interp2 [edi],eax,[w4],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL00_21 0\r\n    Interp2 [edi],eax,[w1],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL00_22 0\r\n    Interp2 [edi],eax,[w1],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL00_60 0\r\n    Interp6 [edi],[w2],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL00_61 0\r\n    Interp6 [edi],[w4],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL00_70 0\r\n    Interp7 [edi],[w4],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL00_90 0\r\n    Interp9 [edi],[w4],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL00_100 0\r\n    Interp10 [edi],[w4],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL01_0 0\r\n    mov [edi+2],ax\r\n%endmacro\r\n\r\n%macro PIXEL01_10 0\r\n    Interp1 [edi+2],eax,[w3]\r\n%endmacro\r\n\r\n%macro PIXEL01_11 0\r\n    Interp1 [edi+2],eax,[w2]\r\n%endmacro\r\n\r\n%macro PIXEL01_12 0\r\n    Interp1 [edi+2],eax,[w6]\r\n%endmacro\r\n\r\n%macro PIXEL01_20 0\r\n    Interp2 [edi+2],eax,[w2],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL01_21 0\r\n    Interp2 [edi+2],eax,[w3],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL01_22 0\r\n    Interp2 [edi+2],eax,[w3],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL01_60 0\r\n    Interp6 [edi+2],[w6],[w2]\r\n%endmacro\r\n\r\n%macro PIXEL01_61 0\r\n    Interp6 [edi+2],[w2],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL01_70 0\r\n    Interp7 [edi+2],[w2],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL01_90 0\r\n    Interp9 [edi+2],[w2],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL01_100 0\r\n    Interp10 [edi+2],[w2],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL10_0 0\r\n    mov [edi+ebx],ax\r\n%endmacro\r\n\r\n%macro PIXEL10_10 0\r\n    Interp1 [edi+ebx],eax,[w7]\r\n%endmacro\r\n\r\n%macro PIXEL10_11 0\r\n    Interp1 [edi+ebx],eax,[w8]\r\n%endmacro\r\n\r\n%macro PIXEL10_12 0\r\n    Interp1 [edi+ebx],eax,[w4]\r\n%endmacro\r\n\r\n%macro PIXEL10_20 0\r\n    Interp2 [edi+ebx],eax,[w8],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL10_21 0\r\n    Interp2 [edi+ebx],eax,[w7],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL10_22 0\r\n    Interp2 [edi+ebx],eax,[w7],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL10_60 0\r\n    Interp6 [edi+ebx],[w4],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL10_61 0\r\n    Interp6 [edi+ebx],[w8],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL10_70 0\r\n    Interp7 [edi+ebx],[w8],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL10_90 0\r\n    Interp9 [edi+ebx],[w8],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL10_100 0\r\n    Interp10 [edi+ebx],[w8],[w4]\r\n%endmacro\r\n\r\n%macro PIXEL11_0 0\r\n    mov [edi+ebx+2],ax\r\n%endmacro\r\n\r\n%macro PIXEL11_10 0\r\n    Interp1 [edi+ebx+2],eax,[w9]\r\n%endmacro\r\n\r\n%macro PIXEL11_11 0\r\n    Interp1 [edi+ebx+2],eax,[w6]\r\n%endmacro\r\n\r\n%macro PIXEL11_12 0\r\n    Interp1 [edi+ebx+2],eax,[w8]\r\n%endmacro\r\n\r\n%macro PIXEL11_20 0\r\n    Interp2 [edi+ebx+2],eax,[w6],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL11_21 0\r\n    Interp2 [edi+ebx+2],eax,[w9],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL11_22 0\r\n    Interp2 [edi+ebx+2],eax,[w9],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL11_60 0\r\n    Interp6 [edi+ebx+2],[w8],[w6]\r\n%endmacro\r\n\r\n%macro PIXEL11_61 0\r\n    Interp6 [edi+ebx+2],[w6],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL11_70 0\r\n    Interp7 [edi+ebx+2],[w6],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL11_90 0\r\n    Interp9 [edi+ebx+2],[w6],[w8]\r\n%endmacro\r\n\r\n%macro PIXEL11_100 0\r\n    Interp10 [edi+ebx+2],[w6],[w8]\r\n%endmacro\r\n\r\ninbuffer     equ 8\r\noutbuffer    equ 12\r\nXres         equ 16\r\nYres         equ 20\r\npitch        equ 24\r\n\r\n_hq2x_16:\r\n    push ebp\r\n    mov ebp,esp\r\n    pushad\r\n\r\n    mov     esi,[ebp+inbuffer]\r\n    mov     edi,[ebp+outbuffer]\r\n    mov     edx,[ebp+Yres]\r\n    mov     [linesleft],edx\r\n    mov     ebx,[ebp+Xres]\r\n    shl     ebx,1\r\n    mov     dword[prevline],0\r\n    mov     dword[nextline],ebx\r\n.loopy\r\n    mov     ecx,[ebp+Xres]\r\n    sub     ecx,2                 ; x={Xres-2, Xres-1} are special cases.\r\n    mov     dword[xcounter],ecx\r\n    ; x=0 - special case\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx]\r\n    movq    mm6,[esi]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx]\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w1],edx\r\n    mov     [w2],edx\r\n    shr     eax,16\r\n    mov     [w3],eax\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w4],edx\r\n    mov     [w5],edx\r\n    shr     eax,16\r\n    mov     [w6],eax\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w7],edx\r\n    mov     [w8],edx\r\n    shr     eax,16\r\n    mov     [w9],eax\r\n    jmp     .flags\r\n.loopx\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx-2]\r\n    movq    mm6,[esi-2]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx-2]\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w1],edx\r\n    shr     eax,16\r\n    mov     [w2],eax\r\n    psrlq   mm5,32\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w3],edx\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w4],edx\r\n    shr     eax,16\r\n    mov     [w5],eax\r\n    psrlq   mm6,32\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w6],edx\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w7],edx\r\n    shr     eax,16\r\n    mov     [w8],eax\r\n    psrlq   mm7,32\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w9],edx\r\n.flags\r\n    mov     ebx,_HQ2X_RGBtoYUV\r\n    mov     eax,[w5]\r\n    xor     ecx,ecx\r\n    movd    mm5,[ebx+eax*4]\r\n    mov     dword[cross],0\r\n\r\n    mov     edx,[w2]\r\n    cmp     eax,edx\r\n    je      .noflag2\r\n    or      dword[cross],1\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag2\r\n    or      ecx,2\r\n.noflag2\r\n    mov     edx,[w4]\r\n    cmp     eax,edx\r\n    je      .noflag4\r\n    or      dword[cross],2\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag4\r\n    or      ecx,8\r\n.noflag4\r\n    mov     edx,[w6]\r\n    cmp     eax,edx\r\n    je      .noflag6\r\n    or      dword[cross],4\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag6\r\n    or      ecx,16\r\n.noflag6\r\n    mov     edx,[w8]\r\n    cmp     eax,edx\r\n    je      .noflag8\r\n    or      dword[cross],8\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag8\r\n    or      ecx,64\r\n.noflag8\r\n    test    ecx,ecx\r\n    jnz     .testflag1\r\n    mov     ecx,[cross]\r\n    mov     ebx,[ebp+pitch]\r\n    jmp     [FuncTable2+ecx*4]\r\n.testflag1\r\n    mov     edx,[w1]\r\n    cmp     eax,edx\r\n    je      .noflag1\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag1\r\n    or      ecx,1\r\n.noflag1\r\n    mov     edx,[w3]\r\n    cmp     eax,edx\r\n    je      .noflag3\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag3\r\n    or      ecx,4\r\n.noflag3\r\n    mov     edx,[w7]\r\n    cmp     eax,edx\r\n    je      .noflag7\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag7\r\n    or      ecx,32\r\n.noflag7\r\n    mov     edx,[w9]\r\n    cmp     eax,edx\r\n    je      .noflag9\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag9\r\n    or      ecx,128\r\n.noflag9\r\n    mov  ebx,[ebp+pitch]\r\n    jmp  [FuncTable+ecx*4]\r\n\r\n..@flag0\r\n..@flag1\r\n..@flag4\r\n..@flag32\r\n..@flag128\r\n..@flag5\r\n..@flag132\r\n..@flag160\r\n..@flag33\r\n..@flag129\r\n..@flag36\r\n..@flag133\r\n..@flag164\r\n..@flag161\r\n..@flag37\r\n..@flag165\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag2\r\n..@flag34\r\n..@flag130\r\n..@flag162\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag16\r\n..@flag17\r\n..@flag48\r\n..@flag49\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag64\r\n..@flag65\r\n..@flag68\r\n..@flag69\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag8\r\n..@flag12\r\n..@flag136\r\n..@flag140\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag3\r\n..@flag35\r\n..@flag131\r\n..@flag163\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag6\r\n..@flag38\r\n..@flag134\r\n..@flag166\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag20\r\n..@flag21\r\n..@flag52\r\n..@flag53\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag144\r\n..@flag145\r\n..@flag176\r\n..@flag177\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag192\r\n..@flag193\r\n..@flag196\r\n..@flag197\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag96\r\n..@flag97\r\n..@flag100\r\n..@flag101\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag40\r\n..@flag44\r\n..@flag168\r\n..@flag172\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag9\r\n..@flag13\r\n..@flag137\r\n..@flag141\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag18\r\n..@flag50\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_20\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag80\r\n..@flag81\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag72\r\n..@flag76\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag10\r\n..@flag138\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag66\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag24\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag7\r\n..@flag39\r\n..@flag135\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag148\r\n..@flag149\r\n..@flag180\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag224\r\n..@flag228\r\n..@flag225\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag41\r\n..@flag169\r\n..@flag45\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag22\r\n..@flag54\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag208\r\n..@flag209\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag104\r\n..@flag108\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag11\r\n..@flag139\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag19\r\n..@flag51\r\n    DiffOrNot w2,w6,PIXEL00_11,PIXEL01_10,PIXEL00_60,PIXEL01_90\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag146\r\n..@flag178\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL11_12,PIXEL01_90,PIXEL11_61\r\n    PIXEL10_20\r\n    jmp .loopx_end\r\n..@flag84\r\n..@flag85\r\n    PIXEL00_20\r\n    DiffOrNot w6,w8,PIXEL01_11,PIXEL11_10,PIXEL01_60,PIXEL11_90\r\n    PIXEL10_21\r\n    jmp .loopx_end\r\n..@flag112\r\n..@flag113\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    DiffOrNot w6,w8,PIXEL10_12,PIXEL11_10,PIXEL10_61,PIXEL11_90\r\n    jmp .loopx_end\r\n..@flag200\r\n..@flag204\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL11_11,PIXEL10_90,PIXEL11_60\r\n    jmp .loopx_end\r\n..@flag73\r\n..@flag77\r\n    DiffOrNot w8,w4,PIXEL00_12,PIXEL10_10,PIXEL00_61,PIXEL10_90\r\n    PIXEL01_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag42\r\n..@flag170\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL10_11,PIXEL00_90,PIXEL10_60\r\n    PIXEL01_21\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag14\r\n..@flag142\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL01_12,PIXEL00_90,PIXEL01_61\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag67\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag70\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag28\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag152\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag194\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag98\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag56\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag25\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag26\r\n..@flag31\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag82\r\n..@flag214\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag88\r\n..@flag248\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag74\r\n..@flag107\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag27\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag86\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_21\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag216\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag106\r\n    PIXEL00_10\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag30\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag210\r\n    PIXEL00_22\r\n    PIXEL01_10\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag120\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag75\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_10\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag29\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag198\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag184\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag99\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag57\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag71\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag156\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag226\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag60\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag195\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag102\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag153\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag58\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag83\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag92\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag202\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag78\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag154\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag114\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag89\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag90\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag55\r\n..@flag23\r\n    DiffOrNot w2,w6,PIXEL00_11,PIXEL01_0,PIXEL00_60,PIXEL01_90\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag182\r\n..@flag150\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL11_12,PIXEL01_90,PIXEL11_61\r\n    PIXEL10_20\r\n    jmp .loopx_end\r\n..@flag213\r\n..@flag212\r\n    PIXEL00_20\r\n    DiffOrNot w6,w8,PIXEL01_11,PIXEL11_0,PIXEL01_60,PIXEL11_90\r\n    PIXEL10_21\r\n    jmp .loopx_end\r\n..@flag241\r\n..@flag240\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    DiffOrNot w6,w8,PIXEL10_12,PIXEL11_0,PIXEL10_61,PIXEL11_90\r\n    jmp .loopx_end\r\n..@flag236\r\n..@flag232\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL11_11,PIXEL10_90,PIXEL11_60\r\n    jmp .loopx_end\r\n..@flag109\r\n..@flag105\r\n    DiffOrNot w8,w4,PIXEL00_12,PIXEL10_0,PIXEL00_61,PIXEL10_90\r\n    PIXEL01_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag171\r\n..@flag43\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL10_11,PIXEL00_90,PIXEL10_60\r\n    PIXEL01_21\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag143\r\n..@flag15\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL01_12,PIXEL00_90,PIXEL01_61\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag124\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag203\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_10\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag62\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag211\r\n    PIXEL00_11\r\n    PIXEL01_10\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag118\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag217\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag110\r\n    PIXEL00_10\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag155\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag188\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag185\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag61\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag157\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag103\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag227\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag230\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag199\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag220\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag158\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag234\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag242\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag59\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag121\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag87\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag79\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag122\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag94\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag218\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag91\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag229\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag167\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag173\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag181\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag186\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag115\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag93\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag206\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag205\r\n..@flag201\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag174\r\n..@flag46\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_12\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag179\r\n..@flag147\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag117\r\n..@flag116\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag189\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag231\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag126\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag219\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag125\r\n    DiffOrNot w8,w4,PIXEL00_12,PIXEL10_0,PIXEL00_61,PIXEL10_90\r\n    PIXEL01_11\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag221\r\n    PIXEL00_12\r\n    DiffOrNot w6,w8,PIXEL01_11,PIXEL11_0,PIXEL01_60,PIXEL11_90\r\n    PIXEL10_10\r\n    jmp .loopx_end\r\n..@flag207\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL01_12,PIXEL00_90,PIXEL01_61\r\n    PIXEL10_10\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag238\r\n    PIXEL00_10\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL11_11,PIXEL10_90,PIXEL11_60\r\n    jmp .loopx_end\r\n..@flag190\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL11_12,PIXEL01_90,PIXEL11_61\r\n    PIXEL10_11\r\n    jmp .loopx_end\r\n..@flag187\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL10_11,PIXEL00_90,PIXEL10_60\r\n    PIXEL01_10\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag243\r\n    PIXEL00_11\r\n    PIXEL01_10\r\n    DiffOrNot w6,w8,PIXEL10_12,PIXEL11_0,PIXEL10_61,PIXEL11_90\r\n    jmp .loopx_end\r\n..@flag119\r\n    DiffOrNot w2,w6,PIXEL00_11,PIXEL01_0,PIXEL00_60,PIXEL01_90\r\n    PIXEL10_12\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag237\r\n..@flag233\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag175\r\n..@flag47\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    PIXEL01_12\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag183\r\n..@flag151\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag245\r\n..@flag244\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag250\r\n    PIXEL00_10\r\n    PIXEL01_10\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag123\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag95\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_10\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag222\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag252\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag249\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag235\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag111\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag63\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag159\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag215\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag246\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag254\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag253\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag251\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag239\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag127\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag191\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag223\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag247\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag255\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n\r\n\r\n..@cross0\r\n    mov     edx,eax\r\n    shl     eax,16\r\n    or      eax,edx\r\n    mov     [edi],eax\r\n    mov     [edi+ebx],eax\r\n    jmp     .loopx_end\r\n..@cross1\r\n    mov     edx,eax\r\n    shl     eax,16\r\n    or      eax,edx\r\n    mov     ecx,[w2]\r\n    and     edx,[zerolowbits]\r\n    and     ecx,[zerolowbits]\r\n    add     ecx,edx\r\n    shr     ecx,1\r\n    add     ecx,0x0821\r\n    and     ecx,[zerolowbits]\r\n    add     edx,ecx\r\n    shr     edx,1\r\n    mov     ecx,edx\r\n    shl     edx,16\r\n    or      edx,ecx\r\n    mov     [edi],edx\r\n    mov     [edi+ebx],eax\r\n    jmp     .loopx_end\r\n..@cross2\r\n    shl     eax,16\r\n    mov     ecx,[w4]\r\n    and     edx,[zerolowbits]\r\n    and     ecx,[zerolowbits]\r\n    add     ecx,edx\r\n    shr     ecx,1\r\n    add     ecx,0x0821\r\n    and     ecx,[zerolowbits]\r\n    add     edx,ecx\r\n    shr     edx,1\r\n    or      eax,edx\r\n    mov     [edi],eax\r\n    mov     [edi+ebx],eax\r\n    jmp     .loopx_end\r\n..@cross4\r\n    mov     ecx,[w6]\r\n    and     edx,[zerolowbits]\r\n    and     ecx,[zerolowbits]\r\n    add     ecx,edx\r\n    shr     ecx,1\r\n    add     ecx,0x0821\r\n    and     ecx,[zerolowbits]\r\n    add     edx,ecx\r\n    shr     edx,1\r\n    shl     edx,16\r\n    or      eax,edx\r\n    mov     [edi],eax\r\n    mov     [edi+ebx],eax\r\n    jmp     .loopx_end\r\n..@cross8\r\n    mov     edx,eax\r\n    shl     eax,16\r\n    or      eax,edx\r\n    mov     ecx,[w8]\r\n    and     edx,[zerolowbits]\r\n    and     ecx,[zerolowbits]\r\n    add     ecx,edx\r\n    shr     ecx,1\r\n    add     ecx,0x0821\r\n    and     ecx,[zerolowbits]\r\n    add     edx,ecx\r\n    shr     edx,1\r\n    mov     ecx,edx\r\n    shl     edx,16\r\n    or      edx,ecx\r\n    mov     [edi],eax\r\n    mov     [edi+ebx],edx\r\n    jmp     .loopx_end\r\n\r\n.loopx_end\r\n    add     esi,2\r\n    add     edi,4\r\n    dec     dword[xcounter]\r\n    jle     .xres_2\r\n    jmp     .loopx\r\n.xres_2\r\n    ; x=Xres-2 - special case\r\n    jl near .xres_1\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx-4]\r\n    movq    mm6,[esi-4]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx-4]\r\n    psrlq   mm5,16\r\n    psrlq   mm6,16\r\n    psrlq   mm7,16\r\n    movd    eax,mm5\r\n    movzx   edx,ax\r\n    mov     [w1],edx\r\n    shr     eax,16\r\n    mov     [w2],eax\r\n    psrlq   mm5,32\r\n    movd    eax,mm5\r\n    mov     [w3],eax\r\n    movd    eax,mm6\r\n    movzx   edx,ax\r\n    mov     [w4],edx\r\n    shr     eax,16\r\n    mov     [w5],eax\r\n    psrlq   mm6,32\r\n    movd    eax,mm6\r\n    mov     [w6],eax\r\n    movd    eax,mm7\r\n    movzx   edx,ax\r\n    mov     [w7],edx\r\n    shr     eax,16\r\n    mov     [w8],eax\r\n    psrlq   mm7,32\r\n    movd    eax,mm7\r\n    mov     [w9],eax\r\n    jmp     .flags\r\n.xres_1\r\n    cmp     dword[xcounter],-1\r\n    jl      .nexty\r\n    ; x=Xres-1 - special case\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx-6]\r\n    movq    mm6,[esi-6]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx-6]\r\n    psrlq   mm5,32\r\n    psrlq   mm6,32\r\n    psrlq   mm7,32\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w1],edx\r\n    shr     eax,16\r\n    mov     [w2],eax\r\n    mov     [w3],eax\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w4],edx\r\n    shr     eax,16\r\n    mov     [w5],eax\r\n    mov     [w6],eax\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w7],edx\r\n    shr     eax,16\r\n    mov     [w8],eax\r\n    mov     [w9],eax\r\n    jmp     .flags\r\n.nexty\r\n    add     edi,ebx\r\n    dec     dword[linesleft]\r\n    jz      .fin\r\n    mov     ebx,[ebp+Xres]\r\n    shl     ebx,1\r\n    cmp     dword[linesleft],1\r\n    je      .lastline\r\n    mov     dword[nextline],ebx\r\n    neg     ebx\r\n    mov     dword[prevline],ebx\r\n    jmp     .loopy\r\n.lastline\r\n    mov     dword[nextline],0\r\n    neg     ebx\r\n    mov     dword[prevline],ebx\r\n    jmp     .loopy\r\n.fin\r\n    emms\r\n    popad\r\n    mov esp,ebp\r\n    pop ebp\r\n    ret\r\n\r\nSECTION .data\r\nFuncTable\r\n    dd ..@flag0, ..@flag1, ..@flag2, ..@flag3, ..@flag4, ..@flag5, ..@flag6, ..@flag7\r\n    dd ..@flag8, ..@flag9, ..@flag10, ..@flag11, ..@flag12, ..@flag13, ..@flag14, ..@flag15\r\n    dd ..@flag16, ..@flag17, ..@flag18, ..@flag19, ..@flag20, ..@flag21, ..@flag22, ..@flag23\r\n    dd ..@flag24, ..@flag25, ..@flag26, ..@flag27, ..@flag28, ..@flag29, ..@flag30, ..@flag31\r\n    dd ..@flag32, ..@flag33, ..@flag34, ..@flag35, ..@flag36, ..@flag37, ..@flag38, ..@flag39\r\n    dd ..@flag40, ..@flag41, ..@flag42, ..@flag43, ..@flag44, ..@flag45, ..@flag46, ..@flag47\r\n    dd ..@flag48, ..@flag49, ..@flag50, ..@flag51, ..@flag52, ..@flag53, ..@flag54, ..@flag55\r\n    dd ..@flag56, ..@flag57, ..@flag58, ..@flag59, ..@flag60, ..@flag61, ..@flag62, ..@flag63\r\n    dd ..@flag64, ..@flag65, ..@flag66, ..@flag67, ..@flag68, ..@flag69, ..@flag70, ..@flag71\r\n    dd ..@flag72, ..@flag73, ..@flag74, ..@flag75, ..@flag76, ..@flag77, ..@flag78, ..@flag79\r\n    dd ..@flag80, ..@flag81, ..@flag82, ..@flag83, ..@flag84, ..@flag85, ..@flag86, ..@flag87\r\n    dd ..@flag88, ..@flag89, ..@flag90, ..@flag91, ..@flag92, ..@flag93, ..@flag94, ..@flag95\r\n    dd ..@flag96, ..@flag97, ..@flag98, ..@flag99, ..@flag100, ..@flag101, ..@flag102, ..@flag103\r\n    dd ..@flag104, ..@flag105, ..@flag106, ..@flag107, ..@flag108, ..@flag109, ..@flag110, ..@flag111\r\n    dd ..@flag112, ..@flag113, ..@flag114, ..@flag115, ..@flag116, ..@flag117, ..@flag118, ..@flag119\r\n    dd ..@flag120, ..@flag121, ..@flag122, ..@flag123, ..@flag124, ..@flag125, ..@flag126, ..@flag127\r\n    dd ..@flag128, ..@flag129, ..@flag130, ..@flag131, ..@flag132, ..@flag133, ..@flag134, ..@flag135\r\n    dd ..@flag136, ..@flag137, ..@flag138, ..@flag139, ..@flag140, ..@flag141, ..@flag142, ..@flag143\r\n    dd ..@flag144, ..@flag145, ..@flag146, ..@flag147, ..@flag148, ..@flag149, ..@flag150, ..@flag151\r\n    dd ..@flag152, ..@flag153, ..@flag154, ..@flag155, ..@flag156, ..@flag157, ..@flag158, ..@flag159\r\n    dd ..@flag160, ..@flag161, ..@flag162, ..@flag163, ..@flag164, ..@flag165, ..@flag166, ..@flag167\r\n    dd ..@flag168, ..@flag169, ..@flag170, ..@flag171, ..@flag172, ..@flag173, ..@flag174, ..@flag175\r\n    dd ..@flag176, ..@flag177, ..@flag178, ..@flag179, ..@flag180, ..@flag181, ..@flag182, ..@flag183\r\n    dd ..@flag184, ..@flag185, ..@flag186, ..@flag187, ..@flag188, ..@flag189, ..@flag190, ..@flag191\r\n    dd ..@flag192, ..@flag193, ..@flag194, ..@flag195, ..@flag196, ..@flag197, ..@flag198, ..@flag199\r\n    dd ..@flag200, ..@flag201, ..@flag202, ..@flag203, ..@flag204, ..@flag205, ..@flag206, ..@flag207\r\n    dd ..@flag208, ..@flag209, ..@flag210, ..@flag211, ..@flag212, ..@flag213, ..@flag214, ..@flag215\r\n    dd ..@flag216, ..@flag217, ..@flag218, ..@flag219, ..@flag220, ..@flag221, ..@flag222, ..@flag223\r\n    dd ..@flag224, ..@flag225, ..@flag226, ..@flag227, ..@flag228, ..@flag229, ..@flag230, ..@flag231\r\n    dd ..@flag232, ..@flag233, ..@flag234, ..@flag235, ..@flag236, ..@flag237, ..@flag238, ..@flag239\r\n    dd ..@flag240, ..@flag241, ..@flag242, ..@flag243, ..@flag244, ..@flag245, ..@flag246, ..@flag247\r\n    dd ..@flag248, ..@flag249, ..@flag250, ..@flag251, ..@flag252, ..@flag253, ..@flag254, ..@flag255\r\n\r\nFuncTable2\r\n    dd ..@cross0, ..@cross1, ..@cross2, ..@flag0,\r\n    dd ..@cross4, ..@flag0,  ..@flag0,  ..@flag0,\r\n    dd ..@cross8, ..@flag0,  ..@flag0,  ..@flag0,\r\n    dd ..@flag0,  ..@flag0,  ..@flag0,  ..@flag0\r\n\r\n%ifidn __OUTPUT_FORMAT__,elf\r\nsection .note.GNU-stack noalloc noexec nowrite progbits\r\n%endif\r\n"
  },
  {
    "path": "meka/srcs/hq2x32.asm",
    "content": ";hq2x filter\r\n;32bpp output\r\n;----------------------------------------------------------\r\n;Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )\r\n;\r\n;This program is free software; you can redistribute it and/or\r\n;modify it under the terms of the GNU General Public License\r\n;as published by the Free Software Foundation; either\r\n;version 2 of the License, or (at your option) any later\r\n;version.\r\n;\r\n;This program is distributed in the hope that it will be useful,\r\n;but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n;GNU General Public License for more details.\r\n;\r\n;You should have received a copy of the GNU General Public License\r\n;along with this program; if not, write to the Free Software\r\n;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r\n\r\n%IFDEF ASM_SYMBOLS_REQUIRE_UNDERSCORE\r\n%DEFINE  _hq2x_32              hq2x_32\r\n%DEFINE  _HQ2X_LUT16to32       HQ2X_LUT16to32\r\n%DEFINE  _HQ2X_RGBtoYUV        HQ2X_RGBtoYUV\r\n%ENDIF ; ASM_SYMBOLS_REQUIRE_UNDERSCORE\r\n\r\nGLOBAL _hq2x_32\r\n\r\nEXTERN _HQ2X_LUT16to32\r\nEXTERN _HQ2X_RGBtoYUV\r\n\r\nSECTION .bss\r\nlinesleft resd 1\r\nxcounter  resd 1\r\ncross     resd 1\r\nnextline  resd 1\r\nprevline  resd 1\r\nw1        resd 1\r\nw2        resd 1\r\nw3        resd 1\r\nw4        resd 1\r\nw5        resd 1\r\nw6        resd 1\r\nw7        resd 1\r\nw8        resd 1\r\nw9        resd 1\r\nc1        resd 1\r\nc2        resd 1\r\nc3        resd 1\r\nc4        resd 1\r\nc5        resd 1\r\nc6        resd 1\r\nc7        resd 1\r\nc8        resd 1\r\nc9        resd 1\r\n\r\nSECTION .data\r\n\r\nreg_blank    dd  0,0\r\nconst3       dd  0x00030003,0x00000003\r\nconst5       dd  0x00050005,0x00000005\r\nconst6       dd  0x00060006,0x00000006\r\nconst14      dd  0x000E000E,0x0000000E\r\nthreshold    dd  0x00300706,0x00000000\r\n\r\nSECTION .text\r\n\r\n%macro TestDiff 2\r\n    xor     ecx,ecx\r\n    mov     edx,[%1]\r\n    cmp     edx,[%2]\r\n    je      %%fin\r\n    mov     ecx,_HQ2X_RGBtoYUV\r\n    movd    mm1,[ecx+edx*4]\r\n    movq    mm5,mm1\r\n    mov     edx,[%2]\r\n    movd    mm2,[ecx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    ecx,mm1\r\n%%fin:\r\n%endmacro\r\n\r\n%macro DiffOrNot 4\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz   %%same\r\n   %3\r\n   jmp %%fin\r\n%%same:\r\n   %4\r\n%%fin\r\n%endmacro\r\n\r\n%macro DiffOrNot 6\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz   %%same\r\n   %3\r\n   %4\r\n   jmp %%fin\r\n%%same:\r\n   %5\r\n   %6\r\n%%fin\r\n%endmacro\r\n\r\n%macro DiffOrNot 8\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz   %%same\r\n   %3\r\n   %4\r\n   %5\r\n   jmp %%fin\r\n%%same:\r\n   %6\r\n   %7\r\n   %8\r\n%%fin\r\n%endmacro\r\n\r\n%macro DiffOrNot 10\r\n   TestDiff %1,%2\r\n   test ecx,ecx\r\n   jz %%same\r\n   %3\r\n   %4\r\n   %5\r\n   %6\r\n   jmp %%fin\r\n%%same:\r\n   %7\r\n   %8\r\n   %9\r\n   %10\r\n%%fin\r\n%endmacro\r\n\r\n%macro Interp1 3\r\n    mov edx,%2\r\n    shl edx,2\r\n    add edx,%3\r\n    sub edx,%2\r\n    shr edx,2\r\n    mov %1,edx\r\n%endmacro\r\n\r\n%macro Interp2 4\r\n    mov edx,%2\r\n    shl edx,1\r\n    add edx,%3\r\n    add edx,%4\r\n    shr edx,2\r\n    mov %1,edx\r\n%endmacro\r\n\r\n%macro Interp5 3\r\n    mov edx,%2\r\n    add edx,%3\r\n    shr edx,1\r\n    mov %1,edx\r\n%endmacro\r\n\r\n%macro Interp6 3\r\n    movd       mm1, eax\r\n    movd       mm2, %2\r\n    movd       mm3, %3\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    pmullw     mm1, [const5]\r\n    psllw      mm2, 1\r\n    paddw      mm1, mm3\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 3\r\n    packuswb   mm1, [reg_blank]\r\n    movd       %1, mm1\r\n%endmacro\r\n\r\n%macro Interp7 3\r\n    movd       mm1, eax\r\n    movd       mm2, %2\r\n    movd       mm3, %3\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    pmullw     mm1, [const6]\r\n    paddw      mm2, mm3\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 3\r\n    packuswb   mm1, [reg_blank]\r\n    movd       %1, mm1\r\n%endmacro\r\n\r\n%macro Interp9 3\r\n    movd       mm1, eax\r\n    movd       mm2, %2\r\n    movd       mm3, %3\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    psllw      mm1, 1\r\n    paddw      mm2, mm3\r\n    pmullw     mm2, [const3]\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 3\r\n    packuswb   mm1, [reg_blank]\r\n    movd       %1, mm1\r\n%endmacro\r\n\r\n%macro Interp10 3\r\n    movd       mm1, eax\r\n    movd       mm2, %2\r\n    movd       mm3, %3\r\n    punpcklbw  mm1, [reg_blank]\r\n    punpcklbw  mm2, [reg_blank]\r\n    punpcklbw  mm3, [reg_blank]\r\n    pmullw     mm1, [const14]\r\n    paddw      mm2, mm3\r\n    paddw      mm1, mm2\r\n    psrlw      mm1, 4\r\n    packuswb   mm1, [reg_blank]\r\n    movd       %1, mm1\r\n%endmacro\r\n\r\n%macro PIXEL00_0 0\r\n    mov [edi],eax\r\n%endmacro\r\n\r\n%macro PIXEL00_10 0\r\n    Interp1 [edi],eax,[c1]\r\n%endmacro\r\n\r\n%macro PIXEL00_11 0\r\n    Interp1 [edi],eax,[c4]\r\n%endmacro\r\n\r\n%macro PIXEL00_12 0\r\n    Interp1 [edi],eax,[c2]\r\n%endmacro\r\n\r\n%macro PIXEL00_20 0\r\n    Interp2 [edi],eax,[c4],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL00_21 0\r\n    Interp2 [edi],eax,[c1],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL00_22 0\r\n    Interp2 [edi],eax,[c1],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL00_60 0\r\n    Interp6 [edi],[c2],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL00_61 0\r\n    Interp6 [edi],[c4],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL00_70 0\r\n    Interp7 [edi],[c4],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL00_90 0\r\n    Interp9 [edi],[c4],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL00_100 0\r\n    Interp10 [edi],[c4],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL01_0 0\r\n    mov [edi+4],eax\r\n%endmacro\r\n\r\n%macro PIXEL01_10 0\r\n    Interp1 [edi+4],eax,[c3]\r\n%endmacro\r\n\r\n%macro PIXEL01_11 0\r\n    Interp1 [edi+4],eax,[c2]\r\n%endmacro\r\n\r\n%macro PIXEL01_12 0\r\n    Interp1 [edi+4],eax,[c6]\r\n%endmacro\r\n\r\n%macro PIXEL01_20 0\r\n    Interp2 [edi+4],eax,[c2],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL01_21 0\r\n    Interp2 [edi+4],eax,[c3],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL01_22 0\r\n    Interp2 [edi+4],eax,[c3],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL01_60 0\r\n    Interp6 [edi+4],[c6],[c2]\r\n%endmacro\r\n\r\n%macro PIXEL01_61 0\r\n    Interp6 [edi+4],[c2],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL01_70 0\r\n    Interp7 [edi+4],[c2],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL01_90 0\r\n    Interp9 [edi+4],[c2],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL01_100 0\r\n    Interp10 [edi+4],[c2],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL10_0 0\r\n    mov [edi+ebx],eax\r\n%endmacro\r\n\r\n%macro PIXEL10_10 0\r\n    Interp1 [edi+ebx],eax,[c7]\r\n%endmacro\r\n\r\n%macro PIXEL10_11 0\r\n    Interp1 [edi+ebx],eax,[c8]\r\n%endmacro\r\n\r\n%macro PIXEL10_12 0\r\n    Interp1 [edi+ebx],eax,[c4]\r\n%endmacro\r\n\r\n%macro PIXEL10_20 0\r\n    Interp2 [edi+ebx],eax,[c8],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL10_21 0\r\n    Interp2 [edi+ebx],eax,[c7],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL10_22 0\r\n    Interp2 [edi+ebx],eax,[c7],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL10_60 0\r\n    Interp6 [edi+ebx],[c4],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL10_61 0\r\n    Interp6 [edi+ebx],[c8],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL10_70 0\r\n    Interp7 [edi+ebx],[c8],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL10_90 0\r\n    Interp9 [edi+ebx],[c8],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL10_100 0\r\n    Interp10 [edi+ebx],[c8],[c4]\r\n%endmacro\r\n\r\n%macro PIXEL11_0 0\r\n    mov [edi+ebx+4],eax\r\n%endmacro\r\n\r\n%macro PIXEL11_10 0\r\n    Interp1 [edi+ebx+4],eax,[c9]\r\n%endmacro\r\n\r\n%macro PIXEL11_11 0\r\n    Interp1 [edi+ebx+4],eax,[c6]\r\n%endmacro\r\n\r\n%macro PIXEL11_12 0\r\n    Interp1 [edi+ebx+4],eax,[c8]\r\n%endmacro\r\n\r\n%macro PIXEL11_20 0\r\n    Interp2 [edi+ebx+4],eax,[c6],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL11_21 0\r\n    Interp2 [edi+ebx+4],eax,[c9],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL11_22 0\r\n    Interp2 [edi+ebx+4],eax,[c9],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL11_60 0\r\n    Interp6 [edi+ebx+4],[c8],[c6]\r\n%endmacro\r\n\r\n%macro PIXEL11_61 0\r\n    Interp6 [edi+ebx+4],[c6],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL11_70 0\r\n    Interp7 [edi+ebx+4],[c6],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL11_90 0\r\n    Interp9 [edi+ebx+4],[c6],[c8]\r\n%endmacro\r\n\r\n%macro PIXEL11_100 0\r\n    Interp10 [edi+ebx+4],[c6],[c8]\r\n%endmacro\r\n\r\ninbuffer     equ 8\r\noutbuffer    equ 12\r\nXres         equ 16\r\nYres         equ 20\r\npitch        equ 24\r\n\r\n_hq2x_32:\r\n    push ebp\r\n    mov ebp,esp\r\n    pushad\r\n\r\n    mov     esi,[ebp+inbuffer]\r\n    mov     edi,[ebp+outbuffer]\r\n    mov     edx,[ebp+Yres]\r\n    mov     [linesleft],edx\r\n    mov     ebx,[ebp+Xres]\r\n    shl     ebx,1\r\n    mov     dword[prevline],0\r\n    mov     dword[nextline],ebx\r\n.loopy\r\n    mov     ecx,[ebp+Xres]\r\n    sub     ecx,2                 ; x={Xres-2, Xres-1} are special cases.\r\n    mov     dword[xcounter],ecx\r\n    ; x=0 - special case\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx]\r\n    movq    mm6,[esi]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx]\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w1],edx\r\n    mov     [w2],edx\r\n    shr     eax,16\r\n    mov     [w3],eax\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w4],edx\r\n    mov     [w5],edx\r\n    shr     eax,16\r\n    mov     [w6],eax\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w7],edx\r\n    mov     [w8],edx\r\n    shr     eax,16\r\n    mov     [w9],eax\r\n    jmp     .flags\r\n.loopx\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx-2]\r\n    movq    mm6,[esi-2]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx-2]\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w1],edx\r\n    shr     eax,16\r\n    mov     [w2],eax\r\n    psrlq   mm5,32\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w3],edx\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w4],edx\r\n    shr     eax,16\r\n    mov     [w5],eax\r\n    psrlq   mm6,32\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w6],edx\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w7],edx\r\n    shr     eax,16\r\n    mov     [w8],eax\r\n    psrlq   mm7,32\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w9],edx\r\n.flags\r\n    mov     ebx,_HQ2X_RGBtoYUV\r\n    mov     eax,[w5]\r\n    xor     ecx,ecx\r\n    movd    mm5,[ebx+eax*4]\r\n    mov     dword[cross],0\r\n\r\n    mov     edx,[w2]\r\n    cmp     eax,edx\r\n    je      .noflag2\r\n    or      dword[cross],1\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag2\r\n    or      ecx,2\r\n.noflag2\r\n    mov     edx,[w4]\r\n    cmp     eax,edx\r\n    je      .noflag4\r\n    or      dword[cross],2\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag4\r\n    or      ecx,8\r\n.noflag4\r\n    mov     edx,[w6]\r\n    cmp     eax,edx\r\n    je      .noflag6\r\n    or      dword[cross],4\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag6\r\n    or      ecx,16\r\n.noflag6\r\n    mov     edx,[w8]\r\n    cmp     eax,edx\r\n    je      .noflag8\r\n    or      dword[cross],8\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag8\r\n    or      ecx,64\r\n.noflag8\r\n    test    ecx,ecx\r\n    jnz     .testflag1\r\n    mov     ecx,[cross]\r\n    mov     ebx,_HQ2X_LUT16to32\r\n    mov     eax,[ebx+eax*4]\r\n    jmp     [FuncTable2+ecx*4]\r\n.testflag1\r\n    mov     edx,[w1]\r\n    cmp     eax,edx\r\n    je      .noflag1\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag1\r\n    or      ecx,1\r\n.noflag1\r\n    mov     edx,[w3]\r\n    cmp     eax,edx\r\n    je      .noflag3\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag3\r\n    or      ecx,4\r\n.noflag3\r\n    mov     edx,[w7]\r\n    cmp     eax,edx\r\n    je      .noflag7\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag7\r\n    or      ecx,32\r\n.noflag7\r\n    mov     edx,[w9]\r\n    cmp     eax,edx\r\n    je      .noflag9\r\n    movq    mm1,mm5\r\n    movd    mm2,[ebx+edx*4]\r\n    psubusb mm1,mm2\r\n    psubusb mm2,mm5\r\n    por     mm1,mm2\r\n    psubusb mm1,[threshold]\r\n    movd    edx,mm1\r\n    test    edx,edx\r\n    jz      .noflag9\r\n    or      ecx,128\r\n.noflag9\r\n    mov  ebx,_HQ2X_LUT16to32\r\n    mov  eax,[ebx+eax*4]\r\n    mov  edx,[w2]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c2],edx\r\n    mov  edx,[w4]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c4],edx\r\n    mov  edx,[w6]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c6],edx\r\n    mov  edx,[w8]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c8],edx\r\n    test ecx,0x005A\r\n    jz  .switch\r\n    mov  edx,[w1]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c1],edx\r\n    mov  edx,[w3]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c3],edx\r\n    mov  edx,[w7]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c7],edx\r\n    mov  edx,[w9]\r\n    mov  edx,[ebx+edx*4]\r\n    mov  [c9],edx\r\n.switch\r\n    mov  ebx,[ebp+pitch]\r\n    jmp  [FuncTable+ecx*4]\r\n\r\n..@flag0\r\n..@flag1\r\n..@flag4\r\n..@flag32\r\n..@flag128\r\n..@flag5\r\n..@flag132\r\n..@flag160\r\n..@flag33\r\n..@flag129\r\n..@flag36\r\n..@flag133\r\n..@flag164\r\n..@flag161\r\n..@flag37\r\n..@flag165\r\n;    PIXEL00_20\r\n;    PIXEL01_20\r\n;    PIXEL10_20\r\n;    PIXEL11_20\r\n\r\n;   the same, only optimized\r\n    shl eax,1\r\n    mov ecx,eax\r\n    add ecx,[c2]\r\n    mov edx,ecx\r\n    add edx,[c4]\r\n    shr edx,2\r\n    mov [edi],edx\r\n    add ecx,[c6]\r\n    shr ecx,2\r\n    mov [edi+4],ecx\r\n    mov ecx,eax\r\n    add ecx,[c8]\r\n    mov edx,ecx\r\n    add edx,[c4]\r\n    shr edx,2\r\n    mov [edi+ebx],edx\r\n    add ecx,[c6]\r\n    shr ecx,2\r\n    mov [edi+ebx+4],ecx\r\n    jmp .loopx_end\r\n..@flag2\r\n..@flag34\r\n..@flag130\r\n..@flag162\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag16\r\n..@flag17\r\n..@flag48\r\n..@flag49\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag64\r\n..@flag65\r\n..@flag68\r\n..@flag69\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag8\r\n..@flag12\r\n..@flag136\r\n..@flag140\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag3\r\n..@flag35\r\n..@flag131\r\n..@flag163\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag6\r\n..@flag38\r\n..@flag134\r\n..@flag166\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag20\r\n..@flag21\r\n..@flag52\r\n..@flag53\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag144\r\n..@flag145\r\n..@flag176\r\n..@flag177\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag192\r\n..@flag193\r\n..@flag196\r\n..@flag197\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag96\r\n..@flag97\r\n..@flag100\r\n..@flag101\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag40\r\n..@flag44\r\n..@flag168\r\n..@flag172\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag9\r\n..@flag13\r\n..@flag137\r\n..@flag141\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag18\r\n..@flag50\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_20\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag80\r\n..@flag81\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag72\r\n..@flag76\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag10\r\n..@flag138\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag66\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag24\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag7\r\n..@flag39\r\n..@flag135\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag148\r\n..@flag149\r\n..@flag180\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag224\r\n..@flag228\r\n..@flag225\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag41\r\n..@flag169\r\n..@flag45\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag22\r\n..@flag54\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag208\r\n..@flag209\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag104\r\n..@flag108\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag11\r\n..@flag139\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag19\r\n..@flag51\r\n    DiffOrNot w2,w6,PIXEL00_11,PIXEL01_10,PIXEL00_60,PIXEL01_90\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag146\r\n..@flag178\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL11_12,PIXEL01_90,PIXEL11_61\r\n    PIXEL10_20\r\n    jmp .loopx_end\r\n..@flag84\r\n..@flag85\r\n    PIXEL00_20\r\n    DiffOrNot w6,w8,PIXEL01_11,PIXEL11_10,PIXEL01_60,PIXEL11_90\r\n    PIXEL10_21\r\n    jmp .loopx_end\r\n..@flag112\r\n..@flag113\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    DiffOrNot w6,w8,PIXEL10_12,PIXEL11_10,PIXEL10_61,PIXEL11_90\r\n    jmp .loopx_end\r\n..@flag200\r\n..@flag204\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL11_11,PIXEL10_90,PIXEL11_60\r\n    jmp .loopx_end\r\n..@flag73\r\n..@flag77\r\n    DiffOrNot w8,w4,PIXEL00_12,PIXEL10_10,PIXEL00_61,PIXEL10_90\r\n    PIXEL01_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag42\r\n..@flag170\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL10_11,PIXEL00_90,PIXEL10_60\r\n    PIXEL01_21\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag14\r\n..@flag142\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL01_12,PIXEL00_90,PIXEL01_61\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag67\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag70\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag28\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag152\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag194\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag98\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag56\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag25\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag26\r\n..@flag31\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag82\r\n..@flag214\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag88\r\n..@flag248\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag74\r\n..@flag107\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag27\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag86\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_21\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag216\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag106\r\n    PIXEL00_10\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag30\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag210\r\n    PIXEL00_22\r\n    PIXEL01_10\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag120\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag75\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_10\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag29\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag198\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag184\r\n    PIXEL00_21\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag99\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag57\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag71\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag156\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag226\r\n    PIXEL00_22\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag60\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag195\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag102\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag153\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag58\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag83\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag92\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag202\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag78\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag154\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag114\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag89\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag90\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag55\r\n..@flag23\r\n    DiffOrNot w2,w6,PIXEL00_11,PIXEL01_0,PIXEL00_60,PIXEL01_90\r\n    PIXEL10_20\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag182\r\n..@flag150\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL11_12,PIXEL01_90,PIXEL11_61\r\n    PIXEL10_20\r\n    jmp .loopx_end\r\n..@flag213\r\n..@flag212\r\n    PIXEL00_20\r\n    DiffOrNot w6,w8,PIXEL01_11,PIXEL11_0,PIXEL01_60,PIXEL11_90\r\n    PIXEL10_21\r\n    jmp .loopx_end\r\n..@flag241\r\n..@flag240\r\n    PIXEL00_20\r\n    PIXEL01_22\r\n    DiffOrNot w6,w8,PIXEL10_12,PIXEL11_0,PIXEL10_61,PIXEL11_90\r\n    jmp .loopx_end\r\n..@flag236\r\n..@flag232\r\n    PIXEL00_21\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL11_11,PIXEL10_90,PIXEL11_60\r\n    jmp .loopx_end\r\n..@flag109\r\n..@flag105\r\n    DiffOrNot w8,w4,PIXEL00_12,PIXEL10_0,PIXEL00_61,PIXEL10_90\r\n    PIXEL01_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag171\r\n..@flag43\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL10_11,PIXEL00_90,PIXEL10_60\r\n    PIXEL01_21\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag143\r\n..@flag15\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL01_12,PIXEL00_90,PIXEL01_61\r\n    PIXEL10_22\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag124\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag203\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    PIXEL10_10\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag62\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag211\r\n    PIXEL00_11\r\n    PIXEL01_10\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag118\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag217\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag110\r\n    PIXEL00_10\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag155\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag188\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag185\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag61\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag157\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag103\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag227\r\n    PIXEL00_11\r\n    PIXEL01_21\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag230\r\n    PIXEL00_22\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag199\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_21\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag220\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag158\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag234\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag242\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag59\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag121\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag87\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag79\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag122\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag94\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag218\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag91\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag229\r\n    PIXEL00_20\r\n    PIXEL01_20\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag167\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_20\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag173\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag181\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag186\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag115\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag93\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag206\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag205\r\n..@flag201\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag174\r\n..@flag46\r\n    DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70\r\n    PIXEL01_12\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag179\r\n..@flag147\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag117\r\n..@flag116\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70\r\n    jmp .loopx_end\r\n..@flag189\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag231\r\n    PIXEL00_11\r\n    PIXEL01_12\r\n    PIXEL10_12\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag126\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag219\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag125\r\n    DiffOrNot w8,w4,PIXEL00_12,PIXEL10_0,PIXEL00_61,PIXEL10_90\r\n    PIXEL01_11\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag221\r\n    PIXEL00_12\r\n    DiffOrNot w6,w8,PIXEL01_11,PIXEL11_0,PIXEL01_60,PIXEL11_90\r\n    PIXEL10_10\r\n    jmp .loopx_end\r\n..@flag207\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL01_12,PIXEL00_90,PIXEL01_61\r\n    PIXEL10_10\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag238\r\n    PIXEL00_10\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL11_11,PIXEL10_90,PIXEL11_60\r\n    jmp .loopx_end\r\n..@flag190\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL11_12,PIXEL01_90,PIXEL11_61\r\n    PIXEL10_11\r\n    jmp .loopx_end\r\n..@flag187\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL10_11,PIXEL00_90,PIXEL10_60\r\n    PIXEL01_10\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag243\r\n    PIXEL00_11\r\n    PIXEL01_10\r\n    DiffOrNot w6,w8,PIXEL10_12,PIXEL11_0,PIXEL10_61,PIXEL11_90\r\n    jmp .loopx_end\r\n..@flag119\r\n    DiffOrNot w2,w6,PIXEL00_11,PIXEL01_0,PIXEL00_60,PIXEL01_90\r\n    PIXEL10_12\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag237\r\n..@flag233\r\n    PIXEL00_12\r\n    PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag175\r\n..@flag47\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    PIXEL01_12\r\n    PIXEL10_11\r\n    PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag183\r\n..@flag151\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_20\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag245\r\n..@flag244\r\n    PIXEL00_20\r\n    PIXEL01_11\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag250\r\n    PIXEL00_10\r\n    PIXEL01_10\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag123\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag95\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_10\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag222\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag252\r\n    PIXEL00_21\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag249\r\n    PIXEL00_12\r\n    PIXEL01_22\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag235\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_21\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag111\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_22\r\n    jmp .loopx_end\r\n..@flag63\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_11\r\n    PIXEL11_21\r\n    jmp .loopx_end\r\n..@flag159\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_22\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag215\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_21\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag246\r\n    PIXEL00_22\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag254\r\n    PIXEL00_10\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag253\r\n    PIXEL00_12\r\n    PIXEL01_11\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag251\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    PIXEL01_10\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag239\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    PIXEL01_12\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    PIXEL11_11\r\n    jmp .loopx_end\r\n..@flag127\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20\r\n    PIXEL11_10\r\n    jmp .loopx_end\r\n..@flag191\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_11\r\n    PIXEL11_12\r\n    jmp .loopx_end\r\n..@flag223\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_10\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20\r\n    jmp .loopx_end\r\n..@flag247\r\n    PIXEL00_11\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    PIXEL10_12\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n..@flag255\r\n    DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100\r\n    DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100\r\n    DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100\r\n    DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100\r\n    jmp .loopx_end\r\n\r\n\r\n..@cross0\r\n    mov     ebx,[ebp+pitch]\r\n    mov     [edi],eax\r\n    mov     [edi+4],eax\r\n    mov     [edi+ebx],eax\r\n    mov     [edi+ebx+4],eax\r\n    jmp     .loopx_end\r\n..@cross1\r\n    mov     ecx,[w2] \r\n    mov     edx,eax\r\n    shl     edx,2\r\n    add     edx,[ebx+ecx*4]\r\n    sub     edx,eax\r\n    shr     edx,2\r\n    mov     ebx,[ebp+pitch]\r\n    mov     [edi],edx\r\n    mov     [edi+4],edx\r\n    mov     [edi+ebx],eax\r\n    mov     [edi+ebx+4],eax\r\n    jmp     .loopx_end\r\n..@cross2\r\n    mov     ecx,[w4]\r\n    mov     edx,eax\r\n    shl     edx,2\r\n    add     edx,[ebx+ecx*4]\r\n    sub     edx,eax\r\n    shr     edx,2\r\n    mov     ebx,[ebp+pitch]\r\n    mov     [edi],edx\r\n    mov     [edi+4],eax\r\n    mov     [edi+ebx],edx\r\n    mov     [edi+ebx+4],eax\r\n    jmp     .loopx_end\r\n..@cross4\r\n    mov     ecx,[w6]\r\n    mov     edx,eax\r\n    shl     edx,2\r\n    add     edx,[ebx+ecx*4]\r\n    sub     edx,eax\r\n    shr     edx,2\r\n    mov     ebx,[ebp+pitch]\r\n    mov     [edi],eax\r\n    mov     [edi+4],edx\r\n    mov     [edi+ebx],eax\r\n    mov     [edi+ebx+4],edx\r\n    jmp     .loopx_end\r\n..@cross8\r\n    mov     ecx,[w8]\r\n    mov     edx,eax\r\n    shl     edx,2\r\n    add     edx,[ebx+ecx*4]\r\n    sub     edx,eax\r\n    shr     edx,2\r\n    mov     ebx,[ebp+pitch]\r\n    mov     [edi],eax\r\n    mov     [edi+4],eax\r\n    mov     [edi+ebx],edx\r\n    mov     [edi+ebx+4],edx\r\n    jmp     .loopx_end\r\n..@crossN\r\n    mov     edx,[w2]\r\n    mov     ecx,[ebx+edx*4]\r\n    mov     [c2],ecx\r\n    mov     edx,[w4]\r\n    mov     ecx,[ebx+edx*4]\r\n    mov     [c4],ecx\r\n    mov     edx,[w6]\r\n    mov     ecx,[ebx+edx*4]\r\n    mov     [c6],ecx\r\n    mov     edx,[w8]\r\n    mov     ecx,[ebx+edx*4]\r\n    mov     [c8],ecx\r\n    mov     ebx,[ebp+pitch]\r\n    jmp     ..@flag0\r\n\r\n.loopx_end\r\n    add     esi,2\r\n    add     edi,8\r\n    dec     dword[xcounter]\r\n    jle     .xres_2\r\n    jmp     .loopx\r\n.xres_2\r\n    ; x=Xres-2 - special case\r\n    jl near .xres_1\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx-4]\r\n    movq    mm6,[esi-4]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx-4]\r\n    psrlq   mm5,16\r\n    psrlq   mm6,16\r\n    psrlq   mm7,16\r\n    movd    eax,mm5\r\n    movzx   edx,ax\r\n    mov     [w1],edx\r\n    shr     eax,16\r\n    mov     [w2],eax\r\n    psrlq   mm5,32\r\n    movd    eax,mm5\r\n    mov     [w3],eax\r\n    movd    eax,mm6\r\n    movzx   edx,ax\r\n    mov     [w4],edx\r\n    shr     eax,16\r\n    mov     [w5],eax\r\n    psrlq   mm6,32\r\n    movd    eax,mm6\r\n    mov     [w6],eax\r\n    movd    eax,mm7\r\n    movzx   edx,ax\r\n    mov     [w7],edx\r\n    shr     eax,16\r\n    mov     [w8],eax\r\n    psrlq   mm7,32\r\n    movd    eax,mm7\r\n    mov     [w9],eax\r\n    jmp     .flags\r\n.xres_1\r\n    cmp     dword[xcounter],-1\r\n    jl      .nexty\r\n    ; x=Xres-1 - special case\r\n    mov     ebx,[prevline]\r\n    movq    mm5,[esi+ebx-6]\r\n    movq    mm6,[esi-6]\r\n    mov     ebx,[nextline]\r\n    movq    mm7,[esi+ebx-6]\r\n    psrlq   mm5,32\r\n    psrlq   mm6,32\r\n    psrlq   mm7,32\r\n    movd    eax,mm5\r\n    movzx   edx,ax  \r\n    mov     [w1],edx\r\n    shr     eax,16\r\n    mov     [w2],eax\r\n    mov     [w3],eax\r\n    movd    eax,mm6\r\n    movzx   edx,ax  \r\n    mov     [w4],edx\r\n    shr     eax,16\r\n    mov     [w5],eax\r\n    mov     [w6],eax\r\n    movd    eax,mm7\r\n    movzx   edx,ax  \r\n    mov     [w7],edx\r\n    shr     eax,16\r\n    mov     [w8],eax\r\n    mov     [w9],eax\r\n    jmp     .flags\r\n.nexty\r\n    add     edi,ebx\r\n    dec     dword[linesleft]\r\n    jz      .fin\r\n    mov     ebx,[ebp+Xres]\r\n    shl     ebx,1\r\n    cmp     dword[linesleft],1\r\n    je      .lastline\r\n    mov     dword[nextline],ebx\r\n    neg     ebx\r\n    mov     dword[prevline],ebx\r\n    jmp     .loopy\r\n.lastline\r\n    mov     dword[nextline],0\r\n    neg     ebx\r\n    mov     dword[prevline],ebx\r\n    jmp     .loopy\r\n.fin\r\n    emms\r\n    popad\r\n    mov esp,ebp\r\n    pop ebp\r\n    ret\r\n\r\nSECTION .data\r\nFuncTable\r\n    dd ..@flag0, ..@flag1, ..@flag2, ..@flag3, ..@flag4, ..@flag5, ..@flag6, ..@flag7\r\n    dd ..@flag8, ..@flag9, ..@flag10, ..@flag11, ..@flag12, ..@flag13, ..@flag14, ..@flag15\r\n    dd ..@flag16, ..@flag17, ..@flag18, ..@flag19, ..@flag20, ..@flag21, ..@flag22, ..@flag23\r\n    dd ..@flag24, ..@flag25, ..@flag26, ..@flag27, ..@flag28, ..@flag29, ..@flag30, ..@flag31\r\n    dd ..@flag32, ..@flag33, ..@flag34, ..@flag35, ..@flag36, ..@flag37, ..@flag38, ..@flag39\r\n    dd ..@flag40, ..@flag41, ..@flag42, ..@flag43, ..@flag44, ..@flag45, ..@flag46, ..@flag47\r\n    dd ..@flag48, ..@flag49, ..@flag50, ..@flag51, ..@flag52, ..@flag53, ..@flag54, ..@flag55\r\n    dd ..@flag56, ..@flag57, ..@flag58, ..@flag59, ..@flag60, ..@flag61, ..@flag62, ..@flag63\r\n    dd ..@flag64, ..@flag65, ..@flag66, ..@flag67, ..@flag68, ..@flag69, ..@flag70, ..@flag71\r\n    dd ..@flag72, ..@flag73, ..@flag74, ..@flag75, ..@flag76, ..@flag77, ..@flag78, ..@flag79\r\n    dd ..@flag80, ..@flag81, ..@flag82, ..@flag83, ..@flag84, ..@flag85, ..@flag86, ..@flag87\r\n    dd ..@flag88, ..@flag89, ..@flag90, ..@flag91, ..@flag92, ..@flag93, ..@flag94, ..@flag95\r\n    dd ..@flag96, ..@flag97, ..@flag98, ..@flag99, ..@flag100, ..@flag101, ..@flag102, ..@flag103\r\n    dd ..@flag104, ..@flag105, ..@flag106, ..@flag107, ..@flag108, ..@flag109, ..@flag110, ..@flag111\r\n    dd ..@flag112, ..@flag113, ..@flag114, ..@flag115, ..@flag116, ..@flag117, ..@flag118, ..@flag119\r\n    dd ..@flag120, ..@flag121, ..@flag122, ..@flag123, ..@flag124, ..@flag125, ..@flag126, ..@flag127\r\n    dd ..@flag128, ..@flag129, ..@flag130, ..@flag131, ..@flag132, ..@flag133, ..@flag134, ..@flag135\r\n    dd ..@flag136, ..@flag137, ..@flag138, ..@flag139, ..@flag140, ..@flag141, ..@flag142, ..@flag143\r\n    dd ..@flag144, ..@flag145, ..@flag146, ..@flag147, ..@flag148, ..@flag149, ..@flag150, ..@flag151\r\n    dd ..@flag152, ..@flag153, ..@flag154, ..@flag155, ..@flag156, ..@flag157, ..@flag158, ..@flag159\r\n    dd ..@flag160, ..@flag161, ..@flag162, ..@flag163, ..@flag164, ..@flag165, ..@flag166, ..@flag167\r\n    dd ..@flag168, ..@flag169, ..@flag170, ..@flag171, ..@flag172, ..@flag173, ..@flag174, ..@flag175\r\n    dd ..@flag176, ..@flag177, ..@flag178, ..@flag179, ..@flag180, ..@flag181, ..@flag182, ..@flag183\r\n    dd ..@flag184, ..@flag185, ..@flag186, ..@flag187, ..@flag188, ..@flag189, ..@flag190, ..@flag191\r\n    dd ..@flag192, ..@flag193, ..@flag194, ..@flag195, ..@flag196, ..@flag197, ..@flag198, ..@flag199\r\n    dd ..@flag200, ..@flag201, ..@flag202, ..@flag203, ..@flag204, ..@flag205, ..@flag206, ..@flag207\r\n    dd ..@flag208, ..@flag209, ..@flag210, ..@flag211, ..@flag212, ..@flag213, ..@flag214, ..@flag215\r\n    dd ..@flag216, ..@flag217, ..@flag218, ..@flag219, ..@flag220, ..@flag221, ..@flag222, ..@flag223\r\n    dd ..@flag224, ..@flag225, ..@flag226, ..@flag227, ..@flag228, ..@flag229, ..@flag230, ..@flag231\r\n    dd ..@flag232, ..@flag233, ..@flag234, ..@flag235, ..@flag236, ..@flag237, ..@flag238, ..@flag239\r\n    dd ..@flag240, ..@flag241, ..@flag242, ..@flag243, ..@flag244, ..@flag245, ..@flag246, ..@flag247\r\n    dd ..@flag248, ..@flag249, ..@flag250, ..@flag251, ..@flag252, ..@flag253, ..@flag254, ..@flag255\r\n\r\nFuncTable2\r\n    dd ..@cross0, ..@cross1, ..@cross2, ..@crossN,\r\n    dd ..@cross4, ..@crossN, ..@crossN, ..@crossN,\r\n    dd ..@cross8, ..@crossN, ..@crossN, ..@crossN,\r\n    dd ..@crossN, ..@crossN, ..@crossN, ..@crossN\r\n\r\n%ifidn __OUTPUT_FORMAT__,elf\r\nsection .note.GNU-stack noalloc noexec nowrite progbits\r\n%endif\r\n"
  },
  {
    "path": "meka/srcs/inputs.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - inputs.c\r\n// User Inputs & Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"app_options.h\"\r\n#include \"app_palview.h\"\r\n#include \"app_techinfo.h\"\r\n#include \"app_tileview.h\"\r\n#include \"blitintf.h\"\r\n#include \"capture.h\"\r\n#include \"db.h\"\r\n#include \"debugger.h\"\r\n#include \"fskipper.h\"\r\n#include \"glasses.h\"\r\n#include \"inputs_c.h\"\r\n#include \"inputs_t.h\"\r\n#include \"lightgun.h\"\r\n#include \"saves.h\"\r\n#include \"sk1100.h\"\r\n#include \"textbox.h\"\r\n#include \"tvoekaki.h\"\r\n#include \"vdp.h\"\r\n#include \"video.h\"\r\n#include \"vmachine.h\"\r\n#include \"sound/sound_logging.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_inputs Inputs;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Function\r\n//-----------------------------------------------------------------------------\r\n\r\n// SWITCH TO INPUT CURRENTLY DEFINED ------------------------------------------\r\nvoid    Inputs_Switch_Current()\r\n{\r\n    switch (Inputs.Peripheral [PLAYER_1])\r\n    {\r\n    case INPUT_JOYPAD:          Inputs_Switch_Joypad       (); break;\r\n    case INPUT_LIGHTPHASER:     Inputs_Switch_LightPhaser  (); break;\r\n    case INPUT_PADDLECONTROL:   Inputs_Switch_PaddleControl(); break;\r\n    case INPUT_SPORTSPAD:       Inputs_Switch_SportsPad    (); break;\r\n    case INPUT_GRAPHICBOARD:    Inputs_Switch_GraphicBoard (); break;\r\n    case INPUT_GRAPHICBOARD_V2: Inputs_Switch_GraphicBoardV2(); break;\r\n    default: Msg(MSGT_USER, \"Error #691: Input type not defined\"); break;\r\n    }\r\n}\r\n\r\n// SWITCH TO NEXT INPUT PERIPHERAL --------------------------------------------\r\nvoid    Inputs_Peripheral_Next(int Player)\r\n{\r\n    if (Inputs.Peripheral [Player] == INPUT_SPORTSPAD) // Skip TV Oekaki\r\n        Inputs.Peripheral [Player] = INPUT_JOYPAD;\r\n    else\r\n        Inputs.Peripheral [Player] = (t_input_peripheral)((Inputs.Peripheral [Player] + 1) % INPUT_PERIPHERAL_MAX);\r\n    if (Player == PLAYER_1)\r\n        Inputs_Switch_Current();\r\n    else\r\n        Inputs_CFG_Peripheral_Change (Player, Inputs.Peripheral [Player]);\r\n}\r\n\r\n// Check for GUI related inputs\r\n// - Note: 'sk1100_pressed' tells if SK-1100 emulation has taken a key yet.\r\n// - Specific checks are being done here to avoid collision.\r\nvoid        Inputs_Check_GUI(bool sk1100_pressed)\r\n{\r\n    // Update INPUTS configuration in priority, since it eat some keys\r\n    Inputs_CFG_Update(&Inputs_CFG);\r\n    //Inputs_CFG_Map_Change_Update();\r\n    //if (Inputs_CFG.active)\r\n    //    Inputs_CFG.Box->update();\r\n\r\n    switch (g_keyboard_modifiers & (ALLEGRO_KEYMOD_CTRL | ALLEGRO_KEYMOD_ALT | ALLEGRO_KEYMOD_SHIFT))\r\n    {\r\n    case 0: // No modifiers\r\n        {\r\n            // State save/load\r\n            if (Inputs_KeyPressed(ALLEGRO_KEY_F5, FALSE))\r\n                SaveState_Save();\r\n            if (Inputs_KeyPressed(ALLEGRO_KEY_F7, FALSE))\r\n                SaveState_Load();\r\n\r\n            // State change slot\r\n            /*\r\n            if (g_driver->id != DRV_COLECO)\r\n                if (!gui.box_z_ordered[0]->focus_inputs_exclusive) // check note in inputs_u.c::Inputs_Emulation_Update()\r\n                {\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_0, FALSE))  Save_Set_Slot (0);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_1, FALSE))  Save_Set_Slot (1);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_2, FALSE))  Save_Set_Slot (2);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_3, FALSE))  Save_Set_Slot (3);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_4, FALSE))  Save_Set_Slot (4);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_5, FALSE))  Save_Set_Slot (5);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_6, FALSE))  Save_Set_Slot (6);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_7, FALSE))  Save_Set_Slot (7);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_8, FALSE))  Save_Set_Slot (8);\r\n                    if (Inputs_KeyPressed (ALLEGRO_KEY_9, FALSE))  Save_Set_Slot (9);\r\n                }\r\n            */\r\n            if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_F6, FALSE, 30, 3))\r\n                SaveState_SetPrevSlot();\r\n            if (Inputs_KeyPressed_Repeat(ALLEGRO_KEY_F8, FALSE, 30, 3))\r\n                SaveState_SetNextSlot();\r\n\r\n            // Blitters switch\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F1, FALSE))\r\n                Blitters_SwitchNext();\r\n\r\n            // Speed & Frame skip\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F2, FALSE))\r\n                Frame_Skipper_Switch();\r\n            if (Inputs_KeyPressed_Repeat (ALLEGRO_KEY_F3, FALSE, 30, 3))\r\n                Frame_Skipper_Configure (-1);\r\n            if (Inputs_KeyPressed_Repeat (ALLEGRO_KEY_F4, FALSE, 30, 3))\r\n                Frame_Skipper_Configure (1);\r\n\r\n            // Input peripheral\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F9, FALSE))\r\n                Inputs_Peripheral_Next (PLAYER_1);\r\n\r\n            // Switch mode (Fullscreen <-> GUI)\r\n            if (Inputs_KeyPressed (Inputs.Cabinet_Mode ? ALLEGRO_KEY_F10 : ALLEGRO_KEY_ESCAPE, FALSE))\r\n                Action_Switch_Mode();\r\n\r\n            // Sprites Display\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F11, FALSE))\r\n                Action_Switch_Layer_Sprites();\r\n\r\n            // Hard Pause\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F12, FALSE))\r\n                g_machine_pause_requests = 1;\r\n        }\r\n        break;\r\n    case ALLEGRO_KEYMOD_CTRL:\r\n        {\r\n            // Hard Reset\r\n            if (!sk1100_pressed && Inputs_KeyPressed(ALLEGRO_KEY_BACKSPACE, TRUE)) // Note: eat backspace to avoid triggering software reset as well\r\n                Machine_Reset();\r\n\r\n            // Background Display\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F11, FALSE))\r\n                Action_Switch_Layer_Background();\r\n\r\n            // Next frame (pause hack)\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F12, FALSE))\r\n                g_machine_pause_requests = (g_machine_flags & MACHINE_PAUSED) ? 2 : 1;\r\n\r\n            // Load State & Continue\r\n            if (Inputs_KeyPressed(ALLEGRO_KEY_F7, FALSE))\r\n            {\r\n                SaveState_Load();\r\n                if (Debugger.active)\r\n                {\r\n                    char command[128] = \"CONT\";\r\n                    Debugger_InputParseCommand(command);        // non-const input\r\n                }\r\n            }\r\n\r\n            // SK-1100 Keyboard switch\r\n            if (Inputs_KeyPressed (ALLEGRO_KEY_F9, FALSE))\r\n                SK1100_Switch();\r\n\r\n            // CTRL-TAB cycle thru boxes with TAB_STOP flag\r\n            if (Inputs_KeyPressed(ALLEGRO_KEY_TAB, FALSE))\r\n            {\r\n                // Remove keypress\r\n                // FIXME-KEYPRESS\r\n                for (t_list* keypresses = Inputs.KeyPressedQueue; keypresses != NULL; )\r\n                {\r\n                    t_key_press* keypress = (t_key_press*)keypresses->elem;\r\n                    keypresses = keypresses->next;\r\n                    if (keypress->scancode == ALLEGRO_KEY_TAB)\r\n                        list_remove(&Inputs.KeyPressedQueue, keypress);\r\n                }\r\n\r\n                // Cycle focus\r\n                for (int n = gui.boxes_count - 1; n >= 0; n--)\r\n                {\r\n                    t_gui_box* b = gui.boxes_z_ordered[n];\r\n                    if ((b->flags & GUI_BOX_FLAGS_TAB_STOP) && (b->flags & GUI_BOX_FLAGS_ACTIVE))\r\n                    {\r\n                        gui_box_set_focus(b);\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n        }\r\n        break;\r\n   case ALLEGRO_KEYMOD_ALT:\r\n       {\r\n           if (!sk1100_pressed)\r\n           {\r\n               // FPS Counter switch\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_F, FALSE))\r\n                   Frame_Skipper_Switch_FPS_Counter();\r\n               // Applets hotkeys\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_L, FALSE)) FB_Switch();\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_O, FALSE)) Options_Switch();\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_M, FALSE)) TB_Message_Switch();\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_P, FALSE)) PaletteViewer_Switch();\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_T, FALSE)) TileViewer_Switch();\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_I, FALSE)) TechInfo_Switch();\r\n               if (Inputs_KeyPressed (ALLEGRO_KEY_V, FALSE))\r\n               {\r\n                   if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\r\n                       Sound_LogVGM_Stop();\r\n                   else\r\n                       Sound_LogVGM_Start();\r\n               }\r\n\r\n               // Hard Reset\r\n               if (Inputs_KeyPressed(ALLEGRO_KEY_BACKSPACE, TRUE))  // Note: eat backspace to avoid triggering software reset as well\r\n                   Machine_Reset();\r\n\r\n               // GUI fullscreen/windowed\r\n                if (Inputs_KeyPressed (ALLEGRO_KEY_ENTER, FALSE))\r\n                {\r\n                    g_config.video_fullscreen ^= 1;\r\n                    //al_toggle_display_flag(g_display, ALLEGRO_FULLSCREEN_WINDOW, g_config.video_fullscreen);\r\n                    Video_Setup_State();\r\n                    return;\r\n                }\r\n\r\n           }\r\n       }\r\n       break;\r\n    }\r\n\r\n    // Quit emulator\r\n    if (Inputs.Cabinet_Mode && Inputs_KeyDown(ALLEGRO_KEY_ESCAPE))\r\n        opt.Force_Quit = TRUE;\r\n\r\n    // Debugger switch\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n        // Disabled when SK-1100 is emulated because of collision in usage of ScrollLock key\r\n        // Actually on SC-3000 it is hardwired to NMI\r\n        if (!Inputs.SK1100_Enabled && Inputs_KeyPressed(ALLEGRO_KEY_SCROLLLOCK, TRUE))\r\n        //if (!sk1100_pressed && Inputs_KeyPressed (ALLEGRO_KEY_SCROLLLOCK, TRUE))\r\n            Debugger_Switch();\r\n    #endif\r\n\r\n    // Screen capture\r\n    if (Inputs_KeyPressed(ALLEGRO_KEY_PRINTSCREEN, FALSE))\r\n        Capture_Request();\r\n\r\n    // SF-7000 Disk 21 Bomber Raid\r\n    // if (Test_Key(KEY_W))\r\n    //     PSG.Registers[6] = PSG.Registers[6] ^ 0x04;\r\n\r\n    // Wonder Boy III, Current Song\r\n    //if (key[KEY_J])\r\n    //   Msg(0, \"RAM[0xFF9] = %02X\", RAM[0xFF9]);\r\n}\r\n\r\n// ACTION: SET INPUT TO STANDARD JOYPADS --------------------------------------\r\nvoid    Inputs_Switch_Joypad()\r\n{\r\n    Inputs_CFG_Peripheral_Change (PLAYER_1, INPUT_JOYPAD);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_Joypad));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Digital));\r\n    gui_menu_uncheck_range (menus_ID.inputs, 0, 5);\r\n    gui_menu_check (menus_ID.inputs, Inputs.Peripheral[PLAYER_1]);\r\n}\r\n\r\n// INPUTS: SET INPUT TO LIGHT PHASER ------------------------------------------\r\nvoid    Inputs_Switch_LightPhaser()\r\n{\r\n    Inputs_CFG_Peripheral_Change (PLAYER_1, INPUT_LIGHTPHASER);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_LightPhaser));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Mouse));\r\n    gui_menu_uncheck_range (menus_ID.inputs, 0, 5);\r\n    gui_menu_check (menus_ID.inputs, Inputs.Peripheral[PLAYER_1]);\r\n}\r\n\r\n// INPUTS: SET INPUT TO PADDLE CONTROLLER -------------------------------------\r\nvoid    Inputs_Switch_PaddleControl()\r\n{\r\n    Inputs_CFG_Peripheral_Change (PLAYER_1, INPUT_PADDLECONTROL);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_PaddleControl));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Mouse));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Digital_Unrecommended));\r\n    gui_menu_uncheck_range (menus_ID.inputs, 0, 5);\r\n    gui_menu_check (menus_ID.inputs, Inputs.Peripheral[PLAYER_1]);\r\n}\r\n\r\nvoid    Inputs_Switch_SportsPad()\r\n{\r\n    Inputs_CFG_Peripheral_Change (PLAYER_1, INPUT_SPORTSPAD);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_SportsPad));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Mouse));\r\n    gui_menu_uncheck_range (menus_ID.inputs, 0, 5);\r\n    gui_menu_check (menus_ID.inputs, Inputs.Peripheral[PLAYER_1]);\r\n}\r\n\r\nvoid    Inputs_Switch_GraphicBoard()\r\n{\r\n    Inputs_CFG_Peripheral_Change (PLAYER_1, INPUT_GRAPHICBOARD);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_GraphicBoard));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Pen));\r\n    gui_menu_uncheck_range (menus_ID.inputs, 0, 5);\r\n    gui_menu_check (menus_ID.inputs, Inputs.Peripheral[PLAYER_1]);\r\n}\r\n\r\nvoid    Inputs_Switch_GraphicBoardV2()\r\n{\r\n    Inputs_CFG_Peripheral_Change (PLAYER_1, INPUT_GRAPHICBOARD_V2);\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_GraphicBoardV2));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Inputs_Play_Pen));\r\n    gui_menu_uncheck_range (menus_ID.inputs, 0, 5);\r\n    gui_menu_check (menus_ID.inputs, Inputs.Peripheral[PLAYER_1]);\r\n}\r\n\r\nvoid    Input_ROM_Change()\r\n{\r\n    bool glasses = FALSE;\r\n    t_input_peripheral peripheral = INPUT_JOYPAD;\r\n\r\n    LightPhaser.EmuFunc = LIGHTPHASER_EMU_FUNC_DEFAULT;\r\n    if (t_db_entry* db_entry = DB.current_entry)\r\n    {\r\n        if (db_entry->emu_inputs != -1)\r\n            peripheral = (t_input_peripheral)db_entry->emu_inputs;\r\n        if (db_entry->emu_lightphaser_emu_func != -1)\r\n            LightPhaser.EmuFunc = (t_lightphaser_emu_func)db_entry->emu_lightphaser_emu_func;\r\n        if (db_entry->flags & DB_FLAG_EMU_3D)\r\n            glasses = TRUE;\r\n    }\r\n    if (Inputs.Peripheral[PLAYER_1] != peripheral)\r\n    {\r\n        Inputs.Peripheral[PLAYER_1] = peripheral;\r\n        Inputs_Switch_Current();\r\n    }\r\n    if (Glasses.Enabled != glasses)\r\n    {\r\n        Glasses_Switch_Enable();\r\n    }\r\n}\r\n\r\nu8  Input_Port_DC()\r\n{\r\n    static int paddle_flip_flop = 0;\r\n\r\n    if (Inputs.SK1100_Enabled && (sms.Input_Mode & 7) != 7)\r\n    {\r\n        // Msg(MSGT_USER, \"Keyboard read %d\", sms.Input_Mode & 7);\r\n        return (tsms.Control [sms.Input_Mode & 7] & 0xFF);\r\n    }\r\n    u8 v = tsms.Control[7] & 0xFF;\r\n\r\n    // FIXME: Rewrite all this broken shit properly.\r\n    if (Inputs.Peripheral[PLAYER_1] == INPUT_GRAPHICBOARD_V2)\r\n    {\r\n        const t_peripheral_graphic_board_v2* p = &Inputs.GraphicBoardV2[0];\r\n        v &= 0xF0;\r\n        if (tsms.Port3F & 0x10)\r\n        {\r\n            v &= ~0x1F;\r\n        }\r\n        else\r\n        {\r\n            switch (p->read_index & 7)\r\n            {\r\n            case 0: v &= ~0x10; v |= p->buttons ^ 0x0f; break; // board always ready\r\n            case 1: v |= p->unknown >> 4; break;\r\n            case 2: v |= p->unknown & 0x0f; break;\r\n            case 3: v |= p->x >> 4; break;\r\n            case 4: v |= p->x & 0x0f; break;\r\n            case 5: v |= p->y >> 4; break;\r\n            case 6: v |= p->y & 0x0f; break;\r\n            }\r\n        }\r\n        //Msg(MSGT_DEBUG, \"in $dc read_index = %d --> %02x\", Inputs.GraphicBoardV2[0].read_index, v);\r\n    }\r\n\r\n    if (Inputs.Peripheral [PLAYER_1] == INPUT_PADDLECONTROL || Inputs.Peripheral [PLAYER_1] == INPUT_SPORTSPAD\r\n     || Inputs.Peripheral [PLAYER_2] == INPUT_PADDLECONTROL || Inputs.Peripheral [PLAYER_2] == INPUT_SPORTSPAD)\r\n    {\r\n        const t_peripheral_paddle* paddle_1 = &Inputs.Paddle[0];\r\n        const t_peripheral_paddle* paddle_2 = &Inputs.Paddle[1];\r\n        const t_peripheral_sportspad* sportspad_1 = &Inputs.SportsPad[0];\r\n        const t_peripheral_sportspad* sportspad_2 = &Inputs.SportsPad[1];\r\n        switch (tsms.Port3F)\r\n        {\r\n            // SPORT PAD -----------------------------------------------------------\r\n        case 0x0D: // 00001101: SportsPad 1 bits 4-8\r\n            v &= 0xF0;\r\n            v |= 0x0F & (((sportspad_1->latch & 1) ? sportspad_1->y : sportspad_1->x) >> 4);\r\n            break;\r\n        case 0x2D: // 00101101: SportsPad 1 bits 0-3\r\n            v &= 0xF0;\r\n            v |= 0x0F & (((sportspad_1->latch & 1) ? sportspad_1->y : sportspad_1->x)     );\r\n            break;\r\n        case 0x07: // 00001111: SportsPad 2 bits 4-5\r\n            v &= 0x3F;\r\n            v |= 0xC0 & (((sportspad_2->latch & 1) ? sportspad_2->y : sportspad_2->x) << 2);\r\n            break;\r\n        case 0x87: // 10001111: SportsPad 2 bits 0-1\r\n            v &= 0x3F;\r\n            v |= 0xC0 & (((sportspad_2->latch & 1) ? sportspad_2->y : sportspad_2->x) << 6);\r\n            break;\r\n\r\n            // PADDLE CONTROL ------------------------------------------------------\r\n            // Japanese \"Flip-Flop\" mode\r\n        case 0x55: // 01010101\r\n            if (paddle_flip_flop) // Paddle 1 bits 0-3, Paddle 2 bits 0-1\r\n                v &= (paddle_1->x & 0xF) | ((paddle_2->x << 6) & 0xC0) | 0x10;\r\n            else                  // Paddle 1 bits 4-7, Paddle 2 bits 4-5\r\n                v &= ((paddle_1->x >> 4) & 0xF) | ((paddle_2->x << 2) & 0xC0) | 0x10;\r\n            break;\r\n            // Export \"Select\" mode\r\n        case 0xDD: // 11011101: Paddle 1 bits 0-3, Paddle 2 bits 0-1\r\n            v &= (paddle_1->x & 0xF) | ((paddle_2->x << 6) & 0xC0) | 0x10;\r\n            break;\r\n        case 0xFD: // 11111101: Paddle 1 bits 4-7, Paddle 2 bits 4-5\r\n            v &= ((paddle_1->x >> 4) & 0xF) | ((paddle_2->x << 2) & 0xC0) | 0x10;\r\n            break;\r\n        case 0xDF: // 11011111: (Paddle 2 bits 0-1 ?)\r\n            break;\r\n        case 0xFF: // 11111111: (Paddle 2 bits 4-5 ?)\r\n            break;\r\n            // default: Msg(MSGT_DEBUG, \"schmilblik error #4444, %02X\", tsms.Port3F);\r\n        }\r\n    }\r\n\r\n    if (Inputs.Peripheral [PLAYER_1] == INPUT_PADDLECONTROL)\r\n    {\r\n        paddle_flip_flop ^= 1;\r\n        if (paddle_flip_flop)\r\n            v |= 0x20;\r\n        else\r\n            v &= ~0x20;\r\n    }\r\n\r\n    // Msg(MSGT_DEBUG, \"AT PC=%04X: IN 0xDC (0x%02X) while Port_3Fh=%02X\", CPU_GetPC, v, tsms.Port3F);\r\n    return (v);\r\n}\r\n\r\nu8  Input_Port_DD()\r\n{\r\n    static int paddle_flip_flop = 0;    // FIXME\r\n\r\n    // SK-1100\r\n    if (Inputs.SK1100_Enabled && (sms.Input_Mode & 7) != 7)\r\n        return (tsms.Control [sms.Input_Mode & 7]  >> 8);\r\n\r\n    // Controllers\r\n    u8 v = (tsms.Control[7]) >> 8;\r\n\r\n    // FIXME: Rewrite all this broken shit properly.\r\n    const t_peripheral_paddle* paddle_1 = &Inputs.Paddle[0];\r\n    const t_peripheral_paddle* paddle_2 = &Inputs.Paddle[1];\r\n    const t_peripheral_sportspad* sportspad_1 = &Inputs.SportsPad[0];\r\n    const t_peripheral_sportspad* sportspad_2 = &Inputs.SportsPad[1];\r\n\r\n    if (Inputs.Peripheral [PLAYER_2] == INPUT_PADDLECONTROL || Inputs.Peripheral [PLAYER_2] == INPUT_SPORTSPAD)\r\n        switch (tsms.Port3F)\r\n    {\r\n        // SPORTS PAD ---------------------------------------------------------\r\n        case 0x07: // 00001111: SportsPad 2 bits 6-7\r\n            v &= 0xFC;\r\n            v |= 0x03 & (((sportspad_2->latch & 1) ? sportspad_2->y : sportspad_2->x) >> 4);\r\n            break;\r\n        case 0x87: // 10001111: SportsPad 2 bits 2-3\r\n            v &= 0xFC;\r\n            v |= 0x03 & (((sportspad_2->latch & 1) ? sportspad_2->y : sportspad_2->x) >> 2);\r\n            break;\r\n\r\n            // PADDLE CONTROL ------------------------------------------------------\r\n            // Japanese \"Flip-Flop\" mode\r\n        case 0x55:\r\n            if (paddle_flip_flop) // Paddle 2 bits 2-3\r\n                v &= 0xFC | ((paddle_2->x >> 2) & 0x3);\r\n            else                  // Paddle 2 bits 6-7\r\n                v &= 0xFC | ((paddle_2->x >> 6) & 0x3);\r\n            break;\r\n            // Export \"Select\" mode\r\n        case 0xDD: // 11011101: Paddle 2 bits 2-3\r\n            v &= 0xFC | ((paddle_2->x >> 2) & 0x3);\r\n            break;\r\n        case 0xFD: // 11111101: Paddle 2 bits 6-7\r\n            v &= 0xFC | ((paddle_2->x >> 6) & 0x3);\r\n            break;\r\n            // default: Msg(MSGT_DEBUG, \"schmilblik error #6666, %02X\", tsms.Port3F);\r\n    }\r\n\r\n    if (Inputs.Peripheral [PLAYER_2] == INPUT_PADDLECONTROL)\r\n    {\r\n        paddle_flip_flop ^= 1;\r\n        // Disabled because paddle 2 is not simulated (input-wise) properly\r\n        // and until that, Super Racing read buttons of the second port as\r\n        // one of the main button, making menus to skip when a paddle is\r\n        // emulated there.\r\n        if (paddle_flip_flop)\r\n            v |= 0x08;\r\n        else\r\n            v &= ~0x08;\r\n    }\r\n\r\n    // Light Gun -----------------------------------------------------------------\r\n    if (Inputs.Peripheral [PLAYER_1] == INPUT_LIGHTPHASER)\r\n        LightPhaser_Sync(PLAYER_1, &v);\r\n    if (Inputs.Peripheral [PLAYER_2] == INPUT_LIGHTPHASER)\r\n        LightPhaser_Sync(PLAYER_2, &v);\r\n    // Nationalisation -----------------------------------------------------------\r\n    Nationalize(&v);\r\n\r\n    // Msg(MSGT_DEBUG, \"AT PC=%04X: IN 0xDD (0x%02X) while Port_3Fh=%02X\", CPU_GetPC, v, tsms.Port3F);\r\n    return (v);\r\n}\r\n\r\n// UPDATE WHAT IS NECESSARY AFTER A PERIPHERAL CHANGE -------------------------\r\nvoid    Inputs_Peripheral_Change_Update()\r\n{\r\n    // Update LightGun.Enabled quick access flag\r\n    LightPhaser.Enabled = (Inputs.Peripheral[0] == INPUT_LIGHTPHASER || Inputs.Peripheral[1] == INPUT_LIGHTPHASER);\r\n\r\n    if (g_env.mouse_installed == -1)\r\n        return;\r\n\r\n    t_mouse_cursor cursor = MEKA_MOUSE_CURSOR_STANDARD;\r\n    int player = PLAYER_1;\r\n\r\n    // Note: Player 1 has priority over Player 2 for cursor\r\n    if (Inputs.Peripheral[PLAYER_2] == INPUT_LIGHTPHASER)       { cursor = MEKA_MOUSE_CURSOR_LIGHT_PHASER; player = PLAYER_2; }\r\n    else if (Inputs.Peripheral[PLAYER_2] == INPUT_SPORTSPAD)    { cursor = MEKA_MOUSE_CURSOR_SPORTS_PAD; player = PLAYER_2; }\r\n    else if (Inputs.Peripheral[PLAYER_2] == INPUT_GRAPHICBOARD || Inputs.Peripheral[PLAYER_2] == INPUT_GRAPHICBOARD_V2) { cursor = MEKA_MOUSE_CURSOR_TV_OEKAKI; player = PLAYER_2; }\r\n\r\n    if (Inputs.Peripheral[PLAYER_1] == INPUT_LIGHTPHASER)       { cursor = MEKA_MOUSE_CURSOR_LIGHT_PHASER; player = PLAYER_1; }\r\n    else if (Inputs.Peripheral[PLAYER_1] == INPUT_SPORTSPAD)    { cursor = MEKA_MOUSE_CURSOR_SPORTS_PAD; player = PLAYER_1; }\r\n    else if (Inputs.Peripheral[PLAYER_1] == INPUT_GRAPHICBOARD || Inputs.Peripheral[PLAYER_1] == INPUT_GRAPHICBOARD_V2) { cursor = MEKA_MOUSE_CURSOR_TV_OEKAKI; player = PLAYER_1; }\r\n\r\n    // Msg(MSGT_DEBUG, \"g_env.state=%d, Cursor=%d, Mask_Left=%d\", g_env.state, Cursor, Mask_Left_8);\r\n\r\n    switch (g_env.state)\r\n    {\r\n    case MEKA_STATE_GAME:\r\n        if (cursor == MEKA_MOUSE_CURSOR_LIGHT_PHASER)\r\n        {\r\n            Inputs_SetMouseCursor(cursor);\r\n            int sx, sy;\r\n            Video_GameMode_EmulatedPosToScreenPos(LightPhaser.X[player], LightPhaser.Y[player], &sx, &sy, false);\r\n            al_set_mouse_xy(g_display, sx, sy);\r\n        }\r\n        else if (cursor == MEKA_MOUSE_CURSOR_TV_OEKAKI)\r\n        {\r\n            Inputs_SetMouseCursor(cursor);\r\n        }\r\n        else\r\n        {\r\n            Inputs_SetMouseCursor(MEKA_MOUSE_CURSOR_NONE);\r\n        }\r\n        break;\r\n    case MEKA_STATE_GUI:\r\n        if (cursor == MEKA_MOUSE_CURSOR_LIGHT_PHASER)\r\n        {\r\n            Inputs_SetMouseCursor(cursor);\r\n            // Note: do not reposition mouse in GUI, this is annoying!\r\n            // position_mouse (LightGun.X [Player] + gamebox_instance->frame.pos.x, LightGun.Y [Player] + gamebox_instance->frame.pos.y);\r\n        }\r\n        else if (cursor == MEKA_MOUSE_CURSOR_SPORTS_PAD || cursor == MEKA_MOUSE_CURSOR_TV_OEKAKI)\r\n        {\r\n            Inputs_SetMouseCursor(cursor);\r\n        }\r\n        else\r\n        {\r\n            Inputs_SetMouseCursor(MEKA_MOUSE_CURSOR_STANDARD);\r\n        }\r\n        break;\r\n    }\r\n}\r\n\r\n// FIXME: Merge with Inputs_Peripheral_Change_Update() ?\r\nvoid    Inputs_SetMouseCursor(t_mouse_cursor mouse_cursor)\r\n{\r\n    Inputs.mouse_cursor = mouse_cursor;\r\n    if (g_env.mouse_installed == -1)\r\n        return;\r\n    switch (mouse_cursor)\r\n    {\r\n    case MEKA_MOUSE_CURSOR_NONE:\r\n        al_hide_mouse_cursor(g_display);\r\n        break;\r\n    case MEKA_MOUSE_CURSOR_STANDARD:\r\n        al_set_mouse_cursor(g_display, Graphics.Cursors.Main);\r\n        al_show_mouse_cursor(g_display);\r\n        break;\r\n    case MEKA_MOUSE_CURSOR_LIGHT_PHASER:\r\n        al_set_mouse_cursor(g_display, Graphics.Cursors.LightPhaser);\r\n        al_show_mouse_cursor(g_display);\r\n        break;\r\n    case MEKA_MOUSE_CURSOR_SPORTS_PAD:\r\n        al_set_mouse_cursor(g_display, Graphics.Cursors.SportsPad);\r\n        al_show_mouse_cursor(g_display);\r\n        break;\r\n    case MEKA_MOUSE_CURSOR_TV_OEKAKI:\r\n        al_set_mouse_cursor(g_display, Graphics.Cursors.TvOekaki);\r\n        al_show_mouse_cursor(g_display);\r\n        break;\r\n    case MEKA_MOUSE_CURSOR_WAIT:\r\n        al_set_mouse_cursor(g_display, Graphics.Cursors.Wait);\r\n        al_show_mouse_cursor(g_display);\r\n        break;\r\n    }\r\n}\r\n\r\n//----------------------------------------------------------\r\n\r\n// Short names for UI\r\nconst t_input_peripheral_info   Inputs_Peripheral_Infos[INPUT_PERIPHERAL_MAX] =\r\n{\r\n    { \"Joypad\"          },\r\n    { \"Light Phaser\"    },\r\n    { \"Paddle Control\"  },\r\n    { \"Sports Pad\"      },\r\n    { \"Terebi Oekaki\"   },\r\n    { \"Graphic Board\"   },\r\n};\r\n\r\nconst char* Inputs_Get_MapName (int Type, int MapIdx)\r\n{\r\n    switch (Type)\r\n    {\r\n    case INPUT_SRC_TYPE_KEYBOARD:\r\n    case INPUT_SRC_TYPE_JOYPAD:\r\n        switch (MapIdx)\r\n        {\r\n        case INPUT_MAP_DIGITAL_UP:      return \"Up\";\r\n        case INPUT_MAP_DIGITAL_DOWN:    return \"Down\";\r\n        case INPUT_MAP_DIGITAL_LEFT:    return \"Left\";\r\n        case INPUT_MAP_DIGITAL_RIGHT:   return \"Right\";\r\n        case INPUT_MAP_BUTTON1:         return \"Button 1\";\r\n        case INPUT_MAP_BUTTON2:         return \"Button 2\";\r\n        case INPUT_MAP_PAUSE_START:     return \"Pause/Start\";\r\n        case INPUT_MAP_RESET:           return \"Reset\";\r\n        }\r\n        break;\r\n    case INPUT_SRC_TYPE_MOUSE:\r\n        switch (MapIdx)\r\n        {\r\n        case INPUT_MAP_ANALOG_AXIS_X:   return \"Axis X\";\r\n        case INPUT_MAP_ANALOG_AXIS_Y:   return \"Axis Y\";\r\n        case INPUT_MAP_BUTTON1:         return \"Button 1\";\r\n        case INPUT_MAP_BUTTON2:         return \"Button 2\";\r\n        case INPUT_MAP_PAUSE_START:     return \"Pause/Start\";\r\n        case INPUT_MAP_RESET:           return \"Reset\";\r\n        }\r\n        break;\r\n    }\r\n    return NULL;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/inputs.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs.h\n// User Inputs & Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\nenum t_mouse_cursor\n{\n    MEKA_MOUSE_CURSOR_NONE,\n    MEKA_MOUSE_CURSOR_STANDARD,\n    MEKA_MOUSE_CURSOR_LIGHT_PHASER,\n    MEKA_MOUSE_CURSOR_SPORTS_PAD,\n    MEKA_MOUSE_CURSOR_TV_OEKAKI,\n    MEKA_MOUSE_CURSOR_WAIT,\n};\n\n// Note: casted to s8 in DB storage so make sure it fits.\n// Note: input configuration does a +1%max so we need consecutive integers.\nenum t_input_peripheral\n{\n    INPUT_JOYPAD            = 0,\n    INPUT_LIGHTPHASER       = 1,\n    INPUT_PADDLECONTROL     = 2,\n    INPUT_SPORTSPAD         = 3,\n    INPUT_GRAPHICBOARD      = 4,\n    INPUT_GRAPHICBOARD_V2   = 5,\n    INPUT_PERIPHERAL_MAX    = 6,\n};\n\n// Input Connection Possibilities ---------------------------------------------\n//\n//   Keyboard --> Joypad\n//            --> Paddle Control (?)    TODO\n//   Joypad   --> Joypad\n//            --> Paddle Control (?)    TODO\n//   Mouse    --> Light Phaser\n//            --> Paddle Control\n//            --> Sports Pad\n//            --> TV Oekaki\n//            --> Joypad (?)            TODO\n//\n//-----------------------------------------------------------------------------\n\n// Input Sources Types\nenum t_input_src_type\n{\n    INPUT_SRC_TYPE_KEYBOARD = 0,\n    INPUT_SRC_TYPE_JOYPAD   = 1,    // Digital only (yet)\n    INPUT_SRC_TYPE_MOUSE    = 2,\n};\n\n// Input Sources Flags\nenum t_input_src_flags\n{\n    INPUT_SRC_FLAGS_DIGITAL         = 0x0001,\n    INPUT_SRC_FLAGS_EMULATE_DIGITAL = 0x0002,\n    INPUT_SRC_FLAGS_ANALOG          = 0x0004,\n    INPUT_SRC_FLAGS_EMULATE_ANALOG  = 0x0008,\n};\n\n// Players Definitions\n#define  PLAYER_NO      (-1)\n#define  PLAYER_1       (0)\n#define  PLAYER_2       (1)\n#define  PLAYER_MAX     (2)\n\n// Input Mapping Types\nenum t_input_map_type\n{\n    INPUT_MAP_TYPE_KEY = 0,\n    INPUT_MAP_TYPE_JOY_BUTTON = 1,\n    INPUT_MAP_TYPE_JOY_AXIS = 2,\n    INPUT_MAP_TYPE_MOUSE_BUTTON = 3,\n    INPUT_MAP_TYPE_MOUSE_AXIS = 4,\n};\n\n#define INPUT_JOY_DEADZONE      (0.2f)          // -0.2f to 0.2f is neutral\n\nstruct t_input_peripheral_info\n{\n    const char* name;\n};\nextern  const t_input_peripheral_info Inputs_Peripheral_Infos [INPUT_PERIPHERAL_MAX];\n\n//-----------------------------------------------------------------------------\n\n// Input Mapping Indexes ------------------------------------------------------\n// Digital Devices (Keyboard/Joystick)\n#define  INPUT_MAP_DIGITAL_UP           (0)\n#define  INPUT_MAP_DIGITAL_DOWN         (1)\n#define  INPUT_MAP_DIGITAL_LEFT         (2)\n#define  INPUT_MAP_DIGITAL_RIGHT        (3)\n// Analog Devices (Mouse)\n#define  INPUT_MAP_ANALOG_AXIS_X        (0)\n#define  INPUT_MAP_ANALOG_AXIS_Y        (1)\n#define  INPUT_MAP_ANALOG_AXIS_X_REL    (2)\n#define  INPUT_MAP_ANALOG_AXIS_Y_REL    (3)\n// Various\n#define  INPUT_MAP_BUTTON1              (4)\n#define  INPUT_MAP_BUTTON2              (5)\n#define  INPUT_MAP_PAUSE_START          (6)\n#define  INPUT_MAP_RESET                (7)\n// Max\n#define  INPUT_MAP_MAX                  (8)\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_key_press\n{\n    int     scancode;\n    int     ascii;\n};\n\nstruct t_input_map_entry\n{\n    t_input_map_type    type;                       // Axis, Button, Wheel, etc..\n    int                 hw_index;                   // Index of button/stick\n    int                 hw_axis;\n    int                 hw_direction;\n    int                 current_value;              // Result, For buttons: 1 if pressed, for axis: contains value\n    int                 pressed_counter;\n};\n\nstruct t_input_src\n{\n    char *              name;\n    int                 flags;                      // enum t_input_src_flags // FIXME-ENUM\n    t_input_src_type    type;\n    bool                enabled;\n    int                 player;                     // PLAYER_1 or PLAYER_2\n\n    int                 Connection_Port;            // Joypad Number, COM Port, etc.. (device & machine dependant)\n    float               Analog_to_Digital_FallOff;  // Default: 0.8f\n    bool                Connected_and_Ready;        // No/Yes\n    t_input_map_entry   Map[INPUT_MAP_MAX];\n};\n\nstruct t_peripheral_graphic_board_v2\n{\n    u8 unknown;       // 0xFD-0xFF\n    u8 buttons;       // 3-bit\n    u8 x, y;\n    u8 read_index;\n};\n\nstruct t_peripheral_paddle\n{\n    // FIXME\n    u8 x;\n};\n\nstruct t_peripheral_sportspad\n{\n    // FIXME\n    u8 x, y;\n    u8 latch;\n};\n\nstruct t_inputs\n{\n    char            FileName[FILENAME_LEN];        // Path to the MEKA.INP file\n    t_mouse_cursor  mouse_cursor;\n    // Emulation\n    t_input_peripheral  Peripheral[PLAYER_MAX];        // 2 inputs ports on emulated machines\n    t_input_src **  Sources;\n    int             Sources_Max;\n    int             SK1100_Enabled;                 // Boolean. Set when SK-1100 enabled.\n\n    // Machine-side peripheral data\n    t_peripheral_paddle             Paddle[PLAYER_MAX];\n    t_peripheral_sportspad          SportsPad[PLAYER_MAX];\n    t_peripheral_graphic_board_v2   GraphicBoardV2[PLAYER_MAX];\n\n    // Keyboard\n    t_list *        KeyPressedQueue;                // Queued keypresses\n\n    // GUI\n    bool            Cabinet_Mode;                   // Boolean. Invert ESC and F10 (this is until inputs keys are fully configurable)\n};\n\nextern t_inputs Inputs;\n\nconst char *    Inputs_Get_MapName(int Type, int MapIdx);\nvoid            Inputs_Peripheral_Next(int Player);\nint             Inputs_Peripheral_Result_Type(int Periph);\nvoid            Inputs_Peripheral_Change_Update();\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Input_ROM_Change();\n\nvoid    Inputs_SetMouseCursor(t_mouse_cursor mouse_cursor);\n\nvoid    Inputs_Check_GUI(bool sk1100_pressed);\n\nvoid    Inputs_Switch_Current();\nvoid    Inputs_Switch_Joypad();\nvoid    Inputs_Switch_LightPhaser();\nvoid    Inputs_Switch_PaddleControl();\nvoid    Inputs_Switch_SportsPad();\nvoid    Inputs_Switch_GraphicBoard();\nvoid    Inputs_Switch_GraphicBoardV2();\n\nu8      Input_Port_DC();\nu8      Input_Port_DD();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/inputs_c.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - inputs_c.c\r\n// Inputs Configuration Applet - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"desktop.h\"\r\n#include \"g_tools.h\"\r\n#include \"g_widget.h\"\r\n#include \"keyinfo.h\"\r\n#include \"inputs_c.h\"\r\n#include \"inputs_t.h\"\r\n#include \"glasses.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_app_inputs_config     Inputs_CFG;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declarations\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void Inputs_CFG_Layout(t_app_inputs_config *app, bool setup);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define INPUTS_CFG_CHECK_X      (9)\r\n#define INPUTS_CFG_CHECK_Y      (9)\r\n\r\n// FIXME: pure crap layouting\r\n// FIXME: Actually, values below are not size of the whole inputs configuration applet\r\n#define INPUTS_CFG_FRAME_X      (150)\r\n#define INPUTS_CFG_FRAME_Y      ((GUI_LOOK_FRAME_PAD1_Y + GUI_LOOK_FRAME_PAD2_Y * 2)                     \\\r\n                                 + ((INPUT_MAP_MAX + 3) * (Font_Height(FONTID_SMALL) + GUI_LOOK_LINES_SPACING_Y)) \\\r\n                                 - GUI_LOOK_LINES_SPACING_Y)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Inputs_CFG_Switch()\r\n{\r\n    Inputs_CFG.active ^= 1;\r\n    gui_box_show (Inputs_CFG.box, Inputs_CFG.active, TRUE);\r\n    gui_menu_toggle_check (menus_ID.inputs, 10);\r\n}\r\n\r\nvoid    Inputs_CFG_Init_Applet()\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG; // Global instance\r\n    t_frame frame;\r\n\r\n    // Setup members\r\n    app->active = FALSE;\r\n    app->Current_Map = -1;\r\n    app->Current_Source = 0;\r\n\r\n    frame.pos.x     = 676;\r\n    frame.pos.y     = 584;\r\n    frame.size.x    = 165 + (INPUTS_CFG_FRAME_X + GUI_LOOK_FRAME_SPACING_X);\r\n    frame.size.y    = 150;\r\n    app->box = gui_box_new(&frame, Msg_Get(MSG_Inputs_Config_BoxTitle));\r\n    Desktop_Register_Box (\"INPUTS\", app->box, 1, &app->active);\r\n\r\n    // Layout\r\n    Inputs_CFG_Layout(app, TRUE);\r\n}\r\n\r\nstatic void Inputs_CFG_Layout(t_app_inputs_config *app, bool setup)\r\n{\r\n    t_frame frame;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (setup)\r\n    {\r\n        // Add closebox widget\r\n        widget_closebox_add(app->box, (t_widget_callback)Inputs_CFG_Switch);\r\n\r\n        // Peripheral change button\r\n        frame.pos.x = 10;\r\n        frame.pos.y = 18;\r\n        frame.size.x = al_get_bitmap_width(Graphics.Inputs.InputsBase);\r\n        frame.size.y = 80-2;\r\n        widget_button_add(app->box, &frame, 1, (t_widget_callback)Inputs_CFG_Peripheral_Change_Handler, FONTID_NONE, NULL);\r\n\r\n        // Input source change button\r\n        frame.pos.x = 170;\r\n        frame.pos.y = 10-Font_Height(FONTID_MEDIUM)/2;\r\n        frame.size.x = INPUTS_CFG_FRAME_X - 5;\r\n        frame.size.y = Font_Height(FONTID_MEDIUM);\r\n        widget_button_add(app->box, &frame, 1|2, (t_widget_callback)Inputs_CFG_Current_Source_Change, FONTID_NONE, NULL);\r\n\r\n        // Input map change button\r\n        frame.pos.x = 170 /* + (INPUTS_CFG_FRAME_X / 2)*/;\r\n        frame.pos.y = 48;\r\n        frame.size.x = (INPUTS_CFG_FRAME_X /* / 2 */) - 10;\r\n        frame.size.y = INPUT_MAP_MAX * (Font_Height(FONTID_SMALL) + GUI_LOOK_LINES_SPACING_Y);\r\n        widget_button_add(app->box, &frame, 1, (t_widget_callback)Inputs_CFG_Map_Change_Handler, FONTID_NONE, NULL);\r\n\r\n        // 'Enabled' checkbox\r\n        frame.pos.x = 170;\r\n        frame.pos.y = 19;\r\n        frame.size.x = INPUTS_CFG_CHECK_X;\r\n        frame.size.y = INPUTS_CFG_CHECK_Y;\r\n        app->CheckBox_Enabled = widget_checkbox_add(app->box, &frame, &Inputs.Sources [app->Current_Source]->enabled, NULL);\r\n\r\n        // Emulate Digital check need to be added before drawing source\r\n        // because currently it is drawn on the box before having the chance\r\n        // to be disabled... so anyway drawing source will clear it.\r\n        frame.pos.x = 170;\r\n        frame.pos.y = 19 + (7 * 2) + (2 + 6) * (Font_Height(FONTID_SMALL) + GUI_LOOK_LINES_SPACING_Y);\r\n        frame.size.x = INPUTS_CFG_CHECK_X;\r\n        frame.size.y = INPUTS_CFG_CHECK_Y;\r\n        app->CheckBox_Emulate_Digital = widget_checkbox_add(app->box, &frame, &app->CheckBox_Emulate_Digital_Value, (t_widget_callback)Inputs_CFG_Emulate_Digital_Handler);\r\n        widget_set_enabled(app->CheckBox_Emulate_Digital, false);\r\n    }\r\n\r\n    // Draw input base\r\n    al_draw_bitmap(Graphics.Inputs.InputsBase, 10, 34, 0x0000);\r\n\r\n    // Draw current peripheral\r\n    Inputs_CFG_Peripherals_Draw();\r\n\r\n    // Draw current input source\r\n    Inputs_CFG_Current_Source_Draw();\r\n}\r\n\r\nbyte        Inputs_CFG_Current_Source_Draw_Map(int i, ALLEGRO_COLOR Color)\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG; // Global instance\r\n\r\n    t_input_src* input_src = Inputs.Sources [Inputs_CFG.Current_Source];\r\n    t_input_map_entry* map = &input_src->Map[i];\r\n\r\n    const char* map_name = Inputs_Get_MapName(input_src->type, i);\r\n    if (map_name == NULL)\r\n        return FALSE;\r\n\r\n    // Set default font\r\n    Font_SetCurrent(FONTID_SMALL);\r\n\r\n    // Shift Y position by 2 steps for analog devices\r\n    if (input_src->flags & INPUT_SRC_FLAGS_ANALOG && i > INPUT_MAP_ANALOG_AXIS_Y_REL)\r\n        i -= 2;\r\n    int x = 165;\r\n    int y = 10 + GUI_LOOK_FRAME_PAD1_Y + (2 + i) * (Font_Height(FONTID_CUR) + GUI_LOOK_LINES_SPACING_Y) + 7;\r\n\r\n    char map_value[128];\r\n    if (map->hw_index == -1)\r\n    {\r\n        sprintf(map_value, \"<Null>\");\r\n    }\r\n    else\r\n    {\r\n        switch (input_src->type)\r\n        {\r\n        case INPUT_SRC_TYPE_KEYBOARD:\r\n            {\r\n                const t_key_info *key_info = KeyInfo_FindByScancode(map->hw_index);\r\n                strcpy(map_value, key_info ? key_info->name : \"error\");\r\n                break;\r\n            }\r\n        case INPUT_SRC_TYPE_JOYPAD:\r\n            switch (map->type)\r\n            {\r\n            case INPUT_MAP_TYPE_JOY_AXIS:\r\n                sprintf(map_value, \"Stick %d, Axis %d, %c\", map->hw_index, map->hw_axis, map->hw_direction ? '+' : '-');\r\n                break;\r\n            case INPUT_MAP_TYPE_JOY_BUTTON:\r\n                sprintf(map_value, \"Button %d\", map->hw_index);\r\n                break;\r\n            }\r\n            break;\r\n        case INPUT_SRC_TYPE_MOUSE:\r\n            switch (map->type)\r\n            {\r\n            case INPUT_MAP_TYPE_MOUSE_AXIS:\r\n                sprintf(map_value, \"Axis %d (%c)\", map->hw_index, 'X' + map->hw_index);\r\n                break;\r\n            case INPUT_MAP_TYPE_MOUSE_BUTTON:\r\n                sprintf(map_value, \"Button %d\", map->hw_index+1);\r\n                break;\r\n            }\r\n            break;\r\n        }\r\n    }\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    Font_Print(FONTID_CUR, map_name, x + GUI_LOOK_FRAME_PAD_X, y, Color);\r\n    Font_Print(FONTID_CUR, map_value, x + (INPUTS_CFG_FRAME_X / 2), y, Color);\r\n    // y += Font_Height() + GUI_LOOK_LINES_SPACING_Y;\r\n\r\n    return TRUE;\r\n}\r\n\r\nvoid    Inputs_CFG_Current_Source_Draw()\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG; // Global instance\r\n    ALLEGRO_BITMAP *bmp = app->box->gfx_buffer;\r\n\r\n    int             x = 165;\r\n    int             y = 10;\r\n    int             font_height;\r\n    int             frame_x = INPUTS_CFG_FRAME_X;\r\n    int             frame_y = INPUTS_CFG_FRAME_Y;\r\n    t_input_src *   input_src = Inputs.Sources [Inputs_CFG.Current_Source];\r\n\r\n    // x = 165 + (i / 2) * (frame_sx + GUI_LOOK_FRAME_SPACING_X);\r\n    // y = 10 + (i % 2) * (frame_sy + GUI_LOOK_FRAME_SPACING_Y);\r\n\r\n    // Set font to use\r\n    Font_SetCurrent(FONTID_MEDIUM);\r\n    font_height = Font_Height();\r\n\r\n    // Clear area to display on\r\n    al_set_target_bitmap(bmp);\r\n    al_draw_filled_rectangle(x, y - font_height / 2,\r\n        x + frame_x + 1, y - font_height / 2 + frame_y + 1,\r\n        COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    // Do the actual display\r\n    {\r\n        char buf[128];\r\n        sprintf(buf, \"%d/%d: %s >>\", app->Current_Source+1, Inputs.Sources_Max, input_src->name);\r\n        gui_rect_titled(buf, FONTID_MEDIUM, LOOK_THIN,\r\n            x, y, x + frame_x, y + frame_y,\r\n            COLOR_SKIN_WIDGET_GENERIC_BORDER, COLOR_SKIN_WINDOW_BACKGROUND, /*COLOR_SKIN_WINDOW_TEXT*/COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT);\r\n    }\r\n\r\n    // Set font to use\r\n    Font_SetCurrent (FONTID_SMALL);\r\n    font_height = Font_Height();\r\n    y += GUI_LOOK_FRAME_PAD1_Y;\r\n\r\n    // Enable Check\r\n    Font_Print(FONTID_CUR, Msg_Get(MSG_Inputs_Config_Source_Enabled), x + GUI_LOOK_FRAME_PAD_X + INPUTS_CFG_CHECK_X + 3, y, COLOR_SKIN_WINDOW_TEXT);\r\n    y += font_height + GUI_LOOK_LINES_SPACING_Y;\r\n\r\n    // Player\r\n    char buf[64];\r\n    snprintf(buf, sizeof(buf), Msg_Get(MSG_Inputs_Config_Source_Player), input_src->player + 1);\r\n    Font_Print(FONTID_CUR, buf, x + GUI_LOOK_FRAME_PAD_X + INPUTS_CFG_CHECK_X + 3, y, COLOR_SKIN_WINDOW_TEXT);\r\n    y += font_height + GUI_LOOK_LINES_SPACING_Y;\r\n\r\n    // Horizontal Separator\r\n    al_draw_line(x + 4, y + 3 + 0.5f, x + frame_x - 4 + 1, y + 3 + 0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n    y += 7;\r\n\r\n    // Mapping\r\n    for (int i = 0; i < INPUT_MAP_MAX; i++)\r\n        if (Inputs_CFG_Current_Source_Draw_Map(i, COLOR_SKIN_WINDOW_TEXT))\r\n            y += font_height + GUI_LOOK_LINES_SPACING_Y;\r\n\r\n    // Quit now if it is not an analog device..\r\n    if (!(input_src->flags & INPUT_SRC_FLAGS_ANALOG))\r\n        return;\r\n\r\n    // Horizontal Separator\r\n    al_draw_line(x + 4, y + 3 + 0.5f, x + frame_x - 4, y + 3 + 0.5f, COLOR_SKIN_WINDOW_SEPARATORS, 0);\r\n    y += 7;\r\n\r\n    // Emulate Digital\r\n    widget_checkbox_redraw (app->CheckBox_Emulate_Digital);\r\n    Font_Print(FONTID_CUR, Msg_Get(MSG_Inputs_Config_Source_Emulate_Joypad), x + GUI_LOOK_FRAME_PAD_X + INPUTS_CFG_CHECK_X + 3, y, COLOR_SKIN_WINDOW_TEXT);\r\n    y += font_height + GUI_LOOK_LINES_SPACING_Y;\r\n}\r\n\r\nvoid    Inputs_CFG_Current_Source_Change (t_widget *w)\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG;   // Global instance\r\n\r\n    if (w->mouse_buttons_activation & 1)\r\n    {\r\n        app->Current_Source++;\r\n        if (app->Current_Source == Inputs.Sources_Max)\r\n            app->Current_Source = 0;\r\n    }\r\n    else if (w->mouse_buttons_activation & 2)\r\n    {\r\n        if (app->Current_Source == 0)\r\n            app->Current_Source = Inputs.Sources_Max;\r\n        app->Current_Source--;\r\n    }\r\n\r\n    Inputs_CFG_Current_Source_Draw();\r\n    widget_checkbox_set_pvalue (app->CheckBox_Enabled, &Inputs.Sources [app->Current_Source]->enabled);\r\n    widget_checkbox_redraw (app->CheckBox_Enabled);\r\n    if (app->Current_Map != -1)\r\n        Inputs_CFG_Map_Change_End(); // a bit crap...\r\n\r\n    {\r\n        t_input_src *input_src = Inputs.Sources [app->Current_Source];\r\n        if (input_src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n        {\r\n            app->CheckBox_Emulate_Digital_Value = (input_src->flags & INPUT_SRC_FLAGS_EMULATE_DIGITAL) ? TRUE : FALSE;\r\n            widget_set_enabled(app->CheckBox_Emulate_Digital, true);\r\n            widget_checkbox_redraw(app->CheckBox_Emulate_Digital);\r\n        }\r\n        else\r\n        {\r\n            widget_set_enabled(app->CheckBox_Emulate_Digital, false);\r\n        }\r\n    }\r\n}\r\n\r\nvoid        Inputs_CFG_Peripherals_Draw()\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG; // Global instance\r\n    ALLEGRO_BITMAP *bmp = app->box->gfx_buffer;\r\n\r\n    ALLEGRO_BITMAP *sprite = NULL;\r\n\r\n    // Set font to use\r\n    Font_SetCurrent (FONTID_SMALL);\r\n\r\n    // Clear area to display on\r\n    al_set_target_bitmap(bmp);\r\n    al_draw_filled_rectangle(10, 20, 10 + al_get_bitmap_width(Graphics.Inputs.InputsBase) + 1, 20 + Font_Height() + 1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n    al_draw_filled_rectangle(10, 58, 10 + al_get_bitmap_width(Graphics.Inputs.InputsBase) + 1, 121 + 1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    // Print 'click to select peripheral' message\r\n    Font_PrintCentered(FONTID_CUR, Msg_Get(MSG_Inputs_Config_Peripheral_Click),\r\n        10 + 11 + (64 / 2) + (58 / 2),\r\n        4, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n    // Do the actual display\r\n    for (int i = 0; i < PLAYER_MAX; i++)\r\n    {\r\n        // Print name\r\n        const char *name = Inputs_Peripheral_Infos[Inputs.Peripheral[i]].name;\r\n        Font_PrintCentered(FONTID_CUR, name,\r\n            10 + 11 + (i ? 64 : 0) + (58 / 2), // X\r\n            20, // Y\r\n            COLOR_SKIN_WINDOW_TEXT);\r\n\r\n        // Draw peripheral sprite\r\n        switch (Inputs.Peripheral[i])\r\n        {\r\n            case INPUT_JOYPAD:          sprite = Graphics.Inputs.Joypad;          break;\r\n            case INPUT_LIGHTPHASER:     sprite = Graphics.Inputs.LightPhaser;     break;\r\n            case INPUT_PADDLECONTROL:   sprite = Graphics.Inputs.PaddleControl;   break;\r\n            case INPUT_SPORTSPAD:       sprite = Graphics.Inputs.SportsPad;       break;\r\n            case INPUT_GRAPHICBOARD:    sprite = Graphics.Inputs.TvOekaki;        break;\r\n            case INPUT_GRAPHICBOARD_V2: sprite = Graphics.Inputs.GraphicBoardV2;  break;\r\n        }\r\n        if (sprite != NULL)\r\n        {\r\n            al_draw_bitmap(sprite,\r\n                10 + 11 + (i ? 64 : 0) + (58 - al_get_bitmap_width(sprite)) / 2, // X\r\n                58, 0x0000);\r\n        }\r\n    }\r\n\r\n    // 3-D Glasses\r\n    // Draw below player 2 peripheral\r\n    if (Glasses.Enabled)\r\n    {\r\n        ALLEGRO_BITMAP *b = Graphics.Inputs.Glasses;\r\n        const int x = 10 + 11 + 64 + (58 - al_get_bitmap_width(b)) / 2;\r\n        const int y = 58 + al_get_bitmap_height(sprite) + 5;\r\n        // rectfill (bmp, x, y, x + b->w, y + b->h, COLOR_SKIN_WINDOW_BACKGROUND);\r\n        al_draw_bitmap(b, x, y, 0x0000);\r\n    }\r\n}\r\n\r\nvoid    Inputs_CFG_Peripheral_Change_Handler (t_widget *w)\r\n{\r\n    const int player = (w->mouse_x <= w->frame.size.x / 2) ? 0 : 1; // 0 or 1 depending on the side the widget was clicked on\r\n    Inputs_Peripheral_Next (player);\r\n}\r\n\r\nvoid    Inputs_CFG_Peripheral_Change (int Player, t_input_peripheral Periph)\r\n{\r\n    Inputs.Peripheral [Player] = Periph;\r\n    Inputs_CFG_Peripherals_Draw();\r\n    Inputs_Peripheral_Change_Update();\r\n}\r\n\r\nvoid    Inputs_CFG_Map_Change_Handler (t_widget *w)\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG; // Global instance\r\n\r\n    int            MapIdx = (w->mouse_y * 8) / w->frame.size.y;\r\n    t_input_src *  input_src = Inputs.Sources [app->Current_Source];\r\n\r\n    if (app->Current_Map != -1)\r\n        return;\r\n\r\n    // Note: eating mouse press FIXME\r\n    gui.mouse.buttons_prev = gui.mouse.buttons;\r\n\r\n    if (input_src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n    {\r\n        if (MapIdx >= 6)\r\n            return;\r\n        if (MapIdx >= 2)\r\n            MapIdx += 2; // Add two because X_REL/Y_REL are not shown\r\n    }\r\n\r\n    switch (input_src->type)\r\n    {\r\n    case INPUT_SRC_TYPE_KEYBOARD:\r\n        Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_Inputs_Src_Map_Keyboard));\r\n        break;\r\n    case INPUT_SRC_TYPE_JOYPAD:\r\n        Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_Inputs_Src_Map_Joypad));\r\n        break;\r\n    case INPUT_SRC_TYPE_MOUSE:\r\n        if (MapIdx < 4)\r\n        {\r\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_Src_Map_Mouse_No_A));\r\n            return;\r\n        }\r\n        Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_Inputs_Src_Map_Mouse));\r\n        break;\r\n    default:\r\n        Msg(MSGT_USER, \"Error #24813R\");\r\n        return;\r\n    }\r\n\r\n    // Change cursor to the '...' one\r\n    Inputs_SetMouseCursor(MEKA_MOUSE_CURSOR_WAIT);\r\n\r\n    // Be sure nothing is kept highlighted\r\n    if (app->Current_Map != -1)\r\n        Inputs_CFG_Current_Source_Draw_Map (app->Current_Map, COLOR_SKIN_WINDOW_TEXT);\r\n\r\n    // Set current map, for the updater\r\n    app->Current_Map = MapIdx;\r\n    Inputs_CFG_Current_Source_Draw_Map (MapIdx, COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT);\r\n}\r\n\r\nvoid    Inputs_CFG_Update(t_app_inputs_config *app)\r\n{\r\n    // Skip update if not active\r\n    if (!Inputs_CFG.active)\r\n        return;\r\n\r\n    // If skin has changed, redraw everything\r\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\r\n    {\r\n        Inputs_CFG_Layout(app, FALSE);\r\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\r\n        app->dirty = TRUE;\r\n    }\r\n\r\n    // Update input map change (if any occuring)\r\n    Inputs_CFG_Map_Change_Update();\r\n\r\n    // Skip redraw if not dirty\r\n    if (!app->dirty)\r\n        return;\r\n\r\n    // Redraw\r\n    app->dirty = FALSE;\r\n}\r\n\r\nvoid    Inputs_CFG_Map_Change_Update()\r\n{\r\n    t_app_inputs_config *app = &Inputs_CFG; // Global instance\r\n\r\n    if (Inputs_CFG.Current_Map == -1)\r\n        return;\r\n\r\n    bool found = FALSE;\r\n    t_input_src* input_src = Inputs.Sources[Inputs_CFG.Current_Source];\r\n    t_input_map_entry* map = &input_src->Map[Inputs_CFG.Current_Map];\r\n\r\n    // Pressing ESC cancel map change\r\n    // Eat the keypress to avoid it having side effect of switching to fullscreen mode\r\n    if (Inputs_KeyPressed(ALLEGRO_KEY_ESCAPE, true))\r\n    {\r\n        found = TRUE;\r\n        map->hw_index = -1;\r\n        Msg(MSGT_STATUS_BAR, \"%s\", Msg_Get(MSG_Inputs_Src_Map_Cancelled));\r\n        Inputs_CFG_Map_Change_End();\r\n        return;\r\n    }\r\n\r\n    // Check if a key/button/axis can be used as the mapping\r\n    switch (input_src->type)\r\n    {\r\n        // Keyboard ----------------------------------------------------------------\r\n    case INPUT_SRC_TYPE_KEYBOARD:\r\n        {\r\n            for (int i = 0; i < ALLEGRO_KEY_MAX; i++)\r\n            {\r\n                // Eat keypresses to avoid them having a side effect with the GUI or game\r\n                if (Inputs_KeyPressed(i, true))\r\n                {\r\n                    const t_key_info *key_info = KeyInfo_FindByScancode(i);\r\n                    if (key_info)\r\n                    {\r\n                        map->hw_index = i;\r\n                        map->type = INPUT_MAP_TYPE_KEY;\r\n                        found = TRUE;\r\n                        Msg(MSGT_STATUS_BAR, Msg_Get(MSG_Inputs_Src_Map_Keyboard_Ok), key_info->name);\r\n                    }\r\n                    else\r\n                    {\r\n                        Msg(MSGT_DEBUG, \"KeyInfo_FindByScancode(%x) failed\", i);\r\n                    }\r\n                    break;\r\n                }\r\n            }\r\n            break;\r\n        }\r\n#ifdef MEKA_JOYPAD\r\n        // Digital Joypad/Joystick -------------------------------------------------\r\n    case INPUT_SRC_TYPE_JOYPAD:\r\n        {\r\n            ALLEGRO_JOYSTICK *joystick = al_get_joystick(input_src->Connection_Port);\r\n            if (!joystick)\r\n                break;\r\n\r\n            ALLEGRO_JOYSTICK_STATE state;\r\n            al_get_joystick_state(joystick, &state);\r\n\r\n            // Check buttons\r\n            const int num_buttons = al_get_joystick_num_buttons(joystick);\r\n            for (int i = 0; i < num_buttons; i++)\r\n            {\r\n                if (state.button[i])\r\n                {\r\n                    map->hw_index = i;\r\n                    map->type = INPUT_MAP_TYPE_JOY_BUTTON;\r\n                    found = TRUE;\r\n                    Msg(MSGT_STATUS_BAR, Msg_Get(MSG_Inputs_Src_Map_Joypad_Ok_B), i);\r\n                    break;\r\n                }\r\n            }\r\n            if (found)\r\n                break;\r\n\r\n            // Check axises\r\n            const int num_sticks = al_get_joystick_num_sticks(joystick);\r\n            for (int i = 0; i < num_sticks; i++)\r\n            {\r\n                const int num_axes = al_get_joystick_num_axes(joystick, i);\r\n                for (int j = 0; j < num_axes; j++)\r\n                {\r\n                    const float axis_pos = state.stick[i].axis[j];\r\n                    //Msg(MSGT_DEBUG, \"- axis %d - pos %f\", j, axis_pos);\r\n                    if (axis_pos > INPUT_JOY_DEADZONE || axis_pos < -INPUT_JOY_DEADZONE)\r\n                    {\r\n                        map->hw_index = i;\r\n                        map->hw_axis = j;\r\n                        map->hw_direction = (axis_pos > 0.0f ? 1 : 0);\r\n                        map->type = INPUT_MAP_TYPE_JOY_AXIS;\r\n                        found = TRUE;\r\n                        Msg(MSGT_STATUS_BAR, Msg_Get(MSG_Inputs_Src_Map_Joypad_Ok_A), i, j, (axis_pos > 0.0f ? '+' : '-'));\r\n                        break;\r\n                    }\r\n                }\r\n                if (found)\r\n                    break;\r\n            }\r\n            break;\r\n        }\r\n#endif // #ifdef MEKA_JOYPAD\r\n        // Mouse -------------------------------------------------------------------\r\n    case INPUT_SRC_TYPE_MOUSE:\r\n        {\r\n            // Buttons\r\n            if (Inputs_CFG.Current_Map >= INPUT_MAP_BUTTON1)\r\n            {\r\n                int n = -1;\r\n                if ((gui.mouse.buttons & 1) && !(gui.mouse.buttons_prev & 1))\r\n                    n = 0;\r\n                else if ((gui.mouse.buttons & 2) && !(gui.mouse.buttons_prev & 2))\r\n                    n = 1;\r\n                else if ((gui.mouse.buttons & 4) && !(gui.mouse.buttons_prev & 4))\r\n                    n = 2;\r\n                if (n != -1)\r\n                {\r\n                    t_input_map_entry* map = &input_src->Map[Inputs_CFG.Current_Map];\r\n                    map->hw_index = n;\r\n                    map->type = INPUT_MAP_TYPE_MOUSE_BUTTON;\r\n                    gui.mouse.buttons_prev = gui.mouse.buttons; // Note: eating mouse press FIXME\r\n                    found = true;\r\n                    Msg(MSGT_STATUS_BAR, Msg_Get(MSG_Inputs_Src_Map_Mouse_Ok_B), n+1);\r\n                    break;\r\n                }\r\n            }\r\n            // Axis\r\n            /*\r\n            if (Inputs_CFG.Current_Map <= INPUT_MAP_ANALOG_AXIS_Y)\r\n            {\r\n            static int save_mouse[3] = { -1, -1, -1 };\r\n            if (mouse_x != save_mouse[0] && save_mouse[0] != -1)\r\n            {\r\n            input_src->Map [Inputs_CFG.Current_Map].Idx = input_src->Map [Inputs_CFG.Current_Map + 2].Idx = MAKE_AXIS (0);\r\n            input_src->Map [Inputs_CFG.Current_Map].Type = input_src->Map [Inputs_CFG.Current_Map + 2].Type = INPUT_MAP_TYPE_MOUSE_AXIS;\r\n            save_mouse[0] = -1;\r\n            found = TRUE;\r\n            break;\r\n            }\r\n            if (mouse_y != save_mouse[1] && save_mouse[1] != -1)\r\n            {\r\n            input_src->Map [Inputs_CFG.Current_Map].Idx = input_src->Map [Inputs_CFG.Current_Map + 2].Idx = MAKE_AXIS (1);\r\n            input_src->Map [Inputs_CFG.Current_Map].Type = input_src->Map [Inputs_CFG.Current_Map + 2].Type = INPUT_MAP_TYPE_MOUSE_AXIS;\r\n            save_mouse[1] = -1;\r\n            found = TRUE;\r\n            break;\r\n            }\r\n            if (mouse_z != save_mouse[2] && save_mouse[2] != -1)\r\n            {\r\n            input_src->Map [Inputs_CFG.Current_Map].Idx = input_src->Map [Inputs_CFG.Current_Map + 2].Idx = MAKE_AXIS (2);\r\n            input_src->Map [Inputs_CFG.Current_Map].Type = input_src->Map [Inputs_CFG.Current_Map + 2].Type = INPUT_MAP_TYPE_MOUSE_AXIS;\r\n            save_mouse[2] = -1;\r\n            found = TRUE;\r\n            break;\r\n            }\r\n            save_mouse[0] = mouse_x;\r\n            save_mouse[1] = mouse_y;\r\n            save_mouse[2] = mouse_z;\r\n            }\r\n            */\r\n            break;\r\n        }\r\n    }\r\n\r\n    if (!found)\r\n        return;\r\n\r\n    Inputs_CFG_Map_Change_End();\r\n    app->dirty = TRUE;\r\n}\r\n\r\nvoid    Inputs_CFG_Map_Change_End()\r\n{\r\n    // Need to restore cursor.\r\n    // FIXME: the method sucks! need to sort those functions anyway.\r\n    Inputs_Peripheral_Change_Update();\r\n\r\n    // Refresh current source after changing mapping\r\n    Inputs_CFG_Current_Source_Draw();\r\n    widget_checkbox_set_pvalue (Inputs_CFG.CheckBox_Enabled, &Inputs.Sources [Inputs_CFG.Current_Source]->enabled);\r\n    //widget_checkbox_redraw (Inputs_CFG.CheckBox_Enabled);\r\n\r\n    // Set current map back to -1\r\n    Inputs_CFG.Current_Map = -1;\r\n}\r\n\r\nvoid    Inputs_CFG_Emulate_Digital_Handler(t_widget *w)\r\n{\r\n    t_input_src *input_src = Inputs.Sources [Inputs_CFG.Current_Source];\r\n    if (!(input_src->flags & INPUT_SRC_FLAGS_ANALOG))\r\n        return;\r\n\r\n    if (Inputs_CFG.CheckBox_Emulate_Digital_Value)\r\n        input_src->flags |= INPUT_SRC_FLAGS_EMULATE_DIGITAL;\r\n    else\r\n        input_src->flags &= ~INPUT_SRC_FLAGS_EMULATE_DIGITAL;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/inputs_c.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs_c.h\n// Inputs Configuration Applet - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_app_inputs_config\n{\n    t_gui_box * box;\n    bool        active;\n    bool        dirty;\n\n    int         Current_Source;\n    int         Current_Map;           // if != -1 then mapping is being changed\n    t_widget *  CheckBox_Enabled;\n    t_widget *  CheckBox_Emulate_Digital;\n    bool        CheckBox_Emulate_Digital_Value;\n};\n\nextern t_app_inputs_config     Inputs_CFG;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Inputs_CFG_Switch                       ();\nvoid    Inputs_CFG_Init_Applet                  ();\nvoid    Inputs_CFG_Update                       (t_app_inputs_config *app);\n\nvoid    Inputs_CFG_Current_Source_Draw          ();\nbyte    Inputs_CFG_Current_Source_Draw_Map      (int i, ALLEGRO_COLOR Color);\nvoid    Inputs_CFG_Current_Source_Change        (t_widget *w);\n\nvoid    Inputs_CFG_Peripherals_Draw             ();\n\nvoid    Inputs_CFG_Peripheral_Change            (int Player, t_input_peripheral Periph);\nvoid    Inputs_CFG_Peripheral_Change_Handler    (t_widget *w);\n\nvoid    Inputs_CFG_Map_Change_Handler           (t_widget *w);\nvoid    Inputs_CFG_Map_Change_Update            ();\nvoid    Inputs_CFG_Map_Change_End               ();\n\nvoid    Inputs_CFG_Emulate_Digital_Handler      (t_widget *w);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/inputs_f.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - inputs_f.c\r\n// Inputs File Load/Save - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"keyinfo.h\"\r\n#include \"libparse.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nFILE   *INP_File;\r\nINLINE  void INP_Write_Line     (const char *s)                   { fprintf(INP_File, \"%s\\n\", s); }\r\nINLINE  void INP_Write_Str      (const char *name, const char *s) { fprintf(INP_File, \"%s = %s\\n\", name, s); }\r\nINLINE  void INP_Write_Int      (const char *name, int value)     { fprintf(INP_File, \"%s = %d\\n\", name, value); }\r\nINLINE  void INP_Write_Float    (const char *name, float value)   { fprintf(INP_File, \"%s = %.2f\\n\", name, value); }\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic const char *Inputs_Src_List_KeyWords [] =\r\n{\r\n    \"type\", \"enabled\", \"player\",\r\n    \"driver\", \"connection\",\r\n    \"emulate_digital\", \"emulate_analog\", \"digital_falloff\",\r\n    \"player_up\", \"player_down\", \"player_left\", \"player_right\",\r\n    \"player_button1\", \"player_button2\", \"player_start_pause\", \"player_reset\",\r\n    \"player_x_axis\", \"player_y_axis\",\r\n    \"mouse_speed_x\", // OBSOLETE\r\n    \"mouse_speed_y\", // OBSOLETE\r\n    \"cabinet_mode\",  // particular case\r\n    NULL\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic int  Load_Inputs_Src_Parse_Var (int var_idx, char *s, t_input_src *input_src)\r\n{\r\n    char w[256];\r\n    if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n        return MEKA_ERR_EMPTY;\r\n\r\n    switch (var_idx)\r\n    {\r\n    case  0: // type -----------------------------------------------------------\r\n        if (!strcmp(w, \"keyboard\"))\r\n        {\r\n            input_src->type = INPUT_SRC_TYPE_KEYBOARD;\r\n            input_src->flags = INPUT_SRC_FLAGS_DIGITAL;\r\n            input_src->Connected_and_Ready = TRUE;\r\n            return MEKA_ERR_OK;\r\n        }\r\n        if (!strcmp(w, \"joypad\"))\r\n        {\r\n            input_src->type = INPUT_SRC_TYPE_JOYPAD;\r\n            input_src->flags = INPUT_SRC_FLAGS_DIGITAL;\r\n            input_src->Connected_and_Ready = FALSE;\r\n            return MEKA_ERR_OK;\r\n        }\r\n        if (!strcmp(w, \"mouse\"))\r\n        {\r\n            input_src->type = INPUT_SRC_TYPE_MOUSE;\r\n            input_src->flags = INPUT_SRC_FLAGS_ANALOG;\r\n            input_src->Connected_and_Ready = (g_env.mouse_installed ? TRUE : FALSE);\r\n            return MEKA_ERR_OK;\r\n        }\r\n        return MEKA_ERR_SYNTAX;\r\n\r\n    case  1: // enabled --------------------------------------------------------\r\n        if (!strcmp(w, \"yes\"))      { input_src->enabled = TRUE; return MEKA_ERR_OK; }\r\n        if (!strcmp(w, \"no\"))       { input_src->enabled = FALSE; return MEKA_ERR_OK; }\r\n        return MEKA_ERR_SYNTAX;\r\n\r\n    case  2: // player ---------------------------------------------------------\r\n        input_src->player = atoi(w) - 1;\r\n        if (input_src->player != 0 && input_src->player != 1)\r\n            return MEKA_ERR_SYNTAX;\r\n        return MEKA_ERR_OK;\r\n\r\n    case  3: // driver ---------------------------------------------------------\r\n\t\t// FIXME-OBSOLETE\r\n        return MEKA_ERR_OK;\r\n\r\n    case  4: // connection -----------------------------------------------------\r\n        input_src->Connection_Port = atoi(w);\r\n        if (input_src->Connection_Port > 0) input_src->Connection_Port -= 1;\r\n        return MEKA_ERR_OK;\r\n\r\n    case  5: // emulate_digital ------------------------------------------------\r\n        if (!strcmp(w, \"yes\"))      { input_src->flags |= INPUT_SRC_FLAGS_EMULATE_DIGITAL; return MEKA_ERR_OK; }\r\n        if (!strcmp(w, \"no\"))       { input_src->flags &= ~INPUT_SRC_FLAGS_EMULATE_DIGITAL; return MEKA_ERR_OK; }\r\n        return MEKA_ERR_SYNTAX;\r\n\r\n    case  6: // emulate_analog -------------------------------------------------\r\n        if (!strcmp(w, \"yes\"))      { input_src->flags |= INPUT_SRC_FLAGS_EMULATE_ANALOG; return MEKA_ERR_OK; }\r\n        if (!strcmp(w, \"no\"))       { input_src->flags &= ~INPUT_SRC_FLAGS_EMULATE_ANALOG; return MEKA_ERR_OK; }\r\n        return MEKA_ERR_SYNTAX;\r\n\r\n    case  7: // digital_falloff ------------------------------------------------\r\n        input_src->Analog_to_Digital_FallOff = atof (w);\r\n        return MEKA_ERR_OK;\r\n\r\n    case  8: // player_up ------------------------------------------------------\r\n    case  9: // player_down ----------------------------------------------------\r\n    case 10: // player_left ----------------------------------------------------\r\n    case 11: // player_right ---------------------------------------------------\r\n    case 12: // player_button1 -------------------------------------------------\r\n    case 13: // player_button2 -------------------------------------------------\r\n    case 14: // player_start_pause ---------------------------------------------\r\n    case 15: // player_reset ---------------------------------------------------\r\n        {\r\n            const int map_idx = INPUT_MAP_DIGITAL_UP + var_idx - 8;\r\n\t\t\tt_input_map_entry* map = &input_src->Map[map_idx];\r\n\r\n            // FIXME: ???\r\n            //if (MapIdx >= INPUT_MAP_DIGITAL_UP && MapIdx <= INPUT_MAP_DOWN && !(input_src->Result_Type & DIGITAL))\r\n            //   return MEKA_ERR_INCOHERENT;\r\n\r\n            if (!strcmp(w, \"key\"))\r\n            {\r\n                const t_key_info *key_info;\r\n                if (input_src->type != INPUT_SRC_TYPE_KEYBOARD)\r\n                    return MEKA_ERR_INCOHERENT;\r\n                //if (!Parse_LineGet (&w, &s))\r\n                //  return MEKA_ERR_SYNTAX;\r\n                parse_skip_spaces(&s);\r\n                if (StrIsNull(s))\r\n                    return MEKA_ERR_SYNTAX;\r\n                key_info = KeyInfo_FindByName(s);\r\n                if (key_info != NULL)\r\n                {\r\n                    map->type = INPUT_MAP_TYPE_KEY;\r\n                    map->hw_index = key_info->scancode;\r\n                }\r\n                return MEKA_ERR_OK;\r\n            }\r\n\r\n            if (!strcmp(w, \"joy\"))\r\n            {\r\n                int stick, axis, dir;\r\n\r\n                if (input_src->type != INPUT_SRC_TYPE_JOYPAD)\r\n                    return MEKA_ERR_INCOHERENT;\r\n                if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE) || strcmp(w, \"stick\") || !parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n                    return MEKA_ERR_SYNTAX;\r\n                stick = atoi(w);\r\n                if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE) || strcmp(w, \"axis\") || !parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n                    return MEKA_ERR_SYNTAX;\r\n                axis = atoi(w);\r\n                if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE) || strcmp(w, \"dir\") || !parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n                    return MEKA_ERR_SYNTAX;\r\n                dir = atoi(w);\r\n                map->type = INPUT_MAP_TYPE_JOY_AXIS;\r\n                map->hw_index = stick;\r\n\t\t\t\tmap->hw_axis = axis;\r\n\t\t\t\tmap->hw_direction = dir;\r\n                return MEKA_ERR_OK;\r\n            }\r\n\r\n            if (!strcmp(w, \"joy_button\"))\r\n            {\r\n                if (input_src->type != INPUT_SRC_TYPE_JOYPAD)\r\n                    return MEKA_ERR_INCOHERENT;\r\n                if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n                    return MEKA_ERR_SYNTAX;\r\n                map->type = INPUT_MAP_TYPE_JOY_BUTTON;\r\n                map->hw_index = atoi(w);\r\n                return MEKA_ERR_OK;\r\n            }\r\n\r\n            if (!strcmp(w, \"mouse_button\"))\r\n            {\r\n                if (input_src->type != INPUT_SRC_TYPE_MOUSE)\r\n                    return MEKA_ERR_INCOHERENT;\r\n                if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n                    return MEKA_ERR_SYNTAX;\r\n                map->type = INPUT_MAP_TYPE_MOUSE_BUTTON;\r\n                map->hw_index = atoi(w);\r\n                return MEKA_ERR_OK;\r\n            }\r\n\r\n            return MEKA_ERR_SYNTAX;\r\n        }\r\n\r\n    case 16: // player_x_axis --------------------------------------------------\r\n    case 17: // player_y_axis --------------------------------------------------\r\n        {\r\n            const int map_idx = INPUT_MAP_ANALOG_AXIS_X + var_idx - 16;\r\n\t\t\tt_input_map_entry* map = &input_src->Map[map_idx];\r\n\r\n            if (!(input_src->flags & INPUT_SRC_FLAGS_ANALOG))\r\n                return MEKA_ERR_INCOHERENT;\r\n\r\n            if (!strcmp(w, \"mouse_axis\"))\r\n            {\r\n                if (input_src->type != INPUT_SRC_TYPE_MOUSE)\r\n                    return MEKA_ERR_INCOHERENT;\r\n                if (!parse_getword(w, sizeof(w), &s, \" \\t\", ';', PARSE_FLAGS_NONE))\r\n                    return MEKA_ERR_SYNTAX;\r\n                map->type = input_src->Map[map_idx + 2].type = INPUT_MAP_TYPE_MOUSE_AXIS;\r\n                map->hw_index = input_src->Map[map_idx + 2].hw_index = atoi(w);\r\n                return MEKA_ERR_OK;\r\n            }\r\n\r\n            return MEKA_ERR_SYNTAX;\r\n        }\r\n\r\n    case 18: // mouse_speed_x --------------------------------------------------\r\n    case 19: // mouse_speed_y --------------------------------------------------\r\n        return MEKA_ERR_OK;\r\n\r\n    case 20: // cabinet_mode ---------------------------------------------------\r\n        {\r\n            Inputs.Cabinet_Mode = atoi(w);\r\n            return MEKA_ERR_OK;\r\n        }\r\n    }\r\n\r\n    return MEKA_ERR_SYNTAX;\r\n}\r\n\r\nvoid            Load_Inputs_Src_List()\r\n{\r\n    t_input_src *   input_src = NULL;\r\n\r\n    // Open and read file\r\n    ConsolePrint(Msg_Get(MSG_Inputs_Src_Loading));\r\n    t_tfile* tf = tfile_read (Inputs.FileName);\r\n    if (tf == NULL)\r\n        Quit_Msg(\"%s\", meka_strerror());\r\n    ConsolePrint(\"\\n\");\r\n\r\n    // Parse each line\r\n    int line_cnt = 0;\r\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        char* line = (char*) lines->elem;\r\n        line_cnt += 1;\r\n\r\n        if (StrIsNull(line))\r\n            continue;\r\n\r\n        if (line[0] == '[' && line[strlen(line) - 1] == ']')\r\n        {\r\n            input_src = Inputs_Sources_Add(StrNDup(line + 1, strlen(line) - 2));\r\n            // ConsolePrintf (\"new source --> %s <--\\n\", CurSrc->Name);\r\n            continue;\r\n        }\r\n\r\n\t\tchar w[256];\r\n        StrLower(line);\r\n        if (!parse_getword(w, sizeof(w), &line, \"=\", ';', PARSE_FLAGS_NONE))\r\n            continue;\r\n\r\n        for (int i = 0; Inputs_Src_List_KeyWords[i]; i++)\r\n\t\t{\r\n            if (strcmp(w, Inputs_Src_List_KeyWords[i]) == 0)\r\n            {\r\n                // FIXME: this is ugly\r\n                if (input_src == NULL\r\n                    && strcmp(w, \"mouse_speed_x\") != 0\r\n                    && strcmp(w, \"mouse_speed_y\") != 0\r\n                    && strcmp(w, \"cabinet_mode\")  != 0)\r\n                {\r\n                    tfile_free(tf);\r\n                    Quit_Msg(Msg_Get(MSG_Inputs_Src_Missing), line_cnt);\r\n                }\r\n\r\n                parse_skip_spaces(&line);\r\n                if (!parse_getword(w, sizeof(w), &line, \"\", ';', PARSE_FLAGS_NONE))\r\n                {\r\n                    tfile_free(tf);\r\n                    Quit_Msg(Msg_Get(MSG_Inputs_Src_Equal), line_cnt);\r\n                }\r\n\r\n                switch (Load_Inputs_Src_Parse_Var(i, w, input_src))\r\n                {\r\n                case MEKA_ERR_SYNTAX:\r\n                    tfile_free(tf);\r\n                    Quit_Msg(Msg_Get(MSG_Inputs_Src_Syntax_Param), line_cnt);\r\n                case MEKA_ERR_INCOHERENT :\r\n                    tfile_free(tf);\r\n                    Quit_Msg(Msg_Get(MSG_Inputs_Src_Inconsistency), line_cnt);\r\n                    break;\r\n                    // FIXME: EMPTY is not handled there\r\n                }\r\n                break;\r\n            }\r\n            if (!Inputs_Src_List_KeyWords [i])\r\n            {\r\n                tfile_free(tf);\r\n                Quit_Msg(Msg_Get(MSG_Inputs_Src_Unrecognized), line_cnt, w);\r\n            }\r\n\t\t}\r\n    }\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n\r\n    // Verify that we have enough inputs sources\r\n    if (Inputs.Sources_Max == 0)\r\n        Quit_Msg(\"%s\", Msg_Get(MSG_Inputs_Src_Not_Enough));\r\n}\r\n\r\nvoid    Write_Inputs_Src_List()\r\n{\r\n\tif (!(INP_File = fopen(Inputs.FileName, \"wt\")))\r\n\t\treturn;\r\n\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"; \" MEKA_NAME \" \" MEKA_VERSION \" - Inputs Configuration\");\r\n\tINP_Write_Line (\"; This file is automatically updated and rewritten when quitting\");\r\n\tINP_Write_Line (\"; Feel free to edit this file manually if you feel the need to.\");\r\n\tINP_Write_Line (\"; However, any comment you may manually add will be deleted!\");\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"\");\r\n\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"; Links:\");\r\n\tINP_Write_Line (\"; Using a SMS/DB-9 controller on your computer:\");\r\n\tINP_Write_Line (\";  - Read the TECH.TXT file at first!\");\r\n\tINP_Write_Line (\";  - SmsCardPad\");\r\n\tINP_Write_Line (\";    http://www.smspower.org/smscartpad/\");\r\n\tINP_Write_Line (\";  - PPJoy joystick driver for Windows 2000/XP\");\r\n\tINP_Write_Line (\";    Download mirror: http://www.zophar.net/joy/ppjoy.html\");\r\n\tINP_Write_Line (\";    Obsolete official website: http://web.archive.org/web/20021018045524/http://www.geocities.com/deonvdw/\");\r\n\tINP_Write_Line (\";  - ArcadeWereld.nl usb controller board\");\r\n\tINP_Write_Line (\";    http://www.smspower.org/forums/15321-SMSDB9ControllerOnPcUsingUSB\");\r\n\tINP_Write_Line (\"; Schematics and drivers for various console controllers adapters:\");\r\n\tINP_Write_Line (\";  - Direct Pad Pro\");\r\n\tINP_Write_Line (\";    http://www.arcadecontrols.com/Mirrors/www.ziplabel.com/dpadpro/\");\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"\");\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"; Miscellaneous features:\");\r\n\tINP_Write_Line (\";\");\r\n\tINP_Write_Line (\"; Invert ESC (switch screens) and F10 (quit) keys. Arcade cabinet owners\");\r\n\tINP_Write_Line (\"; often have the ESC key mapped to a certain button they want to quit with.\");\r\n\tINP_Write_Int  (\"cabinet_mode        \", Inputs.Cabinet_Mode);\r\n\tINP_Write_Line (\";\");\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"\");\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"; Template for creating new input sources:\");\r\n\tINP_Write_Line (\";\");\r\n\tINP_Write_Line (\"; [Name]\");\r\n\tINP_Write_Line (\"; type = keyboard (digital) | joypad (digital) | mouse (analog)\");\r\n\tINP_Write_Line (\";   Select the type of input device\");\r\n\tINP_Write_Line (\"; enabled = yes | no\");\r\n\tINP_Write_Line (\";   Set to no in order to tell MEKA to ignore input from this device\");\r\n\tINP_Write_Line (\"; player = 1 | 2\");\r\n\tINP_Write_Line (\";   Player number\");\r\n\tINP_Write_Line (\"; connection = <number>\");\r\n\tINP_Write_Line (\";   Joypad only. Select connection to use: 1 = first pad, 2 = second pad..\");\r\n\tINP_Write_Line (\"; emulate_digital\");\r\n\tINP_Write_Line (\";   Mouse only. Enable support for digital devices (such as SMS joypad),\");\r\n\tINP_Write_Line (\";   to play games with the mouse. Recommended with shooters mainly.\");\r\n\tINP_Write_Line (\"; digital_falloff (between 0 and 1, default being 0.8)\");\r\n\tINP_Write_Line (\";   Mouse only, when digital emulation is enabled. Reduce to increase\");\r\n\tINP_Write_Line (\";   precision, but most games will be harder to play.\");\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tINP_Write_Line (\"\");\r\n\r\n\tfor (int i = 0; i < Inputs.Sources_Max; i++)\r\n\t{\r\n\t\tchar s [256], s2 [256];\r\n\t\tt_input_src *input_src = Inputs.Sources[i];\r\n\t\tsprintf(s, \"[%s]\", input_src->name);\r\n\t\tINP_Write_Line(s);\r\n\r\n\t\tswitch (input_src->type)\r\n\t\t{\r\n\t\tcase INPUT_SRC_TYPE_KEYBOARD: sprintf(s, \"keyboard\");  break;\r\n\t\tcase INPUT_SRC_TYPE_JOYPAD:   sprintf(s, \"joypad\");    break;\r\n\t\tcase INPUT_SRC_TYPE_MOUSE:    sprintf(s, \"mouse\");     break;\r\n\t\t}\r\n\t\tINP_Write_Str (\"type               \", s);\r\n\t\tif (input_src->type == INPUT_SRC_TYPE_JOYPAD)\r\n\t\t\tINP_Write_Int  (\"connection         \", input_src->Connection_Port + 1);\r\n\t\tINP_Write_Str (\"enabled            \", input_src->enabled ? \"yes\" : \"no\");\r\n\t\tINP_Write_Int (\"player             \", input_src->player + 1);\r\n\r\n\t\tfor (int j = 0; j < INPUT_MAP_MAX; j++)\r\n\t\t{\r\n\t\t\tconst t_input_map_entry* map = &input_src->Map[j];\r\n\t\t\tif (map->hw_index == -1)\r\n\t\t\t\tcontinue;\r\n\t\t\ts[0] = EOSTR;\r\n\t\t\tif (input_src->flags & INPUT_SRC_FLAGS_DIGITAL)\r\n\t\t\t{\r\n\t\t\t\tswitch (j)\r\n\t\t\t\t{\r\n\t\t\t\tcase INPUT_MAP_DIGITAL_UP:    strcpy(s, \"player_up          \"); break;\r\n\t\t\t\tcase INPUT_MAP_DIGITAL_DOWN:  strcpy(s, \"player_down        \"); break;\r\n\t\t\t\tcase INPUT_MAP_DIGITAL_LEFT:  strcpy(s, \"player_left        \"); break;\r\n\t\t\t\tcase INPUT_MAP_DIGITAL_RIGHT: strcpy(s, \"player_right       \"); break;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (input_src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n\t\t\t{\r\n\t\t\t\tswitch (j)\r\n\t\t\t\t{\r\n\t\t\t\tcase INPUT_MAP_ANALOG_AXIS_X: strcpy(s, \"player_x_axis      \"); break;\r\n\t\t\t\tcase INPUT_MAP_ANALOG_AXIS_Y: strcpy(s, \"player_y_axis      \"); break;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (StrIsNull(s))\r\n\t\t\t{\r\n\t\t\t\tswitch (j)\r\n\t\t\t\t{\r\n\t\t\t\tcase INPUT_MAP_BUTTON1:     strcpy(s, \"player_button1     \"); break;\r\n\t\t\t\tcase INPUT_MAP_BUTTON2:     strcpy(s, \"player_button2     \"); break;\r\n\t\t\t\tcase INPUT_MAP_PAUSE_START: strcpy(s, \"player_start_pause \"); break;\r\n\t\t\t\tcase INPUT_MAP_RESET:       strcpy(s, \"player_reset       \"); break;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (StrIsNull(s))\r\n\t\t\t\tcontinue;\r\n\t\t\tswitch (input_src->type)\r\n\t\t\t{\r\n\t\t\t\t// Keyboard -----------------------------------------------------------\r\n\t\t\tcase INPUT_SRC_TYPE_KEYBOARD:\r\n\t\t\t\t{\r\n\t\t\t\t\t// Handle special case of the ; key that has to be backslashed\r\n\t\t\t\t\t// Removed because... colon is actually ':', not ';' :)\r\n\t\t\t\t\t// if (n == KEY_COLON)\r\n\t\t\t\t\t//    sprintf(s2, \"key \\\\;\");\r\n\t\t\t\t\t//else\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst t_key_info *key_info = KeyInfo_FindByScancode(map->hw_index);\r\n\t\t\t\t\t\tconst char *key_name = key_info ? key_info->name : \"error\";\r\n\t\t\t\t\t\tchar *key_name_escaped = parse_escape_string(key_name, NULL);\r\n\t\t\t\t\t\tsprintf(s2, \"key %s\", key_name_escaped ? key_name_escaped : key_name);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Joypad -------------------------------------------------------------\r\n\t\t\tcase INPUT_SRC_TYPE_JOYPAD:\r\n\t\t\t\tswitch (map->type)\r\n\t\t\t\t{\r\n\t\t\t\tcase INPUT_MAP_TYPE_JOY_BUTTON:\r\n\t\t\t\t\tsprintf(s2, \"joy_button %i\", map->hw_index);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase INPUT_MAP_TYPE_JOY_AXIS:\r\n\t\t\t\t\tsprintf(s2, \"joy stick %i axis %i dir %i\", map->hw_index, map->hw_axis, map->hw_direction);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\t// Mouse --------------------------------------------------------------\r\n\t\t\tcase INPUT_SRC_TYPE_MOUSE:\r\n\t\t\t\tswitch (map->type)\r\n\t\t\t\t{\r\n\t\t\t\tcase INPUT_MAP_TYPE_MOUSE_BUTTON:\r\n\t\t\t\t\tsprintf(s2, \"mouse_button %i\", map->hw_index);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase INPUT_MAP_TYPE_MOUSE_AXIS:\r\n\t\t\t\t\tsprintf(s2, \"mouse_axis %i\", map->hw_index);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (!StrIsNull(s2))\r\n\t\t\t\tINP_Write_Str(s, s2);\r\n\t\t}\r\n\t\t// Not yet implemented\r\n\t\t// if (input_src->Result_Type == DIGITAL)\r\n\t\t//   INP_Write_Str (\"emulate_analog     \", (input_src->flags & INPUT_SRC_FLAGS_EMULATE_ANALOG) ? \"yes\" : \"no\");\r\n\t\tif (input_src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n\t\t{\r\n\t\t\tINP_Write_Str   (\"emulate_digital    \", (input_src->flags & INPUT_SRC_FLAGS_EMULATE_DIGITAL) ? \"yes\" : \"no\");\r\n\t\t\tINP_Write_Float (\"digital_falloff    \", input_src->Analog_to_Digital_FallOff);\r\n\t\t}\r\n\t\tINP_Write_Line (\"\");\r\n\t}\r\n\r\n\tINP_Write_Line (\";-----------------------------------------------------------------------------\");\r\n\tfclose (INP_File);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/inputs_f.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs_f.h\n// Inputs File Load/Save - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Load_Inputs_Src_List();\nvoid    Write_Inputs_Src_List();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/inputs_i.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs_i.c\n// Inputs Initialization - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"inputs_i.h\"\n#include \"inputs_f.h\"\n#include \"lightgun.h\"\n#include \"periph.h\"\n#include \"rapidfir.h\"\n\n//-----------------------------------------------------------------------------\n// Forward declaration\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Inputs_Init()\n{\n    // Keyboard\n    Inputs.KeyPressedQueue = NULL;\n\n    // Sources\n    Inputs_Sources_Init();\n\n    // Peripheral\n    Peripherals_Init();\n\n    // Load Inputs Sources List\n    Load_Inputs_Src_List();\n}\n\n#ifdef MEKA_JOYPAD\n\nvoid    Inputs_Joystick_Init()\n{\n    int     i;\n    int     num_joy;\n    bool    found = FALSE;\n\n    for (i = 0; i < Inputs.Sources_Max; i++)\n    {\n        t_input_src *src = Inputs.Sources[i];\n        if (src->type == INPUT_SRC_TYPE_JOYPAD)\n        {\n            found = TRUE;\n            break;\n        }\n    }\n    if (found == FALSE)\n        return;\n\n    // There is at least one joypad so we'll launch initialization\n    ConsolePrint(Msg_Get(MSG_Inputs_Joy_Init));\n\n    if (!al_install_joystick() || ((num_joy = al_get_num_joysticks()) == 0))\n    {\n        ConsolePrint(Msg_Get(MSG_Inputs_Joy_Init_None));\n        ConsolePrint(\"\\n\");\n        return;\n    }\n    ConsolePrintf (Msg_Get(MSG_Inputs_Joy_Init_Found), num_joy);\n    ConsolePrint(\"\\n\");\n\n    // Flag available devices \"connected and ready\"\n    for (i = 0; i < Inputs.Sources_Max; i++)\n    {\n        t_input_src *src = Inputs.Sources[i];\n        if (src->type == INPUT_SRC_TYPE_JOYPAD)\n            if (src->Connection_Port < num_joy)\n                src->Connected_and_Ready = TRUE;\n    }\n}\n\nvoid    Inputs_Joystick_Close()\n{\n    al_uninstall_joystick();\n}\n\n#endif // MEKA_JOYPAD\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/inputs_i.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs_i.h\n// Inputs Initialization - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Inputs_Init();\nvoid    Inputs_Close();\n\n#ifdef MEKA_JOYPAD\nvoid    Inputs_Joystick_Init();\nvoid    Inputs_Joystick_Close();\n#endif\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/inputs_t.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs_t.c\n// Inputs Tools - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"inputs_t.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstatic int  typematic_repeating = 0;\nstatic int  typematic_repeat_counter = 0;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Inputs_KeyClearAllState()\n{\n    for (int i = 0; i < ALLEGRO_KEY_MAX; i++)\n        g_keyboard_state[i] = -1.0f;\n}\n\nvoid    Inputs_KeyPressQueue_Remove(t_key_press *keypress)\n{\n    Inputs_KeyEat(keypress->scancode); // FIXME\n\n    list_remove(&Inputs.KeyPressedQueue, keypress);\n    free(keypress);\n}\n\nvoid    Inputs_KeyPressQueue_Clear()\n{\n    list_free(&Inputs.KeyPressedQueue);\n}\n\nbool    Inputs_KeyDown(int keycode)\n{\n    return g_keyboard_state[keycode] >= 0.0f;\n    //return al_key_down(&g_keyboard_state, keycode);\n}\n\n// Eat given key by removing the corresponding flag in the global key[] table\nvoid    Inputs_KeyEat(int keycode)\n{\n    g_keyboard_state[keycode] = -1.0f;\n    //g_keyboard_state.__key_down__internal__[keycode / 32] &= ~(1 << (keycode & 31));\n}\n\n//-----------------------------------------------------------------------------\n// Inputs_KeyPressed (int keycode, bool eat)\n// Return whether given key was just pressed, then eat the key if asked for\n//-----------------------------------------------------------------------------\nbool    Inputs_KeyPressed(int keycode, bool eat)\n{\n    // Check if requested key was just pressed\n    if (Inputs_KeyDown(keycode) && opt.Current_Key_Pressed == 0)\n    {\n        opt.Current_Key_Pressed = keycode;\n        typematic_repeating = FALSE;\n        typematic_repeat_counter = 0;\n        if (eat)\n            Inputs_KeyEat(keycode);\n        return true;\n    }\n    // Check if previously pressed key was released\n    // FIXME: shouldn't be done in this function, but rather in a single inputs-update\n    if (opt.Current_Key_Pressed != 0 && Inputs_KeyDown(opt.Current_Key_Pressed) == false)\n        opt.Current_Key_Pressed = 0;\n    return false;\n}\n\n//-----------------------------------------------------------------------------\n// Inputs_KeyPressed_Repeat (int keycode, bool eat, int delay, int rate)\n// Return whether given key was pressed, handing repetition,\n// then eat the key if asked for.\n//-----------------------------------------------------------------------------\n// FIXME: this function is broken since it relies on static global data. \n// Repeating two keys should mess the whole thing ?\n//-----------------------------------------------------------------------------\nbool    Inputs_KeyPressed_Repeat(int keycode, bool eat, int delay, int rate)\n{\n    // hmm...\n    Inputs_KeyPressed(keycode, eat);\n    if (opt.Current_Key_Pressed != keycode)\n    {\n        //Msg(MSGT_DEBUG, \"%d != %d\", opt.Current_Key_Pressed, keycode);\n        return false;\n    }\n\n    // Increment counter\n    typematic_repeat_counter++;\n\n    // Delay\n    if (typematic_repeating == FALSE)\n    {\n        // Return TRUE on first press\n        if (typematic_repeat_counter == 1)\n            return true;\n        // Then wait for given delay\n        if (typematic_repeat_counter == delay)\n        {\n            typematic_repeating = TRUE;\n            typematic_repeat_counter = 0;\n            return true;\n        }\n    }\n    else\n    {\n        // Repeat\n        if (typematic_repeat_counter == rate)\n        {\n            typematic_repeat_counter = 0;\n            return true;\n        }\n    }\n    return false;\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/inputs_t.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - inputs_t.h\n// Inputs Tools - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Inputs_KeyClearAllState         ();\nvoid    Inputs_KeyEat                   (int keycode);\n\nvoid    Inputs_KeyPressQueue_Remove     (t_key_press *keypress);\nvoid    Inputs_KeyPressQueue_Clear      ();\n\nbool    Inputs_KeyDown                  (int keycode);\nbool    Inputs_KeyPressed               (int keycode, bool eat);\nbool    Inputs_KeyPressed_Repeat        (int keycode, bool eat, int delay, int rate);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/inputs_u.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - inputs_u.c\r\n// Inputs Update - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_game.h\"\r\n#include \"inputs_t.h\"\r\n#include \"lightgun.h\"\r\n#include \"periph.h\"\r\n#include \"rapidfir.h\"\r\n#include \"sk1100.h\"\r\n#include \"tvoekaki.h\"\r\n#include \"video.h\"\r\n#include \"vmachine.h\"\r\n#include \"vdp.h\"\r\n\r\n// #define DEBUG_JOY\r\n\r\nfloat                   g_keyboard_state[ALLEGRO_KEY_MAX];\r\nint                     g_keyboard_modifiers = 0;\r\nALLEGRO_EVENT_QUEUE *   g_keyboard_event_queue = NULL;\r\nALLEGRO_MOUSE_STATE     g_mouse_state;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void Inputs_FixUpJoypadOppositesDirections();\r\nstatic void Inputs_UpdateMouseRange();\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Inputs_Sources_Init()\r\n{\r\n    Inputs.Sources = NULL;\r\n    Inputs.Sources_Max = 0;\r\n\r\n    Inputs.Peripheral [0] = INPUT_JOYPAD;\r\n    Inputs.Peripheral [1] = INPUT_JOYPAD;\r\n\r\n    for (int i = 0; i < ALLEGRO_KEY_MAX; i++)\r\n        g_keyboard_state[i] = -1.0f;\r\n    memset(&g_mouse_state, 0, sizeof(g_mouse_state));\r\n    g_keyboard_event_queue = al_create_event_queue();\r\n    al_register_event_source(g_keyboard_event_queue, al_get_keyboard_event_source());\r\n}\r\n\r\nt_input_src *       Inputs_Sources_Add(char *name)\r\n{\r\n    t_input_src* src = (t_input_src*)malloc (sizeof (t_input_src));\r\n\r\n    src->name                      = name;\r\n    src->type                      = INPUT_SRC_TYPE_KEYBOARD;\r\n    src->enabled                   = TRUE;\r\n    src->flags                     = INPUT_SRC_FLAGS_DIGITAL;\r\n    src->player                    = PLAYER_1;\r\n    src->Connection_Port           = 0;\r\n    src->Analog_to_Digital_FallOff = 0.8f;\r\n    src->Connected_and_Ready       = FALSE; // by default. need to be flagged for use\r\n\r\n    for (int i = 0; i < INPUT_MAP_MAX; i++)\r\n    {\r\n        t_input_map_entry* map = &src->Map[i];\r\n        map->type = INPUT_MAP_TYPE_KEY; // key,button,..\r\n        map->hw_index = -1;\r\n        map->hw_axis = 0;\r\n        map->hw_direction = 0;\r\n        map->current_value = 0;\r\n        map->pressed_counter = 0;\r\n    }\r\n\r\n    Inputs.Sources = (t_input_src**)realloc(Inputs.Sources, (Inputs.Sources_Max + 1) * sizeof (t_input_src *));\r\n    Inputs.Sources [Inputs.Sources_Max] = src;\r\n    Inputs.Sources_Max ++;\r\n\r\n    return (src);\r\n}\r\n\r\nvoid       Inputs_Sources_Close()\r\n{\r\n    for (int i = 0; i < Inputs.Sources_Max; i++)\r\n    {\r\n        t_input_src *input_src = Inputs.Sources[i];\r\n        free(input_src->name);\r\n        free(input_src);\r\n    }\r\n    free(Inputs.Sources);\r\n    Inputs.Sources = NULL;\r\n    Inputs.Sources_Max = 0;\r\n}\r\n\r\n// Update emulation inputs, based on inputs sources data\r\n// If 'running' is false, only update emulation state, but do not produce\r\n// any side effect such as backspace doing an automatic HardReset in GG mode.\r\nvoid    Inputs_Emulation_Update(bool running)\r\n{\r\n    // Control[7] is the following:\r\n    // LG2.LG1.Unused.Reset.P2B.P2A.P2R.P2L - P2D.P2U.P1B.P1A.P1R.P1L.P1D.P1U\r\n    // Now setting all bits (active logic)\r\n    u16* c = &tsms.Control[7];\r\n    *c |= 0x1FFF;\r\n\r\n    // If we are in GUI mode, check if the focused box has the exclusive inputs flag.\r\n    // If it has it and the machine is running (not paused or being debugged), return.\r\n    // The reason for doing that is that handling inputs priority is a mess with the\r\n    // current GUI system, because applet/widget updating code is mostly only run on\r\n    // emulation frame that are not skipped, while inputs for emulation should run for\r\n    // all frames (including skipped ones).\r\n    // So it is a bit complicated to handle a way for an applet to 'eat' a key,\r\n    // and I use an easy path.\r\n    if (g_env.state == MEKA_STATE_GUI && !(g_machine_flags & MACHINE_PAUSED))\r\n    {\r\n        if (gui.boxes_z_ordered[0] && (gui.boxes_z_ordered[0]->flags & GUI_BOX_FLAGS_FOCUS_INPUTS_EXCLUSIVE) != 0)\r\n        {\r\n            // Returning from the emulation inputs update requires to take care of a few variables...\r\n            if (tsms.Control_Start_Pause == 1) // Leave it if it is == 2\r\n                tsms.Control_Start_Pause = 0;\r\n            if (g_driver->id == DRV_GG)\r\n                tsms.Control_GG |= (0x80);\r\n            if (Inputs.SK1100_Enabled)\r\n                SK1100_Clear();\r\n            return;\r\n        }\r\n    }\r\n\r\n    bool pause_pressed = false;\r\n    bool reset_pressed = false;\r\n\r\n    // Convert input sources data to emulation inputs data\r\n    const int players = ((g_driver->id == DRV_GG) ? 1 : 2); // 1 player on GG, else 2\r\n    for (int i = 0; i < players; i++)\r\n    {\r\n        for (int src_index = 0; src_index < Inputs.Sources_Max; src_index++)\r\n        {\r\n            const t_input_src* src = Inputs.Sources[src_index];\r\n            if (src->enabled == FALSE || src->player != i)\r\n                continue;\r\n\r\n            // If current peripheral is digital, skip analog only inputs sources\r\n            // If current peripheral is analog, skip digital only inputs sources\r\n            // k = Inputs_Peripheral_Infos [Inputs.Peripheral [i]].result_type;\r\n            // if (!(Src->Result_Type & (k | (k << 1))))\r\n            //    continue;\r\n            // Process peripheral dependent stuff\r\n            switch (Inputs.Peripheral[i])\r\n            {\r\n            case INPUT_JOYPAD: //---------------------------- Joypad/Control Stick\r\n                if (src->flags & INPUT_SRC_FLAGS_DIGITAL)\r\n                {\r\n                    //Msg(MSGT_DEBUG, \"Player %d Src %d LEFT=%d\", i, source_index, src->Map[INPUT_MAP_DIGITAL_LEFT].Res);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_UP].current_value)     *c &= (!i? ~0x0001 : ~0x0040);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_DOWN].current_value)   *c &= (!i? ~0x0002 : ~0x0080);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_LEFT].current_value)   *c &= (!i? ~0x0004 : ~0x0100);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_RIGHT].current_value)  *c &= (!i? ~0x0008 : ~0x0200);\r\n                    if (src->Map[INPUT_MAP_BUTTON1].current_value)        *c &= (!i? ~0x0010 : ~0x0400);\r\n                    if (src->Map[INPUT_MAP_BUTTON2].current_value)        *c &= (!i? ~0x0020 : ~0x0800);\r\n                }\r\n                else if (src->flags & INPUT_SRC_FLAGS_EMULATE_DIGITAL) // ANALOG\r\n                {\r\n                    if (src->Map[INPUT_MAP_ANALOG_AXIS_Y_REL].current_value < 0)  *c &= (!i? ~0x0001 : ~0x0040);\r\n                    if (src->Map[INPUT_MAP_ANALOG_AXIS_Y_REL].current_value > 0)  *c &= (!i? ~0x0002 : ~0x0080);\r\n                    if (src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].current_value < 0)  *c &= (!i? ~0x0004 : ~0x0100);\r\n                    if (src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].current_value > 0)  *c &= (!i? ~0x0008 : ~0x0200);\r\n                    if (src->Map[INPUT_MAP_BUTTON1].current_value)                *c &= (!i? ~0x0010 : ~0x0400);\r\n                    if (src->Map[INPUT_MAP_BUTTON2].current_value)                *c &= (!i? ~0x0020 : ~0x0800);\r\n                }\r\n                break;\r\n            case INPUT_LIGHTPHASER: //------------------------------- Light Phaser\r\n                if (src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n                    LightPhaser_Update(i, src->Map[INPUT_MAP_ANALOG_AXIS_X].current_value, src->Map[INPUT_MAP_ANALOG_AXIS_Y].current_value);\r\n                if (src->Map[INPUT_MAP_BUTTON1].current_value)           *c &= (!i? ~0x0010 : ~0x0400);\r\n                if (src->Map[INPUT_MAP_BUTTON2].current_value)           *c &= (!i? ~0x0020 : ~0x0800);\r\n                break;\r\n            case INPUT_PADDLECONTROL: //------------------------ Paddle Controller\r\n                {\r\n                    int x = Inputs.Paddle[i].x;\r\n                    int dx = 0;\r\n                    if (src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n                    {\r\n                        // Using analog relative movement\r\n                        dx = src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].current_value;\r\n                        if (dx > 0)\r\n                            dx = (dx + 4) / 5;\r\n                        else if (dx < 0)\r\n                            dx = (dx - 4) / 5;\r\n                    }\r\n                    else\r\n                    {\r\n                        // Using digital\r\n                        // Linear maxed acceleration\r\n                        const int dx_table[1+5] =\r\n                        { 0, 1, 2, 3, 5, 7 };\r\n                        //0  1  2  3  4  5, 6\r\n                        //Msg(MSGT_DEBUG, \"Map[DIGITAL_LEFT].pressed_counter = %d, [DIGITAL_RIGHT] = %d\", src->Map[INPUT_MAP_DIGITAL_LEFT].pressed_counter, src->Map[INPUT_MAP_DIGITAL_RIGHT].pressed_counter);\r\n                        if (src->Map[INPUT_MAP_DIGITAL_LEFT].pressed_counter > 0 && src->Map[INPUT_MAP_DIGITAL_RIGHT].pressed_counter == 0)\r\n                        {\r\n                            dx = src->Map[INPUT_MAP_DIGITAL_LEFT].pressed_counter;\r\n                            dx = -dx_table[(dx > 5) ? 5 : dx];\r\n                        }\r\n                        if (src->Map[INPUT_MAP_DIGITAL_RIGHT].pressed_counter > 0 && src->Map[INPUT_MAP_DIGITAL_LEFT].pressed_counter == 0)\r\n                        {\r\n                            dx = src->Map[INPUT_MAP_DIGITAL_RIGHT].pressed_counter;\r\n                            dx = dx_table[(dx > 5) ? 5 : dx];\r\n                        }\r\n                    }\r\n                    if (dx != 0)\r\n                    {\r\n                        x += dx;\r\n                        if (x < 0) x = 0; else if (x > 255) x = 255;\r\n                        Inputs.Paddle[i].x = x;\r\n                    }\r\n                    // Button 1 (only one button on Paddle Control)\r\n                    if (src->Map[INPUT_MAP_BUTTON1].current_value)           *c &= (!i? ~0x0010 : ~0x0400);\r\n                    break;\r\n                }\r\n            case INPUT_SPORTSPAD: //--------------------------------- Sports Pads\r\n                if (src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n                    Peripherals_SportsPad_Update(i, src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].current_value, src->Map[INPUT_MAP_ANALOG_AXIS_Y_REL].current_value);\r\n                if (src->Map[INPUT_MAP_BUTTON1].current_value)           *c &= (!i? ~0x0010 : ~0x0400);\r\n                if (src->Map[INPUT_MAP_BUTTON2].current_value)           *c &= (!i? ~0x0020 : ~0x0800);\r\n                break;\r\n            case INPUT_GRAPHICBOARD: //----------------------------- Terebi Oekaki\r\n                if (src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n                {\r\n                    // Create button field (this is due to old code legacy)\r\n                    const int b_field = (src->Map[INPUT_MAP_BUTTON1].current_value ? 1 : 0) | (src->Map[INPUT_MAP_BUTTON2].current_value ? 2 : 0);\r\n                    TVOekaki_Update (src->Map[INPUT_MAP_ANALOG_AXIS_X].current_value, src->Map[INPUT_MAP_ANALOG_AXIS_Y].current_value, b_field);\r\n                }\r\n                else // Support standard controller with digital inputs, because the\r\n                {    // Terebi Oekaki is not connected to the controller port, it is free to use !\r\n                    if (src->Map[INPUT_MAP_DIGITAL_UP].current_value)     *c &= (!i? ~0x0001 : ~0x0040);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_DOWN].current_value)   *c &= (!i? ~0x0002 : ~0x0080);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_LEFT].current_value)   *c &= (!i? ~0x0004 : ~0x0100);\r\n                    if (src->Map[INPUT_MAP_DIGITAL_RIGHT].current_value)  *c &= (!i? ~0x0008 : ~0x0200);\r\n                    if (src->Map[INPUT_MAP_BUTTON1].current_value)        *c &= (!i? ~0x0010 : ~0x0400);\r\n                    if (src->Map[INPUT_MAP_BUTTON2].current_value)        *c &= (!i? ~0x0020 : ~0x0800);\r\n                }\r\n                break;\r\n            case INPUT_GRAPHICBOARD_V2:\r\n                if (src->flags & INPUT_SRC_FLAGS_ANALOG)\r\n                {\r\n                    const int buttons = (src->Map[INPUT_MAP_BUTTON1].current_value ? 2 : 0) | (src->Map[INPUT_MAP_BUTTON2].current_value ? 4 : 0) | (src->Map[INPUT_MAP_PAUSE_START].current_value ? 1 : 0);\r\n                    Peripherals_GraphicBoardV2_Update(i, src->Map[INPUT_MAP_ANALOG_AXIS_X].current_value, src->Map[INPUT_MAP_ANALOG_AXIS_Y].current_value, buttons);\r\n                }\r\n                break;\r\n            }\r\n            // Process RESET and PAUSE/START buttons\r\n            if (src->Map[INPUT_MAP_PAUSE_START].current_value) { pause_pressed = TRUE; if (tsms.Control_Start_Pause == 0) tsms.Control_Start_Pause = 1; }\r\n            if (src->Map[INPUT_MAP_RESET].current_value)       { reset_pressed = TRUE; }\r\n        }\r\n    }\r\n\r\n    // SK-1100 Keyboard update\r\n    if (Inputs.SK1100_Enabled)\r\n        SK1100_Update();\r\n\r\n    // Handle reset and clear pause latch if necessary\r\n    if (reset_pressed == TRUE)\r\n    {\r\n        if (g_driver->id == DRV_SMS)\r\n        {\r\n            // Set the reset bit on SMS\r\n            // FIXME: What about always setting it? (not only on SMS)\r\n            *c &= ~0x1000;\r\n        }\r\n        else\r\n        {\r\n            if (running)\r\n            {\r\n                // If SK-1100 is not emulated then process with an hardware Reset\r\n                // Note: this test is invalid in case Reset was pressed from a pad, it will cancel pressing reset from the pad\r\n                if (Inputs.SK1100_Enabled == FALSE)\r\n                    Machine_Reset();\r\n            }\r\n        }\r\n    }\r\n\r\n    if (pause_pressed == FALSE)\r\n        tsms.Control_Start_Pause = 0;\r\n\r\n    // Game Gear Start button\r\n    if (g_driver->id == DRV_GG)\r\n    {\r\n        if (tsms.Control_Start_Pause == 1)\r\n            tsms.Control_GG &= (~0x80);\r\n        else\r\n            tsms.Control_GG |= (0x80);\r\n    }\r\n\r\n    // Correct the cases where opposite directions are pressed\r\n    if (!g_config.allow_opposite_directions)\r\n        Inputs_FixUpJoypadOppositesDirections();\r\n\r\n    // Simulate Rapid Fire\r\n    if (running)\r\n    {\r\n        if (RapidFire != 0)\r\n            RapidFire_Update();\r\n    }\r\n}\r\n\r\n// Read and update all inputs sources\r\nvoid    Inputs_Sources_Update()\r\n{\r\n    float dt = 1.0f/60.0f;      // FIXME: Delta time\r\n\r\n    for (int i = 0; i < ALLEGRO_KEY_MAX; i++)\r\n        if (g_keyboard_state[i] >= 0.0f)\r\n            g_keyboard_state[i] += dt;\r\n\r\n    // Process keyboard events\r\n    ALLEGRO_EVENT key_event;\r\n    while (al_get_next_event(g_keyboard_event_queue, &key_event))\r\n    {\r\n        switch (key_event.type)\r\n        {\r\n        case ALLEGRO_EVENT_KEY_DOWN:\r\n            //Msg(MSGT_DEBUG, \"ALLEGRO_EVENT_KEY_DOWN %d\", key_event.keyboard.keycode);\r\n            if (g_keyboard_state[key_event.keyboard.keycode] < 0.0f)\r\n                g_keyboard_state[key_event.keyboard.keycode] = 0.0f;\r\n            break;\r\n        case ALLEGRO_EVENT_KEY_UP:\r\n            //Msg(MSGT_DEBUG, \"ALLEGRO_EVENT_KEY_UP %d\", key_event.keyboard.keycode);\r\n            g_keyboard_state[key_event.keyboard.keycode] = -1.0f;\r\n            break;\r\n        case ALLEGRO_EVENT_KEY_CHAR:\r\n            // Process 'character' keypresses\r\n            // Those are transformed (given keyboard state & locale) into printable character\r\n            // Equivalent to using ToUnicode() in the Win32 API.\r\n            // Note: Allegro is handling repeat for us here.\r\n            if (key_event.keyboard.unichar > 0 && (key_event.keyboard.unichar & ~0xFF) == 0)\r\n            {\r\n                //Msg(MSGT_DEBUG, \"%i %04x\", key_event.keyboard.keycode, key_event.keyboard.unichar);\r\n                t_key_press* key_press = (t_key_press*)malloc(sizeof(*key_press));\r\n                key_press->scancode = key_event.keyboard.keycode;\r\n                key_press->ascii = key_event.keyboard.unichar & 0xFF;\r\n                list_add_to_end(&Inputs.KeyPressedQueue, key_press);\r\n            }\r\n            break;\r\n        }\r\n    }\r\n    \r\n    // Allegro 5 doesn't receive PrintScreen under Windows because of the high-level API it is using.\r\n#ifdef ARCH_WIN32\r\n    if (GetAsyncKeyState(VK_SNAPSHOT))\r\n        g_keyboard_state[ALLEGRO_KEY_PRINTSCREEN] = g_keyboard_state[ALLEGRO_KEY_PRINTSCREEN] < 0.0f ? 0.0f : g_keyboard_state[ALLEGRO_KEY_PRINTSCREEN] + dt;\r\n    else\r\n        g_keyboard_state[ALLEGRO_KEY_PRINTSCREEN] = -1.0f;\r\n    // g_keyboard_state.__key_down__internal__[ALLEGRO_KEY_PRINTSCREEN/32] |= (1 << (ALLEGRO_KEY_PRINTSCREEN & 31));\r\n#endif\r\n\r\n    // Update keyboard modifiers flags\r\n    g_keyboard_modifiers = 0;\r\n    if (Inputs_KeyDown(ALLEGRO_KEY_LCTRL) || Inputs_KeyDown(ALLEGRO_KEY_RCTRL))\r\n        g_keyboard_modifiers |= ALLEGRO_KEYMOD_CTRL;\r\n    if (Inputs_KeyDown(ALLEGRO_KEY_ALT) || Inputs_KeyDown(ALLEGRO_KEY_ALTGR))\r\n        g_keyboard_modifiers |= ALLEGRO_KEYMOD_ALT;\r\n    if (Inputs_KeyDown(ALLEGRO_KEY_LSHIFT) || Inputs_KeyDown(ALLEGRO_KEY_RSHIFT))\r\n        g_keyboard_modifiers |= ALLEGRO_KEYMOD_SHIFT;\r\n\r\n    // Keyboard debugging\r\n#if 0\r\n    u8 win32_keyboard_state[256];\r\n    memset(&win32_keyboard_state[0], 0, sizeof(win32_keyboard_state));\r\n    bool ret = GetKeyboardState(&win32_keyboard_state[0]);\r\n    for (int i = 0; i != 256; i++)\r\n        if (win32_keyboard_state[i])\r\n            Msg(MSGT_DEBUG, \"[%d Win32 pressed %d\\n\", ret, i);\r\n        //if (GetAsyncKeyState(i))\r\n        //  Msg( MSGT_DEBUG, \"[%d] Win32 Pressed key %d, %08x\", ret, i, GetAsyncKeyState(i));\r\n\r\n    //for (int i = 0; i != ALLEGRO_KEY_MAX; i++)\r\n    //  if (al_key_down(&g_keyboard_state, i))\r\n    //      Msg( MSGT_DEBUG, \"Pressed key %d\", i);\r\n#endif\r\n\r\n    // Poll mouse\r\n    al_get_mouse_state(&g_mouse_state);\r\n\r\n    // FIXME-ALLEGRO5: Used to be provided by Allegro 4 as mouse_mx, mouse_my (mickeys?) - check SVN log\r\n    //int screen_center_x, screen_center_y;\r\n    //Video_GameMode_GetScreenCenterPos(&screen_center_x, &screen_center_y);\r\n    //const int mouse_mx_unbounded = g_mouse_state.x - screen_center_x;\r\n    //const int mouse_my_unbounded = g_mouse_state.y - screen_center_y;\r\n    const int mouse_mx_unbounded = g_mouse_state.x - gui.mouse.x_prev;\r\n    const int mouse_my_unbounded = g_mouse_state.y - gui.mouse.y_prev;\r\n\r\n    // Recenter and clamp in range\r\n    Inputs_UpdateMouseRange();\r\n\r\n    for (int i = 0; i < Inputs.Sources_Max; i++)\r\n    {\r\n        t_input_src *Src = Inputs.Sources[i];\r\n        if (!Src->enabled || Src->Connected_and_Ready == FALSE)\r\n            continue;\r\n        switch (Src->type)\r\n        {\r\n            // Keyboard -------------------------------------------------------------\r\n        case INPUT_SRC_TYPE_KEYBOARD:\r\n            {\r\n                for (int j = 0; j != INPUT_MAP_MAX; j++)\r\n                {\r\n                    t_input_map_entry *map = &Src->Map[j];\r\n                    const int old_res = map->current_value;\r\n                    map->current_value = (map->hw_index != -1 && Inputs_KeyDown(map->hw_index));\r\n                    if (old_res && map->current_value)\r\n                    {\r\n                        Src->Map[j].pressed_counter++;\r\n                        //Msg(MSGT_DEBUG, \"Map %d on\", j);\r\n                    }\r\n                    else\r\n                    {\r\n                        Src->Map[j].pressed_counter = 0;\r\n                    }\r\n                }\r\n                break;\r\n            }\r\n#ifdef MEKA_JOYPAD\r\n            // Digital Joypad/Joystick ----------------------------------------------\r\n        case INPUT_SRC_TYPE_JOYPAD:\r\n            {\r\n                ALLEGRO_JOYSTICK *joystick = al_get_joystick(Src->Connection_Port);\r\n                ALLEGRO_JOYSTICK_STATE state;\r\n                al_get_joystick_state(joystick, &state);\r\n\r\n#ifdef DEBUG_JOY\r\n                {\r\n                    const int num_sticks = al_get_joystick_num_sticks(joystick);\r\n                    const int num_buttons = al_get_joystick_num_buttons(joystick);\r\n\r\n                    Msg(MSGT_DEBUG, \"Joystick %d\", Src->Connection_Port);\r\n                    for (int i = 0; i < num_sticks; i++)\r\n                    {\r\n                        const int num_axes = al_get_joystick_num_axes(joystick, i);\r\n                        Msg(MSGT_DEBUG, \"- Stick %d\\n\", i);\r\n                        for (int j = 0; j < num_axes; j++)\r\n                        {\r\n                            Msg(MSGT_DEBUG, \"   - Axis %d (pos = %f)\\n\", j, state.stick[i].axis[j]);\r\n                        }\r\n                    }\r\n\r\n                    char buf[512];\r\n                    strcpy(buf, \"- Buttons \");\r\n                    for (int i = 0; i < num_buttons; i++)\r\n                        sprintf(buf + strlen(buf), \"%d \", state.button[i]);\r\n                    Msg(MSGT_DEBUG, buf);\r\n                }\r\n#endif\r\n\r\n                for (int j = 0; j != INPUT_MAP_MAX; j++)\r\n                {\r\n                    t_input_map_entry *map = &Src->Map[j];\r\n                    int old_res = map->current_value;\r\n                    switch (map->type)\r\n                    {\r\n                    case INPUT_MAP_TYPE_JOY_AXIS:\r\n                        {\r\n                            const float v = state.stick[map->hw_index].axis[map->hw_axis];\r\n                            map->current_value = (map->hw_direction ? v > INPUT_JOY_DEADZONE : v < -INPUT_JOY_DEADZONE);\r\n                            break;\r\n                        }\r\n                    case INPUT_MAP_TYPE_JOY_BUTTON:\r\n                        {\r\n                            map->current_value = (map->hw_index != (-1) && state.button[map->hw_index]);\r\n                            break;\r\n                        }\r\n                    }\r\n                    if (old_res && map->current_value)\r\n                        Src->Map[j].pressed_counter++;\r\n                    else\r\n                        Src->Map[j].pressed_counter = 0;\r\n                }\r\n                break;\r\n            }\r\n#endif // #ifdef MEKA_JOYPAD\r\n            // Mouse ----------------------------------------------------------------\r\n        case INPUT_SRC_TYPE_MOUSE:\r\n            {\r\n                bool disable_mouse_button = false;\r\n\r\n                if (g_env.state == MEKA_STATE_GAME)\r\n                {\r\n                    int mx, my;\r\n                    Video_GameMode_ScreenPosToEmulatedPos(g_mouse_state.x, g_mouse_state.y, &mx, &my, true);\r\n                    //Msg(MSGT_USER, \"%d %d\", mx, my);\r\n                    Src->Map[INPUT_MAP_ANALOG_AXIS_X].current_value = mx;\r\n                    Src->Map[INPUT_MAP_ANALOG_AXIS_Y].current_value = my;\r\n                }\r\n                else\r\n                {\r\n                    // Compute distance to first GUI game box\r\n                    // FIXME: this sucks\r\n                    int x = g_mouse_state.x - gamebox_instance->frame.pos.x;\r\n                    int y = g_mouse_state.y - gamebox_instance->frame.pos.y;\r\n                    if (x < 0 || y < 0 || x >= gamebox_instance->frame.size.x || y >= gamebox_instance->frame.size.y)\r\n                        disable_mouse_button = true;\r\n                    if (x < 0) x = 0;\r\n                    // if (x > 255) x = 255;\r\n                    if (y < 0) y = 0;\r\n\r\n                    const float sx = (float)g_driver->x_res / (gamebox_instance->frame.size.x + 1);\r\n                    const float sy = (float)g_driver->y_res / (gamebox_instance->frame.size.y + 1);\r\n                    x *= sx;\r\n                    y *= sy;\r\n                    if ((g_driver->id == DRV_SMS) && (Mask_Left_8))\r\n                        x += 4;\r\n\r\n                    Src->Map[INPUT_MAP_ANALOG_AXIS_X].current_value = x;\r\n                    Src->Map[INPUT_MAP_ANALOG_AXIS_Y].current_value = y;\r\n                }\r\n\r\n                int x = Src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].current_value;\r\n                //Msg(MSGT_DEBUG, \"x = %d, %d - %d\", x, g_mouse_state.x,gui.mouse.x_prev);\r\n                const int mx = mouse_mx_unbounded;\r\n                if (x > 0 && mx < x)\r\n                { if (mx < 0) x = 0; else x *= Src->Analog_to_Digital_FallOff; }\r\n                else if (x < 0 && mx > x)\r\n                { if (mx > 0) x = 0; else x *= Src->Analog_to_Digital_FallOff; }\r\n                else\r\n                { x = mx; }\r\n                Src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].current_value = x;\r\n\r\n                int y = Src->Map[INPUT_MAP_ANALOG_AXIS_Y_REL].current_value;\r\n                const int my = mouse_my_unbounded;\r\n                if (y > 0 && my < y)\r\n                { if (my < 0) y = 0; else y *= Src->Analog_to_Digital_FallOff; }\r\n                else if (y < 0 && my > y)\r\n                { if (my > 0) y = 0; else y *= Src->Analog_to_Digital_FallOff; }\r\n                else\r\n                { y = my; }\r\n                Src->Map[INPUT_MAP_ANALOG_AXIS_Y_REL].current_value = y;\r\n\r\n                // No counters for analog data\r\n                Src->Map[INPUT_MAP_ANALOG_AXIS_X].pressed_counter = 0;\r\n                Src->Map[INPUT_MAP_ANALOG_AXIS_Y].pressed_counter = 0;\r\n                Src->Map[INPUT_MAP_ANALOG_AXIS_X_REL].pressed_counter = 0;\r\n                Src->Map[INPUT_MAP_ANALOG_AXIS_Y_REL].pressed_counter = 0;\r\n\r\n                // Buttons\r\n                for (int j = 4; j < INPUT_MAP_MAX; j++)\r\n                {\r\n                    t_input_map_entry *map = &Src->Map[j];\r\n                    const int old_res = map->current_value;\r\n                    const int button_mask = (1 << Src->Map[j].hw_index);\r\n                    if (disable_mouse_button)\r\n                        Src->Map[j].current_value = 0;\r\n                    else\r\n                        Src->Map[j].current_value = (Src->Map[j].hw_index != -1 && (g_mouse_state.buttons & button_mask));\r\n                    if (old_res && map->current_value)\r\n                        Src->Map[j].pressed_counter++;\r\n                    else\r\n                        Src->Map[j].pressed_counter = 0;\r\n                }\r\n                break;\r\n            }\r\n            //-----------------------------------------------------------------------\r\n        }\r\n    }\r\n}\r\n\r\nvoid Inputs_Sources_ClearOutOfFocus()\r\n{\r\n    for (size_t i = 0; i < ALLEGRO_KEY_MAX; i++)\r\n        g_keyboard_state[i] = -1.0f;\r\n    g_keyboard_modifiers = 0;\r\n}\r\n\r\nvoid Inputs_UpdateMouseRange()\r\n{\r\n    if (g_env.state != MEKA_STATE_GAME)\r\n        return;\r\n\r\n    int sx_org;\r\n    int sy_org;\r\n    Video_GameMode_ScreenPosToEmulatedPos(g_mouse_state.x, g_mouse_state.y, &sx_org, &sy_org, false);\r\n\r\n    if (Inputs.mouse_cursor == MEKA_MOUSE_CURSOR_LIGHT_PHASER || Inputs.mouse_cursor == MEKA_MOUSE_CURSOR_TV_OEKAKI)\r\n    {\r\n        const int sx = Clamp<int>(sx_org, (Mask_Left_8) ? 8 : 0, g_driver->x_res);\r\n        const int sy = Clamp<int>(sy_org, 0, g_driver->y_res);\r\n        if (sx != sx_org || sy != sy_org)\r\n        {\r\n            int mx, my;\r\n            Video_GameMode_EmulatedPosToScreenPos(sx, sy, &mx, &my, false);\r\n            al_set_mouse_xy(g_display, mx, my);\r\n        }\r\n    }\r\n    else if (Inputs.Peripheral[PLAYER_1] == INPUT_SPORTSPAD || Inputs.Peripheral[PLAYER_2] == INPUT_SPORTSPAD)\r\n    {\r\n        // Recenter so we can keep moving\r\n        int sx, sy;\r\n        Video_GameMode_GetScreenCenterPos(&sx, &sy);\r\n        al_set_mouse_xy(g_display, sx, sy);\r\n    }\r\n\r\n    //Msg(MSGT_USER, \"xy %d %d -> %d %d\", sx_org, sy_org, sx, sy);\r\n}\r\n\r\n// Fix up/down & left/right cases\r\nstatic void    Inputs_FixUpJoypadOppositesDirections()\r\n{\r\n    u16        joy = tsms.Control[7];\r\n    if (!(joy & (0x0001 | 0x0002))) { joy |= (0x0001 | 0x0002); } // P1 Up & Down\r\n    if (!(joy & (0x0004 | 0x0008))) { joy |= (0x0004 | 0x0008); } // P1 Left & Right\r\n    if (!(joy & (0x0040 | 0x0080))) { joy |= (0x0040 | 0x0080); } // P2 Up & Down\r\n    if (!(joy & (0x0100 | 0x0200))) { joy |= (0x0100 | 0x0200); } // P2 Left & Right\r\n    tsms.Control[7] = joy;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/inputs_u.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - inputs_u.h\r\n// Inputs Update - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid            Inputs_Emulation_Update(bool running);\r\n\r\nvoid            Inputs_Sources_Init();\r\nvoid            Inputs_Sources_Close();\r\nt_input_src *   Inputs_Sources_Add(char *name);\r\nvoid            Inputs_Sources_Update();\r\nvoid            Inputs_Sources_ClearOutOfFocus();\r\n\r\nextern float                    g_keyboard_state[ALLEGRO_KEY_MAX];      // -1: not pressed, 0:just pressed, >0: held time\r\nextern int                      g_keyboard_modifiers;\r\nextern ALLEGRO_MOUSE_STATE      g_mouse_state;\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/ioports.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - ioports.c\r\n// I/O Ports Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: Old, crappy, incorrect mess.\r\n// FIXME: Implement proper port map, mirroring, etc. Per system.\r\n//-----------------------------------------------------------------------------\r\n\r\n//#define DEBUG_IO\r\n#include \"shared.h\"\r\n#include \"beam.h\"\r\n#include \"bios.h\"\r\n#include \"commport.h\"\r\n#include \"fdc765.h\"\r\n#include \"sf7000.h\"\r\n#include \"vdp.h\"\r\n#include \"periph.h\"\r\n#include \"mappers.h\"\r\n#include \"vmachine.h\"\r\n#include \"sound/fmunit.h\"\r\n#include \"sound/psg.h\"\r\n#include \"sdsc.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define IO_LOG_WRITE()  { Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Port_Write), CPU_GetPC, Port, Value); }\r\n\r\n#define IO_LOG_READ()   { Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Port_Read), CPU_GetPC, Port); }\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n// I/O: Port output\r\nvoid    Out_SMS(u16 Port, u8 Value)\r\n{\r\n    // 0x80..0xBF : VDP\r\n    if ((Port & 0xC0) == 0x80)\r\n    {\r\n        if (Port & 0x01)\r\n        {\r\n            // 0xBD,0xBF and odd addresses: VDP Address\r\n            Tms_VDP_Out_Address(Value);\r\n            return;\r\n        }\r\n        else\r\n        {\r\n            // 0xBE and even addresses: VDP Data\r\n            Tms_VDP_Out_Data(Value);\r\n            return;\r\n        }\r\n    }\r\n\r\n    switch (Port)\r\n    {\r\n        // LightGun & Nationalization port\r\n    case 0x3F: \r\n        {\r\n            const u8 old_value = tsms.Port3F;\r\n            const u8 new_value = Value;\r\n            Peripherals_WritePort3F(old_value, new_value);\r\n            tsms.Port3F = Value;\r\n            // IO_LOG_WRITE();\r\n            return;\r\n        }\r\n\r\n        // YM2413 FM ports\r\n    case 0xF0:\r\n        sms.FM_Register = Value & 0x3F;\r\n        return;\r\n    case 0xF1:\r\n        // Here we are not testing if FM Unit is enabled\r\n        // Because SMS Japanese BIOS always use FM Unit (as well as PSG).\r\n        // if (Sound.FM_Enabled)\r\n        {\r\n            if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\r\n            {\r\n                VGM_Data_Add_FM(&Sound.LogVGM, (Value << 8) | sms.FM_Register);\r\n            }\r\n            FM_Write(sms.FM_Register, Value);\r\n        }\r\n        return;\r\n    case 0xF2: \r\n        if (Sound.FM_Enabled)\r\n        {\r\n            sms.FM_Magic = Value;\r\n        }\r\n        return;\r\n\r\n    case 0xFC:\r\n        SDSC_Debug_Console_Control(Value);\r\n        return;\r\n\r\n    case 0xFD:\r\n        SDSC_Debug_Console_Data(Value);\r\n        return;\r\n\r\n       // 0x7E, 0x7F: SN76489 PSG\r\n       // NB: At least Cosmic Spacehead uses 0x7E for writing.\r\n    case 0x7E: case 0x7F:\r\n        SN76489_Write (Value);\r\n        return;\r\n\r\n        // 0xDE: Keyboard Raster\r\n    case 0xDE: \r\n        sms.Input_Mode = Value; // & 7; // Upper bits needed for SK-1100 detection\r\n        // Msg(MSGT_DEBUG, \"At %04Xh: Port 0xDE = %02Xh\", sms.R.PC.W, Value);\r\n        return;\r\n\r\n    case 0xE0:\r\n        if (g_machine.mapper == MAPPER_SC3000_Survivors_Multicart)\r\n            Out_SC3000_SurvivorsMulticarts_DataWrite(Value);\r\n        return;\r\n\r\n        // Gear-to-gear Emulation\r\n    case 0x01: Comm_Write_01 (Value); return;\r\n    case 0x02: Comm_Write_02 (Value); return;\r\n    case 0x03: Comm_Write_03 (Value); return;\r\n    case 0x05: Comm_Write_05 (Value); return;\r\n\r\n        // Game Gear Stereo\r\n        // FIXME: emulate stereo!\r\n    case 0x06: \r\n        if (g_driver->id == DRV_GG)\r\n        {\r\n            SN76489_StereoWrite (Value);\r\n            if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\r\n                VGM_Data_Add_GG_Stereo (&Sound.LogVGM, Value);\r\n        }\r\n        return;\r\n\r\n    case 0x3E: \r\n        // RAM [0] = Value & 7;\r\n        // Msgt (MSGT_DEBUG, \"At %04Xh: [%02Xh] = %02Xh\", sms.R.PC.W, Port, Value);\r\n        return;\r\n\r\n        // 0xFF/255: Switch from BIOS to Cartridge -----------------------------------\r\n        // FIXME: This is awful\r\n    case 0xFF: \r\n        if ((g_machine_flags & (MACHINE_ROM_LOADED | MACHINE_NOT_IN_BIOS)) == MACHINE_ROM_LOADED)\r\n            BIOS_Switch_to_Game();\r\n        return;\r\n    }\r\n\r\n#ifdef DEBUG_IO\r\n    IO_LOG_WRITE();\r\n#endif\r\n}\r\n\r\n// I/O: Port input\r\nu8      In_SMS (u16 Port)\r\n{\r\n    // 0x80..0xBF : VDP\r\n    if ((Port & 0xC0) == 0x80)\r\n    {\r\n        if (Port & 0x01)\r\n            return Tms_VDP_In_Status(); // 0xBD,0xBF and odd addresses: VDP Status\r\n        else\r\n            return Tms_VDP_In_Data();   // 0xBE and even addresses: VDP Data\r\n    }\r\n\r\n    // 0x40 .. 0x7F : H/V counters\r\n    if ((Port & 0xC0) == 0x40)\r\n    {\r\n        if (Port & 0x01)\r\n            return Beam_X();    // HCounter (Latched)\r\n        else\r\n            return Beam_Y();    // VCounter\r\n    }\r\n\r\n    // FIXME: Proper mirroring/port mapping is not emulated.\r\n    switch (Port)\r\n    {\r\n        // Input Port 1 (Controller 1 and part of Controller 2)\r\n    case 0xC0:\r\n    case 0xDC: \r\n        return Input_Port_DC();\r\n\r\n        // Input Port 2 (Controller 2 & Latches)\r\n    case 0xC1:\r\n    case 0xDD: \r\n        return Input_Port_DD();\r\n\r\n        // Keyboard scan / printer / cassette\r\n    case 0xDE: \r\n        if (Inputs.SK1100_Enabled)\r\n            return (sms.Input_Mode);\r\n        return (0xFF);\r\n\r\n        // Joystick 3 Port (Game Gear)\r\n    case 0x00: \r\n        if (g_driver->id == DRV_GG)\r\n        {\r\n            switch (sms.Country)\r\n            {\r\n            case COUNTRY_EXPORT:    tsms.Control_GG |= 0x40; break;\r\n            case COUNTRY_JAPAN:     tsms.Control_GG &= 0xBF; break;\r\n            }\r\n            return (tsms.Control_GG /* | 0x3F */);\r\n        }\r\n        // FIXME: There is a difference here between models of SMS, and Wonder Boy in Monster World\r\n        // takes advantage of it.\r\n        return (0x00);\r\n\r\n        // FM Unit Detection\r\n    case 0xF2: \r\n        return (sms.FM_Magic);\r\n\r\n        // Gear-to-Gear\r\n    case 0x01: return (Comm_Read_01 ());\r\n    case 0x02: return (Comm_Read_02 ());\r\n    case 0x03: return (Comm_Read_03 ());\r\n    case 0x04: return (Comm_Read_04 ());\r\n    case 0x05: return (Comm_Read_05 ());\r\n\r\n        /*\r\n        // [Arcade] Inputs\r\n        //      Bit 0 : Coin\r\n        //      Bit 6 : Start\r\n    case 0xE0:\r\n        {\r\n            u8 v = 0xFF;\r\n            //IO_LOG_READ();\r\n            if (key[KEY_1]) v &= ~0x80;\r\n            if (key[KEY_2]) v &= ~0x40;\r\n            if (key[KEY_3]) v &= ~0x20;\r\n            if (key[KEY_4]) v &= ~0x10;\r\n            if (key[KEY_5]) v &= ~0x08;\r\n            if (key[KEY_6]) v &= ~0x04;\r\n            if (key[KEY_7]) v &= ~0x02;\r\n            if (key[KEY_8]) v &= ~0x01;\r\n            return (v);\r\n        }\r\n        // [Arcade] Dipswitches\r\n    case 0x50:\r\n        {\r\n            u8 v = 0xFF;\r\n            IO_LOG_READ();\r\n            if (key[KEY_Q]) v &= ~0x80;\r\n            if (key[KEY_W]) v &= ~0x40;\r\n            if (key[KEY_E]) v &= ~0x20;\r\n            if (key[KEY_R]) v &= ~0x10;\r\n            if (key[KEY_T]) v &= ~0x08;\r\n            if (key[KEY_Y]) v &= ~0x04;\r\n            if (key[KEY_U]) v &= ~0x02;\r\n            if (key[KEY_I]) v &= ~0x01;\r\n            return (v);\r\n        }\r\n        */\r\n    }\r\n\r\n#ifdef DEBUG_IO\r\n    IO_LOG_READ();\r\n#endif\r\n\r\n    return (0xFF);\r\n}\r\n\r\n// I/O: Port output for SF-7000\r\nvoid Out_SF7000 (u16 Port, u8 Value)\r\n{\r\n    // 0x80..0xBF : VDP\r\n    if ((Port & 0xC0) == 0x80)\r\n    {\r\n        if (Port & 0x01)\r\n        {\r\n            // 0xBD,0xBF and odd addresses: VDP Address\r\n            Tms_VDP_Out_Address(Value);\r\n            return;\r\n        }\r\n        else\r\n        {\r\n            // 0xBE and even addresses: VDP Data\r\n            Tms_VDP_Out_Data(Value);\r\n            return;\r\n        }\r\n    }\r\n\r\n    switch (Port)\r\n    {\r\n        // 0x7E, 0x7F: SN76489 PSG\r\n    case 0x7E: case 0x7F: \r\n        SN76489_Write (Value); /* PSG_0_Write (Value); */ return;\r\n\r\n        // 0xDE: Keyboard Raster Port\r\n    case 0xDE: \r\n        sms.Input_Mode = Value; // & 7; // Upper bits needed for SK-1100 detection\r\n        return;\r\n\r\n        // SF-7000 Stuff -------------------------------------------------------------\r\n        //--[ FDC ]-------------------------------------------------------------------\r\n        // case 0xE0: /* Status */ return;\r\n    case 0xE1: FDC765_Data_Write (Value); return;\r\n        //--[ P.P.I. ]----------------------------------------------------------------\r\n        //case 0xE4: // FDC/Printer check\r\n        //    SF7000.Port_E4 = Value;\r\n        //    return;\r\n    case 0xE5: // Printer data output (parallel)\r\n        //SF7000.Port_E5 = Value;\r\n        return;\r\n    case 0xE6: // FDC/Printer control\r\n        SF7000.Port_E6 = Value;\r\n        SF7000_IPL_Mapping_Update();\r\n        if ((SF7000.Port_E6 & 0x03) == 0x03) // ???\r\n        {\r\n            // Reset Floppy Disk\r\n            FDC765_Reset();\r\n            // Need to trigger a NMI there ?\r\n            CPU_ForceNMI = TRUE;\r\n        }\r\n        return;\r\n    case 0xE7: // Control Register\r\n        SF7000.Port_E7 = Value;\r\n        if (!(Value & 0x80))\r\n        {\r\n            byte Mask = 1 << ((Value >> 1) & 0x07);\r\n            if (Value & 0x01)\r\n                SF7000.Port_E6 |= Mask;\r\n            else\r\n                SF7000.Port_E6 &= ~Mask;\r\n\r\n            if (Value & 0x04)\r\n            {\r\n                FDC765_Reset();\r\n                FDC765_Cmd_For_SF7000 = TRUE;\r\n            }\r\n        }\r\n\r\n        SF7000_IPL_Mapping_Update();\r\n        return;\r\n        //--[ USART 8251 ]------------------------------------------------------------\r\n    case 0xE8: SF7000.Port_E8 = Value; return;\r\n    case 0xE9: SF7000.Port_E9 = Value; return;\r\n    }\r\n\r\n#ifdef DEBUG_IO\r\n    IO_LOG_WRITE();\r\n#endif\r\n}\r\n\r\n// I/O: Port Input for SF-7000\r\nu8 In_SF7000 (word Port)\r\n{\r\n    // 0x80..0xBF : VDP\r\n    if ((Port & 0xC0) == 0x80)\r\n    {\r\n        if (Port & 0x01)\r\n            return Tms_VDP_In_Status();     // 0xBD,0xBF and odd addresses: VDP Status\r\n        else\r\n            return Tms_VDP_In_Data();       // 0xBE and even addresses: VDP Data\r\n    }\r\n\r\n    switch (Port /*& 0xFF*/)\r\n    {\r\n        // 0xC0/192 - 0xDC/220 : Joystick 1 Port -------------------------------------\r\n    case 0xC0:\r\n    case 0xDC: return (Input_Port_DC());\r\n\r\n        // 0xC1/193 - 0xDD/221 : Joystick 2 & LightGun Latch Port --------------------\r\n    case 0xC1:\r\n    case 0xDD: return (Input_Port_DD());\r\n\r\n        // 0xDE: Keyboard scan / printer / cassette ----------------------------------\r\n    case 0xDE: return sms.Input_Mode;\r\n\r\n        // SF-7000 Stuff -------------------------------------------------------------\r\n        //--[ FDC ]-------------------------------------------------------------------\r\n    case 0xE0: return FDC765_Status_Read();\r\n    case 0xE1: return FDC765_Data_Read();\r\n        //--[ P.P.I. ]----------------------------------------------------------------\r\n    case 0xE4: // FDC/Printer control\r\n        {\r\n            static int delay = 0x3200;      // FIXME\r\n            if (--delay <= 0)\r\n            {\r\n                delay = 0x3200;\r\n                SF7000.Port_E4 ^= 4;\r\n            }\r\n            return FDC765_Cmd_For_SF7000 | SF7000.Port_E4 /* & 4 */;\r\n        }\r\n    case 0xE5: // Printer data output (parallel)\r\n        return SF7000.Port_E5;\r\n    case 0xE6: // FDC/Printer control\r\n        return SF7000.Port_E6;\r\n    case 0xE7: /// Control Register\r\n        return SF7000.Port_E7;\r\n        //--[ USART ]-----------------------------------------------------------------\r\n    case 0xE8: return SF7000.Port_E8;\r\n    case 0xE9: return SF7000.Port_E9;\r\n    }\r\n\r\n#ifdef DEBUG_IO\r\n    IO_LOG_READ();\r\n#endif\r\n\r\n    return (0xFF);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/ioports.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - ioports.h\n// I/O Ports Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\n// Handlers pointers for the Z80 emulator\nextern byte    (*InZ80)   (register word Port);\nextern void    (*OutZ80)  (register word Port, register byte Value);\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nbyte    In_SMS     (word Port);\nvoid    Out_SMS    (word Port, byte Value);\nbyte    In_SF7000  (word Port);\nvoid    Out_SF7000 (word Port, byte Value);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/keyinfo.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - keysname.c\r\n// Keyboard Keys Names - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: may want to use hash tables to retrieve keys by scancode/name\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"keyinfo.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic const t_key_info  KeyInfo_Table [] =\r\n{\r\n    { ALLEGRO_KEY_A,            \"A\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_B,            \"B\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_C,            \"C\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_D,            \"D\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_E,            \"E\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_F,            \"F\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_G,            \"G\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_H,            \"H\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_I,            \"I\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_J,            \"J\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_K,            \"K\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_L,            \"L\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_M,            \"M\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_N,            \"N\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_O,            \"O\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_P,            \"P\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_Q,            \"Q\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_R,            \"R\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_S,            \"S\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_T,            \"T\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_U,            \"U\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_V,            \"V\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_W,            \"W\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_X,            \"X\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_Y,            \"Y\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_Z,            \"Z\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n\r\n    { ALLEGRO_KEY_0,            \"0\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_1,            \"1\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_2,            \"2\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_3,            \"3\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_4,            \"4\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_5,            \"5\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_6,            \"6\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_7,            \"7\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_8,            \"8\",             KEY_INFO_PRINTABLE                          },\r\n    { ALLEGRO_KEY_9,            \"9\",             KEY_INFO_PRINTABLE                          },\r\n\r\n    { ALLEGRO_KEY_PAD_0,        \"0 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_1,        \"1 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_2,        \"2 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_3,        \"3 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_4,        \"4 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_5,        \"5 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_6,        \"6 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_7,        \"7 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_8,        \"8 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_9,        \"9 (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n\r\n    { ALLEGRO_KEY_F1,           \"F1\",            0                                           },\r\n    { ALLEGRO_KEY_F2,           \"F2\",            0                                           },\r\n    { ALLEGRO_KEY_F3,           \"F3\",            0                                           },\r\n    { ALLEGRO_KEY_F4,           \"F4\",            0                                           },\r\n    { ALLEGRO_KEY_F5,           \"F5\",            0                                           },\r\n    { ALLEGRO_KEY_F6,           \"F6\",            0                                           },\r\n    { ALLEGRO_KEY_F7,           \"F7\",            0                                           },\r\n    { ALLEGRO_KEY_F8,           \"F8\",            0                                           },\r\n    { ALLEGRO_KEY_F9,           \"F9\",            0                                           },\r\n    { ALLEGRO_KEY_F10,          \"F10\",           0                                           },\r\n    { ALLEGRO_KEY_F11,          \"F11\",           0                                           },\r\n    { ALLEGRO_KEY_F12,          \"F12\",           0                                           },\r\n\r\n    { ALLEGRO_KEY_ESCAPE,       \"Escape\",        0                                           },\r\n    { ALLEGRO_KEY_TILDE,        \"Tilde\",         KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_MINUS,        \"Minus\",         KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_EQUALS,       \"Equals\",        KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_BACKSPACE,    \"Backspace\",                          KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_TAB,          \"Tab\",                                KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_OPENBRACE,    \"[\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_CLOSEBRACE,   \"]\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_ENTER,        \"Enter\",                              KEY_INFO_ALLOW_USE     },\r\n    //{ ALLEGRO_KEY_COLON,        \";\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // //??Semi Colon (;), not Colon (:)\r\n    { ALLEGRO_KEY_SEMICOLON,    \"Semicolon\",     KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // ?\r\n    { ALLEGRO_KEY_QUOTE,        \"'\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // Quote ('), not Double Quote (\")\r\n    { ALLEGRO_KEY_BACKSLASH,    \"\\\\\",            KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_BACKSLASH2,   \"\\\\\",            KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_COMMA,        \",\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_FULLSTOP,     \".\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // Stop is .\r\n    { ALLEGRO_KEY_SLASH,        \"/\",             KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_SPACE,        \"Space\",         KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_INSERT,       \"Insert\",                             KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_DELETE,       \"Delete\",                             KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_HOME,         \"Home\",                               KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_END,          \"End\",                                KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PGUP,         \"Page Up\",                            KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PGDN,         \"Page Down\",                          KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_LEFT,         \"Left\",                               KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_RIGHT,        \"Right\",                              KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_UP,           \"Up\",                                 KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_DOWN,         \"Down\",                               KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_SLASH,    \"/ (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_ASTERISK, \"* (Pad)\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n\r\n    { ALLEGRO_KEY_PAD_MINUS,    \"Minus (Pad)\",   KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_PLUS,     \"Plus (Pad)\",    KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_DELETE,   \". (Pad)\",                            KEY_INFO_ALLOW_USE     },\r\n    { 123,                      \". (Pad)\",                            KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAD_ENTER,    \"Enter (Pad)\",                        KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PRINTSCREEN,  \"Print Screen\",                       KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_PAUSE,        \"Pause\",         0                                           },\r\n    { ALLEGRO_KEY_ABNT_C1,      \"ABNT_C1\",                            KEY_INFO_ALLOW_USE     }, // ?\r\n    { ALLEGRO_KEY_YEN,          \"Yen\",                                KEY_INFO_ALLOW_USE     }, // Should be printable, if the font include the yen character\r\n    { ALLEGRO_KEY_KANA,         \"Kana\",                               KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_CONVERT,      \"Convert\",                            KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_NOCONVERT,    \"No Convert\",                         KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_AT,           \"At\",            KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_CIRCUMFLEX,   \"Circumflex\",    KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_COLON2,       \"Colon (2)\",     KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // ?\r\n    { ALLEGRO_KEY_KANJI,        \"Kanji\",                              KEY_INFO_ALLOW_USE     },\r\n\r\n    // Those are commented as 'MacOs' in Allegro's keyboard.h, yet I got KEY_SEMICOLON by pressing M on french keyboard...\r\n    { ALLEGRO_KEY_PAD_EQUALS,   \"Equal (Pad)\",   KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // ?\r\n    { ALLEGRO_KEY_BACKQUOTE,    \"Backquote\",     KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // ?\r\n    { ALLEGRO_KEY_SEMICOLON2,   \"Semicolon\",     KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // ?\r\n    { ALLEGRO_KEY_COMMAND,      \"Command\",       KEY_INFO_PRINTABLE | KEY_INFO_ALLOW_USE     }, // ?\r\n\r\n    { ALLEGRO_KEY_LSHIFT,       \"Left Shift\",                         KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_RSHIFT,       \"Right Shift\",                        KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_RCTRL,        \"Right Control\",                      KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_LCTRL,        \"Left Control\",                       KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_ALT,          \"Alt\",                                KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_ALTGR,        \"Alt GR\",                             KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_LWIN,         \"Left Win\",                           KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_RWIN,         \"Right Win\",                          KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_MENU,         \"Menu Win\",                           KEY_INFO_ALLOW_USE     },\r\n    { ALLEGRO_KEY_SCROLLLOCK,   \"Scroll Lock\",   0                                           },\r\n    { ALLEGRO_KEY_NUMLOCK,      \"Num Lock\",      0                                           },\r\n    { ALLEGRO_KEY_CAPSLOCK,     \"Caps Lock\",                          KEY_INFO_ALLOW_USE     },\r\n\r\n    { -1, NULL, 0 }\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nconst t_key_info *    KeyInfo_FindByScancode(int scancode)\r\n{\r\n    const t_key_info *ki = &KeyInfo_Table[0];\r\n    while (ki->scancode != -1)\r\n    {\r\n        if (ki->scancode == scancode)\r\n            return (ki);\r\n        ki++;\r\n    }\r\n    return (NULL);\r\n}\r\n\r\nconst t_key_info *    KeyInfo_FindByName(const char *name)\r\n{\r\n    const t_key_info *ki = &KeyInfo_Table[0];\r\n    while (ki->scancode != -1)\r\n    {\r\n        if (stricmp(ki->name, name) == 0)\r\n            return (ki);\r\n        ki++;\r\n    }\r\n    return (NULL);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/keyinfo.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - keysname.h\n// Keyboard Keys Names - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define KEY_INFO_PRINTABLE    (0x01)\n#define KEY_INFO_ALLOW_USE    (0x02)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_key_info\n{\n    int         scancode;\n    const char *name;\n    int         flags;\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nconst t_key_info *    KeyInfo_FindByScancode(int scancode);\nconst t_key_info *    KeyInfo_FindByName(const char *name);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/libmisc.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - LIBMY.C\r\n// Various helper functions - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: many of those functions are now useless, outdated or not efficient\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nunsigned short *StrCpyU16(unsigned short *s1, unsigned short *s2)\r\n{\r\n    unsigned short  *r = s1;\r\n\r\n    while (*s2)\r\n        *s1++ = *s2++;\r\n    *s1 = EOSTR;\r\n    return (r);\r\n}\r\n\r\nint     StrLenU16(const unsigned short *s)\r\n{\r\n    int    i = 0;\r\n    while (*s++)\r\n        i++;\r\n    return (i);\r\n}\r\n\r\nchar   *StrNDup(const char *src, int n)\r\n{\r\n    int    n2;\r\n    char  *ret, *dst;\r\n\r\n    n2 = strlen (src);\r\n    if (n2 < n)\r\n        n = n2;\r\n    ret = dst = (char*)malloc (sizeof (char) * (n + 1));\r\n    while (*src && n --)\r\n        *dst++ = *src++;\r\n    *dst = EOSTR;\r\n    return (ret);\r\n}\r\n\r\nunsigned short   *StrDupToU16(const char *src)\r\n{\r\n    u16* ret = (u16*)malloc (sizeof (unsigned short) * (strlen (src) + 1));\r\n    u16* dst = ret;\r\n    while (*src)\r\n    {\r\n        *dst++ = *src++;\r\n    }\r\n    *dst = EOSTR;\r\n    return (ret);\r\n}\r\n\r\nunsigned short   *StrNDupToU16(const char *src, int n)\r\n{\r\n    int n2 = strlen (src);\r\n    if (n2 < n)\r\n        n = n2;\r\n    u16* ret = (u16*)malloc (sizeof (unsigned short) * (n + 1));\r\n    u16* dst = ret;\r\n    while (*src && n --)\r\n    {\r\n        *dst++ = *src++;\r\n    }\r\n    *dst = EOSTR;\r\n    return (ret);\r\n}\r\n\r\nvoid    StrWriteBitfield(int v, int n_bits, char* out_field)\r\n{\r\n    char* p = out_field;\r\n\r\n    for (int bit_idx = n_bits-1; bit_idx >= 0; bit_idx--)\r\n    {\r\n        *p++ = (v & (1 << bit_idx)) ? '1' : '0';\r\n        if (bit_idx != 0 && (bit_idx & 7) == 0)\r\n            *p++ = '.';\r\n    }\r\n    *p = EOSTR;\r\n}\r\n\r\nbool    StrIsNull(const char *s)\r\n{\r\n    if (s == 0 || *s == EOSTR)\r\n        return true;\r\n    return false;\r\n}\r\n\r\nvoid    StrUpper(char *s)\r\n{\r\n    char c;\r\n    while ((c = *s) != 0)\r\n    {\r\n        if (c >= 'a' && c <= 'z')\r\n        {\r\n            c = c - 'a' + 'A';\r\n            *s = c;\r\n        }\r\n        s++;\r\n    }\r\n}\r\n\r\nvoid    StrLower(char *s)\r\n{\r\n    char c;\r\n    while ((c = *s) != 0)\r\n    {\r\n        if (c >= 'A' && c <= 'Z')\r\n        {\r\n            c = c - 'A' + 'a';\r\n            *s = c;\r\n        }\r\n        s++;\r\n    }\r\n}\r\n\r\nvoid StrReplace (char *s, char c1, char c2)\r\n{\r\n    while (*s)\r\n    {\r\n        if (*s == c1)\r\n            *s = c2;\r\n        s++;\r\n    }\r\n}\r\n\r\nint StrMatch (const char *src, const char *wildcards)\r\n{\r\n    int nbr = 0;\r\n    for (int val = 0; ; val++)\r\n    {\r\n        if (wildcards[val] == '*')\r\n        {\r\n            int i = 0;\r\n            do\r\n            {\r\n                nbr = nbr + StrMatch(src + val + i, wildcards + val + 1);\r\n                i++;\r\n            }\r\n            while (src[val + i - 1] != EOSTR);\r\n            return (nbr);\r\n        }\r\n        else\r\n        {\r\n            if (wildcards[val] != src[val])\r\n                return (0);\r\n            if (wildcards[val] == EOSTR)\r\n                return (1);\r\n        }\r\n    }\r\n}\r\n\r\nvoid    StrChomp (char *s)\r\n{\r\n    int   last;\r\n\r\n    last = strlen(s) - 1;\r\n    while (last >= 0 && (s[last] == '\\n' || s[last] == '\\r'))\r\n    {\r\n        s[last] = EOSTR;\r\n        last -= 1;\r\n    }\r\n}\r\n\r\nvoid    StrTrim (char *s)\r\n{\r\n    char * s1 = s;\r\n    char * s2 = s;\r\n    while (*s2 == ' ' || *s2 == '\\t')\r\n        s2++;\r\n    if (s1 != s2)\r\n    {\r\n        while (*s2 != EOSTR)\r\n            *s1++ = *s2++;\r\n        *s1 = EOSTR;\r\n    }\r\n    StrTrimEnd(s);\r\n}\r\n\r\nvoid     StrTrimEnd(char *s)\r\n{\r\n    int i = strlen(s) - 1;\r\n    while (i > 0 && (s[i] == ' ' || s[i] == '\\t'))\r\n    {\r\n        s[i] = EOSTR;\r\n        i--;\r\n    }\r\n}\r\n\r\nvoid    StrRemoveBlanks(char *s)\r\n{\r\n    char *dst;\r\n\r\n    dst = s;\r\n    while (*s != EOSTR)\r\n    {\r\n        if (*s == ' ' || *s == '\\t')\r\n            s++;\r\n        else\r\n            *dst++ = *s++;\r\n    }\r\n    *dst = EOSTR;\r\n}\r\n\r\n//\r\n// Linked List Library\r\n// 1999-2001\r\n// FIXME: shit\r\n//\r\n\r\nvoid        list_add(t_list **list, void *elem)\r\n{\r\n    t_list* item = (t_list*)malloc(sizeof (t_list));\r\n    item->elem = elem;\r\n    item->next = *list;\r\n    *list = item;\r\n}\r\n\r\nvoid        list_add_to_end(t_list **list, void *elem)\r\n{\r\n    t_list* item = (t_list*)malloc(sizeof (t_list));\r\n    item->elem = elem;\r\n    item->next = 0;\r\n    if (*list == 0)\r\n    {\r\n        // List is empty, stick on the beginning\r\n        *list = item;\r\n    }\r\n    else\r\n    {\r\n        // Get to end of list (slow) to add element\r\n        t_list *list2 = *list;\r\n        while (list2->next)\r\n            list2 = list2->next;\r\n        list2->next = item;\r\n    }\r\n}\r\n\r\nvoid        list_free(t_list **list)\r\n{\r\n    while (*list)\r\n    {\r\n        t_list* next = (*list)->next;\r\n        free((*list)->elem);\r\n        free(*list);\r\n        *list = next;\r\n    }\r\n}\r\n\r\nvoid        list_free_no_elem(t_list **list)\r\n{\r\n    while (*list)\r\n    {\r\n        t_list* next = (*list)->next;\r\n        free(*list);\r\n        *list = next;\r\n    }\r\n}\r\n\r\nvoid            list_free_custom(t_list **list, void (*custom_free)(void *))\r\n{\r\n    while (*list)\r\n    {\r\n        t_list* next = (*list)->next;\r\n        if (custom_free != 0)\r\n        {\r\n            void *elem = (*list)->elem;\r\n            custom_free(elem);\r\n        }\r\n        free(*list);\r\n        *list = next;\r\n    }\r\n}\r\n\r\nvoid            list_remove(t_list **list, void *elem)\r\n{\r\n    t_list* elem_prev = 0;\r\n    t_list* save = *list;\r\n    while (*list)\r\n    {\r\n        if ((*list)->elem == elem)\r\n        {\r\n            t_list* tmp = *list;\r\n            *list = (*list)->next;\r\n            free(tmp);\r\n            if (!elem_prev)\r\n                save = *list;\r\n            else\r\n                elem_prev->next = *list;\r\n        }\r\n        if ((elem_prev = *list))\r\n            *list = (*list)->next;\r\n    }\r\n    *list = save;\r\n}\r\n\r\nvoid    list_reverse(t_list **list)\r\n{\r\n    if (*list == 0)\r\n        return;\r\n    t_list* src = 0;\r\n    while ((*list)->next)\r\n    {\r\n        t_list* dest = (*list)->next;\r\n        (*list)->next = src;\r\n        src = *list;\r\n        *list = dest;\r\n    }\r\n    (*list)->next = src;\r\n}\r\n\r\nint     list_size(const t_list *list)\r\n{\r\n    int cnt = 0;\r\n    while (list)\r\n    {\r\n        cnt++;\r\n        list = list->next;\r\n    }\r\n    return (cnt);\r\n}\r\n\r\nvoid    list_sort(t_list **list, int (*fct)(void *elem1, void *elem2))\r\n{\r\n    t_list* i = *list;\r\n    while (i)\r\n    {\r\n        t_list* j = i->next;\r\n        while (j)\r\n        {\r\n            if (fct(i->elem, j->elem) >= 0)\r\n            {\r\n                void* temp = i->elem;\r\n                i->elem = j->elem;\r\n                j->elem = temp;\r\n            }\r\n            j = j->next;\r\n        }\r\n        i = i->next;\r\n    }\r\n}\r\n"
  },
  {
    "path": "meka/srcs/libmisc.h",
    "content": "//\r\n// Meka - LIBMY.H\r\n// Various functions - Headers and Constants\r\n//\r\n\r\n#ifndef _LIB_MISC_H_\r\n#define _LIB_MISC_H_\r\n\r\n#define EOSTR                   (0)\r\n\r\nunsigned short* StrCpyU16       (unsigned short *s1, unsigned short *s2);\r\nunsigned short* StrDupToU16     (const char *src);\r\nunsigned short* StrNDupToU16    (const char *src, int n);\r\nint             StrLenU16       (const unsigned short *s);\r\n\r\nvoid    StrWriteBitfield        (int v, int bit_count, char* out_buf);\r\n\r\nchar*   StrNDup                 (const char *src, int n);\r\nbool    StrIsNull               (const char *s);\r\nvoid    StrReplace              (char *s, char c1, char c2);\r\nvoid    StrUpper                (char *s);\r\nvoid    StrLower                (char *s);\r\n\r\nint     StrMatch                (const char *src, const char *wildcards);\r\nvoid    StrChomp                (char *s);\r\nvoid    StrTrim                 (char *s);\r\nvoid    StrTrimEnd              (char *s);\r\nvoid    StrRemoveBlanks         (char *s);\r\n\r\n//\r\n// Linked List Library\r\n// 1999-2001\r\n// FIXME: shit\r\n//\r\n\r\nstruct t_list\r\n{\r\n    t_list *    next;\r\n    void *      elem;\r\n};\r\n\r\nvoid    list_add(t_list **list, void *elem);\r\nvoid    list_add_to_end(t_list **list, void *elem);\r\n\r\nvoid    list_free(t_list **list);           // Free a list, call free() on all elements\r\nvoid    list_free_no_elem(t_list **list);   // Free a list, do not free elements (should be done by the program)\r\ntypedef void (*t_list_free_handler)(void*);\r\ntypedef int (*t_list_cmp_handler)(void *, void *);\r\nvoid    list_free_custom(t_list **list, void (*custom_free)(void*));\r\n\r\nvoid    list_remove(t_list **list, void *elem);\r\nvoid    list_reverse(t_list **list);\r\nint     list_size(const t_list *list);\r\nvoid    list_sort(t_list **list, int (*fct)(void *elem1, void *elem2));\r\n\r\n#endif\r\n"
  },
  {
    "path": "meka/srcs/libparse.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// Parsing helper functions\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include <string.h>\r\n#include <stdlib.h>\r\n#include <ctype.h>\r\n#include \"libparse.h\"\r\n\r\n#ifndef FALSE\r\n#define FALSE   0\r\n#endif\r\n#ifndef  TRUE\r\n#define TRUE    1\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// parse_trim_trailing_spaces(char *s)\r\n// Trim trailing spaces by writing an end-of-string marker\r\n//-----------------------------------------------------------------------------\r\nvoid        parse_trim_trailing_spaces (char *s)\r\n{\r\n    int     i;\r\n    i = strlen(s) - 1;\r\n    while (i >= 0 && isspace((unsigned char)s[i])) // u8 needed because of accentued characters in MEKA.MSG and isspace asserting\r\n        s[i--] = EOSTR;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// parse_skip_spaces(char **src)\r\n// Skip all spaces in pointed string\r\n//-----------------------------------------------------------------------------\r\nvoid        parse_skip_spaces(char **src)\r\n{\r\n    char    c;\r\n    while ((c = **src) == ' ' || c == '\\t')\r\n        (*src) ++;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Retrieve next word, as delimited by the given set of separators,\r\n// into given location, with maximum length, starting at given pointed string.\r\n// Increase pointed string source.\r\n// If no location is given, automatically allocate result.\r\n//-----------------------------------------------------------------------------\r\n// Note: In case of repeated separators (eg: \",,,,\", it doesn't return NULL \r\n// but empty strings. NULL is returned at end of source pointed string.\r\n//-----------------------------------------------------------------------------\r\nchar *      parse_getword(char *dst, int dst_len, char **src, const char *separators, char comment_char, t_parse_flags flags)\r\n{\r\n    char *  p;\r\n    int     inhibit;\r\n    char    c;\r\n    char *  dst_write;\r\n\r\n    // If dst is NULL, we have to allocate ourself\r\n    if (dst == NULL)\r\n    {\r\n        dst_len = 0;\r\n        inhibit = FALSE;\r\n        for (p = *src; (c = *p) != EOSTR; p++)\r\n        {\r\n            if (!inhibit)\r\n            {\r\n                if (strchr (separators, c))\r\n                    break;\r\n                if (c == comment_char)\r\n                    break;\r\n                if (c == '\\\\')\r\n                {\r\n                    inhibit = TRUE;\r\n                    continue;\r\n                }\r\n            }\r\n            dst_len++;\r\n            inhibit = FALSE;\r\n        }\r\n        if (dst_len == 0 && (*p == EOSTR || *p == comment_char))\r\n            return (NULL);\r\n        dst_len++; // for \\0 storage\r\n        dst = (char*)malloc(sizeof (char) * dst_len);\r\n    }\r\n\r\n    // Copy word until separator or end-of-string is found. Handle \\ inhibitor.\r\n    dst_write = dst;\r\n    inhibit = FALSE;\r\n    for (p = *src; (c = *p) != EOSTR; p++)\r\n    {\r\n        if (!inhibit)\r\n        {\r\n            if (strchr (separators, c))\r\n                break;\r\n            if (c == comment_char)\r\n                break;\r\n            if (c == '\\\\')\r\n            {\r\n                inhibit = TRUE;\r\n                continue;\r\n            }\r\n        }\r\n        if (dst_write - dst == dst_len)\r\n            break;\r\n        if (inhibit)\r\n        {\r\n            if (c == 'n')\r\n                c = '\\n';\r\n            else if (c == 't')\r\n                c = '\\t';\r\n        }\r\n        *dst_write++ = c;\r\n        inhibit = FALSE;\r\n    }\r\n    *dst_write = EOSTR;\r\n\r\n    // Set new source pointer\r\n    if (flags & PARSE_FLAGS_DONT_EAT_SEPARATORS)\r\n        *src = p;\r\n    else\r\n        *src = (*p == EOSTR || *p == comment_char) ? p : p + 1;\r\n\r\n    // Return NULL at end of string\r\n    if (dst_write - dst == 0 && (*p == EOSTR || *p == comment_char))\r\n        return (NULL);\r\n\r\n    // Trim trailing spaces\r\n    parse_trim_trailing_spaces(dst);\r\n\r\n    return (dst);\r\n}\r\n\r\nchar *      parse_escape_string(const char *src, const char *escape_chars)\r\n{\r\n    char *  p;\r\n    char *  dst;\r\n    char    c;\r\n    int     count;\r\n    int     src_length;\r\n\r\n    // Default escape characters\r\n    if (escape_chars == NULL)\r\n        escape_chars = PARSE_ESCAPE_CHARACTERS_DEFAULT;\r\n\r\n    // Count characters to escape\r\n    count = 0;\r\n    for (src_length = 0; (c = src[src_length]) != '\\0'; src_length++)\r\n    {\r\n        if (strchr(escape_chars, c) != NULL)\r\n            count++;\r\n    }\r\n\r\n    // If none, return NULL\r\n    if (count == 0)\r\n        return NULL;\r\n\r\n    dst = (char*)malloc(sizeof(char) * (src_length + count + 1));\r\n    p = dst;\r\n    while ((c = *src++) != '\\0')\r\n    {\r\n        if (strchr(escape_chars, c) != NULL)\r\n        {\r\n            *p++ = '\\\\';\r\n            //count--;\r\n        }\r\n        *p++ = c;\r\n    }\r\n    *p = '\\0';\r\n\r\n    return (dst);\r\n}\r\n\r\nchar *      parse_unescape_string(const char *src, const char *escape_chars)\r\n{\r\n    char *  dst;\r\n    char *  p;\r\n    char    c;\r\n    int     src_length;\r\n\r\n    // Default escape characters\r\n    if (escape_chars == NULL)\r\n        escape_chars = PARSE_ESCAPE_CHARACTERS_DEFAULT;\r\n\r\n    // Make it easier, allocate same as source length\r\n    src_length = strlen(src);\r\n    dst = (char*)malloc(sizeof(char) * (src_length + 1));\r\n    p = dst;\r\n\r\n    // Copy\r\n    while ((c = *src++) != '\\0')\r\n    {\r\n        if (strchr(escape_chars, c) != NULL)\r\n        {\r\n            c = *src++;\r\n            if (c == '\\0')  // FIXME: not exact behavior, but at least we're safe here\r\n                break;\r\n        }\r\n        *p++ = c;\r\n    }\r\n    *p = '\\0';\r\n\r\n    return (dst);\r\n}\r\n\r\nt_tfile *       tfile_read(const char *filename)\r\n{\r\n    // Open and file\r\n    FILE* f;\r\n    if ((f = fopen(filename, \"rb\")) == NULL)\r\n    { \r\n        meka_errno = MEKA_ERR_FILE_OPEN; \r\n        return NULL; \r\n    }\r\n\r\n    // Gets its size\r\n    int size;\r\n    if (fseek(f, 0, SEEK_END) != 0 || (size = ftell(f)) == -1 || fseek(f, 0, SEEK_SET) != 0)\r\n    { \r\n        meka_errno = MEKA_ERR_FILE_READ; \r\n        return NULL; \r\n    }\r\n\r\n    // Allocate the t_tfile and read file data into to\r\n    t_tfile* tf = (t_tfile*)malloc(sizeof (t_tfile));\r\n    tf->size = size;\r\n    tf->data_raw = (char*)malloc(sizeof (char) * size + 1);\r\n    tf->data_lines = NULL;\r\n\r\n    if (fread(tf->data_raw, sizeof (char), size, f) < (unsigned int)size)\r\n    { \r\n        meka_errno = MEKA_ERR_FILE_READ; \r\n        tfile_free(tf);\r\n        return NULL; \r\n    }\r\n    tf->data_raw[size] = EOSTR;\r\n    fclose(f);\r\n\r\n    // Silently ignore UTF-8 header (for meka.nam)\r\n    char* p_cur = tf->data_raw;\r\n    if ((u8)p_cur[0] == 0xEF && (u8)p_cur[1] == 0xBB && (u8)p_cur[2] == 0xBF)\r\n        p_cur += 3;\r\n\r\n    // Parse raw data to create the lines list\r\n    int lines_count = 0;\r\n    char* p_new;\r\n    while ((p_new = strchr(p_cur, '\\n')) != NULL)\r\n    {\r\n        *p_new = EOSTR;\r\n        StrChomp(p_cur);\r\n        list_add_to_end(&tf->data_lines, p_cur);\r\n        lines_count++;\r\n        p_cur = p_new + 1;\r\n    }\r\n\r\n    // Handle last line case\r\n    if (p_cur < tf->data_raw + tf->size)\r\n    {\r\n        list_add_to_end(&tf->data_lines, p_cur);\r\n        lines_count++;\r\n    }\r\n    tf->data_lines_count = lines_count;\r\n\r\n    // OK\r\n    meka_errno = MEKA_ERR_OK;\r\n    return (tf);\r\n}\r\n\r\nvoid            tfile_free(t_tfile *tf)\r\n{\r\n    list_free_no_elem(&tf->data_lines);\r\n    free(tf->data_raw);\r\n    free(tf);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/libparse.h",
    "content": "//-----------------------------------------------------------------------------\r\n// Parsing helper functions\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n#define PARSE_ESCAPE_CHARACTERS_DEFAULT     \"\\\"\\\\;\" // \" \\ ;\r\n\r\nenum t_parse_flags\r\n{\r\n    PARSE_FLAGS_NONE                    = 0,\r\n    PARSE_FLAGS_DONT_EAT_SEPARATORS     = 0x0001,\r\n    //PARSE_FLAGS_STRING_INHIBIT        = 0x0002    // FIXME: TODO. \"\" enclosed string is inhibited\r\n};\r\n\r\n// Text file\r\nstruct t_tfile\r\n{\r\n    int           size;\r\n    char *        data_raw;\r\n    t_list *      data_lines;\r\n    int           data_lines_count;\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nt_tfile *   tfile_read(const char *filename);\r\nvoid        tfile_free(t_tfile *tf);\r\n\r\nvoid        parse_trim_trailing_spaces  (char *s);\r\nvoid        parse_skip_spaces           (char **src);\r\nchar *      parse_getword               (char *dst, int dst_len, char **src, const char *separators, char comment_char, t_parse_flags flags = PARSE_FLAGS_NONE);\r\n\r\nchar *      parse_escape_string         (const char *src, const char *escape_chars);\r\nchar *      parse_unescape_string       (const char *src, const char *escape_chars);\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/lightgun.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - lightgun.c\r\n// Light Phaser Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"beam.h\"\r\n#include \"lightgun.h\"\r\n#include \"glasses.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_light_phaser          LightPhaser;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    LightPhaser_Init()\r\n{\r\n    LightPhaser.Enabled = FALSE;\r\n    LightPhaser.LastSync = 0;\r\n    LightPhaser.X[PLAYER_1] = LightPhaser.X[PLAYER_2] = SMS_RES_X / 2;\r\n    LightPhaser.Y[PLAYER_1] = LightPhaser.Y[PLAYER_2] = SMS_RES_Y / 2;\r\n    LightPhaser.EmuFunc = LIGHTPHASER_EMU_FUNC_DEFAULT;\r\n}\r\n\r\nu8      LightPhaser_GetX()\r\n{\r\n    const int r = LightPhaser.X[LightPhaser.LastSync];\r\n\r\n    // FIXME-2019: This is terribly broken and incorrect, needs to be redone from scratch nicely, \r\n    // - with a first layer of correct emulation\r\n    // - and a secondary layer of per-game hacks to improve gameplay quality\r\n    switch (LightPhaser.EmuFunc)\r\n    {\r\n    case LIGHTPHASER_EMU_FUNC_DEFAULT:\r\n        return (u8)(16 + (r / 2));\r\n    case LIGHTPHASER_EMU_FUNC_MISSILE_DEFENSE_3D:\r\n        return (u8)(16 + 6 + (r / 2));\r\n    case LIGHTPHASER_EMU_FUNC_3DGUNNER:\r\n        if (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT)\r\n            return (u8)(16 + 9 + (r / 2));\r\n        if (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_RIGHT)\r\n            return (u8)(16 + (r / 2));\r\n        return (u8)(16 + 4 + (r / 2));\r\n    }\r\n    assert(0);\r\n    return 0;\r\n}\r\n\r\n// FIXME: This old-fashioned code is incorrect. Light Phaser should be\r\n// emulated using TH bit correctly and horizontal latch.\r\nvoid    LightPhaser_Sync(int player, byte *v)\r\n{\r\n    *v |= ((player == PLAYER_1) ? 0x40 : 0x80);\r\n    const int dx = LightPhaser.X[player] - Beam_Calc_X();\r\n    const int dy = LightPhaser.Y[player] - tsms.VDP_Line;\r\n\r\n    if (dy > -4 && dy < 4)\r\n    {\r\n        // Arbitrary values found after trying different settings\r\n        if (dx > -48 && dx < 48)\r\n        {\r\n            *v &= (player == PLAYER_1) ? ~0x40 : ~0x80;\r\n            LightPhaser.LastSync = player;\r\n        }\r\n    }\r\n}\r\n\r\n// Light Phaser update function\r\n// This is supposed to work with an analog mouse\r\n// Fullscreen mode should be enabled to work properly\r\nvoid    LightPhaser_Update(int player, int device_x, int device_y)\r\n{\r\n    LightPhaser.X[player] = device_x;\r\n    LightPhaser.Y[player] = device_y;\r\n    // LightGun_X = ((mouse_x + 28 + ((256 - mouse_x) >> 5)) & 0xFF) >> 1;\r\n    // LightGun_Y = mouse_y + 1;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/lightgun.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - lightgun.h\n// Light Phaser Emulation - Headers\n//-----------------------------------------------------------------------------\n\n// Hard-coded Light-phaser function to reduce mismatch between user cursor\nenum t_lightphaser_emu_func\n{\n    LIGHTPHASER_EMU_FUNC_DEFAULT = 0,\n    LIGHTPHASER_EMU_FUNC_MISSILE_DEFENSE_3D = 1,\n    LIGHTPHASER_EMU_FUNC_3DGUNNER = 2\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    LightPhaser_Init();\nvoid    LightPhaser_Sync(int player, byte *);\nvoid    LightPhaser_Update(int player, int device_x, int device_y);\nu8      LightPhaser_GetX();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_light_phaser\n{\n    bool    Enabled;        // Set if has least one Light Phaser is now enabled\n    int     LastSync;\n    u8      X[2];\n    u8      Y[2];\n    t_lightphaser_emu_func  EmuFunc;\n};\n\nextern t_light_phaser  LightPhaser;\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/machine.cpp",
    "content": "\r\n// MEKA - machine.c\r\n// Emulated Machines Initialization - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"bios.h\"\r\n#include \"coleco.h\"\r\n#include \"commport.h\"\r\n#include \"db.h\"\r\n#include \"debugger.h\"\r\n#include \"eeprom.h\"\r\n#include \"glasses.h\"\r\n#include \"mappers.h\"\r\n#include \"palette.h\"\r\n#include \"sf7000.h\"\r\n#include \"sg1ksc3k.h\"\r\n#include \"vdp.h\"\r\n#include \"video.h\"\r\n#include \"vmachine.h\"\r\n#include \"tvoekaki.h\"\r\n#include \"tvtype.h\"\r\n#include \"sound/fmunit.h\"\r\n#include \"sound/psg.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nint g_machine_pause_requests = 0;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Machine_Pause()\r\n{\r\n    g_machine_flags ^= MACHINE_PAUSED;\r\n    CPU_Loop_Stop = TRUE;\r\n    if (g_machine_pause_requests > 0)\r\n        g_machine_pause_requests--;\r\n\r\n    // Verbose\r\n    if (g_machine_flags & MACHINE_PAUSED)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Machine_Pause));\r\n        // gui_menu_check (menus_ID.machine, 2);\r\n        Screen_Save_to_Next_Buffer();\r\n    }\r\n    else\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Machine_Resume));\r\n        // gui_menu_uncheck_range(menus_ID.machine, 2, 2);\r\n    }\r\n}\r\n\r\nvoid    Machine_Debug_Start()\r\n{\r\n    // Msg(MSGT_DEBUG, \"Machine_Debug_Start()\");\r\n    g_machine_flags |= MACHINE_PAUSED | MACHINE_DEBUGGING;\r\n    CPU_Loop_Stop = TRUE;\r\n    Screen_Save_to_Next_Buffer();\r\n}\r\n\r\nvoid    Machine_Debug_Stop()\r\n{\r\n    // Msg(MSGT_DEBUG, \"Machine_Debug_Stop()\");\r\n    g_machine_flags &= ~(MACHINE_PAUSED | MACHINE_DEBUGGING);\r\n    // next pass in MainLoop() will restart CPU emulation\r\n    // We however set the flag in case this function is called with emulation\r\n    // is already running (eg: setting a breakpoint while running)\r\n    CPU_Loop_Stop = TRUE;\r\n}\r\n\r\n// Note: called everytime we change video mode.\r\nvoid    Machine_Set_Handler_Loop()\r\n{\r\n    switch (g_driver->id)\r\n    {\r\n    case DRV_COLECO:                   LoopZ80 = Loop_Coleco;          return;\r\n    case DRV_SG1000: case DRV_SC3000:  LoopZ80 = Loop_SG1000_SC3000;   return;\r\n    case DRV_SF7000:                   LoopZ80 = Loop_SG1000_SC3000;   return;\r\n    default:                           LoopZ80 = Loop_SMS;             return;\r\n    }\r\n}\r\n\r\nvoid    Machine_Set_Handler_IO()\r\n{\r\n    switch (g_driver->id)\r\n    {\r\n    case DRV_COLECO:\r\n        InZ80 = InZ80_NoHook = Coleco_Port_In;\r\n        OutZ80 = OutZ80_NoHook = Coleco_Port_Out;\r\n        // sms.Input_Mode = 1; // Useless since it is overwritten later\r\n        return;\r\n    case DRV_SF7000:\r\n        InZ80 = InZ80_NoHook = In_SF7000;\r\n        OutZ80 = OutZ80_NoHook = Out_SF7000;\r\n        return;\r\n    default:\r\n        InZ80 = InZ80_NoHook = In_SMS;\r\n        OutZ80 = OutZ80_NoHook = Out_SMS;\r\n        return;\r\n    }\r\n}\r\n\r\nvoid    Machine_Set_Handler_MemRW()\r\n{\r\n    RdZ80 = Read_Default;\r\n    WrZ80 = Write_Default;\r\n\r\n    switch (g_machine.mapper)\r\n    {\r\n    case MAPPER_SMS_NoMapper:            // SMS games with no bank switching\r\n        WrZ80 = Write_Mapper_SMS_NoMapper;\r\n        break;\r\n    case MAPPER_32kRAM:                  // Used by Sega Basic, The Castle, ..\r\n    case MAPPER_SC3000_Survivors_Multicart:\r\n        WrZ80 = Write_Mapper_32kRAM;\r\n        break;\r\n    case MAPPER_ColecoVision:            // Colecovision\r\n        WrZ80 = Write_Mapper_Coleco;\r\n        break;\r\n    case MAPPER_CodeMasters:             // CodeMasters games\r\n        WrZ80 = Write_Mapper_CodeMasters;\r\n        break;\r\n    case MAPPER_93c46:                   // Used by Game Gear baseball games\r\n        RdZ80 = Read_Mapper_93c46;\r\n        WrZ80 = Write_Mapper_93c46;\r\n        break;\r\n    case MAPPER_SG1000:                  // 4 kb of RAM\r\n        WrZ80 = Write_Mapper_SG1000;\r\n        break;\r\n    case MAPPER_SMS_ActionReplay:        // SMS Action Replay with embedded RAM\r\n        WrZ80 = Write_Mapper_SMS_ActionReplay;\r\n        break;\r\n    case MAPPER_TVOekaki:                // Terebi Oekaki Graphic Board\r\n        RdZ80 = Read_Mapper_TVOekaki;\r\n        WrZ80 = Write_Mapper_TVOekaki;\r\n        break;\r\n    case MAPPER_SF7000:                  // SF-7000\r\n        WrZ80 = Write_Mapper_SF7000;\r\n        break;\r\n    case MAPPER_SMS_Korean_A000:         // SMS Korean games with A000 register\r\n        WrZ80 = Write_Mapper_SMS_Korean_A000;\r\n        break;\r\n    case MAPPER_SMS_Korean_BFFC:         // SMS Korean games with BFFC register\r\n        WrZ80 = Write_Mapper_SMS_Korean_BFFC;\r\n        break;\r\n    case MAPPER_SMS_Korean_MSX_8KB_0003: // SMS Korean games with MSX-based 8KB mapper\r\n        WrZ80 = Write_Mapper_SMS_Korean_MSX_8KB_0003;\r\n        break;\r\n    case MAPPER_SMS_Korean_MSX_8KB_0300: // SMS Korean games with MSX-based 8KB mapper\r\n        WrZ80 = Write_Mapper_SMS_Korean_MSX_8KB_0300;\r\n        break;\r\n    case MAPPER_SMS_Korean_Janggun:      // SMS Korean Janggun-ui Adeul\r\n        RdZ80 = Read_Mapper_SMS_Korean_Janggun;\r\n        WrZ80 = Write_Mapper_SMS_Korean_Janggun;\r\n        break;\r\n    case MAPPER_SMS_4PakAllAction:\r\n        WrZ80 = Write_Mapper_SMS_4PakAllAction;\r\n        break;\r\n    case MAPPER_SMS_DisplayUnit:         // SMS Display Unit (RAM from 4000-47FF)\r\n        RdZ80 = Read_Mapper_SMS_DisplayUnit;\r\n        WrZ80 = Write_Mapper_SMS_DisplayUnit;\r\n        break;\r\n    case MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA:\r\n        RdZ80 = Read_Mapper_SG1000_Taiwan_MSX_Adapter_TypeA;\r\n        WrZ80 = Write_Mapper_SG1000_Taiwan_MSX_Adapter_TypeA;\r\n        break;\r\n    case MAPPER_SMS_Korean_FFFF_HiCom:\r\n        WrZ80 = Write_Mapper_SMS_Korean_FFFF_HiCom;\r\n        break;\r\n    case MAPPER_SMS_Korean_2000_xor_1F:\r\n        WrZ80 = Write_Mapper_SMS_Korean_2000_xor_1F;\r\n        break;\r\n    case MAPPER_SMS_Korean_FFFE:\r\n        WrZ80 = Write_Mapper_SMS_Korean_FFFE;\r\n        break;\r\n    case MAPPER_SMS_Korean_FFF3_FFFC:\r\n        WrZ80 = Write_Mapper_SMS_Korean_FFF3_FFFC;\r\n        break;\r\n    case MAPPER_SMS_Korean_0000_xor_FF:\r\n        WrZ80 = Write_Mapper_SMS_Korean_0000_xor_FF;\r\n        break;\r\n    case MAPPER_SMS_Korean_MD_FFF0:\r\n        WrZ80 = Write_Mapper_SMS_Korean_MD_FFF0;\r\n        break;\r\n    case MAPPER_SMS_Korean_MD_FFF5:\r\n        WrZ80 = Write_Mapper_SMS_Korean_MD_FFF5;\r\n        break;\r\n    case MAPPER_SMS_Korean_MD_FFFA:\r\n        WrZ80 = Write_Mapper_SMS_Korean_MD_FFFA;\r\n        break;\r\n    case MAPPER_SMS_Korean_MSX_32KB_2000:\r\n        WrZ80 = Write_Mapper_SMS_Korean_MSX_32KB_2000;\r\n        break;\r\n    case MAPPER_SMS_Korean_SMS_32KB_2000:\r\n        WrZ80 = Write_Mapper_SMS_Korean_SMS_32KB_2000;\r\n        break;\r\n    case MAPPER_SMS_Korean_MSX_SMS_8000:\r\n        WrZ80 = Write_Mapper_SMS_Korean_MSX_SMS_8000;\r\n        break;\r\n    case MAPPER_MSX_Generic16_8000:\r\n        WrZ80 = Write_Mapper_MSX_Generic16_8000;\r\n        break;\r\n    }\r\n\r\n    // Save the original handlers as \"NoHook\" versions\r\n    RdZ80_NoHook = RdZ80;\r\n    WrZ80_NoHook = WrZ80;\r\n}\r\n\r\nvoid        Machine_Set_Mapper()\r\n{\r\n    if (DB.current_entry != NULL && DB.current_entry->emu_mapper != -1)\r\n    {\r\n        g_machine.mapper = DB.current_entry->emu_mapper;\r\n        return;\r\n    }\r\n\r\n    // Select default mapper per driver\r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_SC3000:\r\n        if (tsms.Size_ROM <= 32*1024)\r\n            g_machine.mapper = MAPPER_32kRAM;       // FIXME: Not technically correct. Should be enabled for BASIC.\r\n        else\r\n            g_machine.mapper = MAPPER_SG1000;\r\n        if (DB.current_entry == NULL && tsms.Size_ROM >= 0x200000)\r\n            if (memcmp(ROM+0x1F8004, \"SC-3000 SURVIVORS MULTICART BOOT MENU\", 38) == 0)\r\n                g_machine.mapper = MAPPER_SC3000_Survivors_Multicart;\r\n        return;\r\n    case DRV_COLECO:\r\n        g_machine.mapper = MAPPER_ColecoVision;\r\n        return;\r\n    case DRV_SG1000:\r\n        g_machine.mapper = MAPPER_SG1000;\r\n        return;\r\n    case DRV_SF7000:\r\n        g_machine.mapper = MAPPER_SF7000;\r\n        return;\r\n    case DRV_SMS:\r\n    case DRV_GG:\r\n        if (tsms.Size_ROM <= 48*1024)\r\n            g_machine.mapper = MAPPER_SMS_NoMapper;\r\n        else\r\n            g_machine.mapper = MAPPER_Standard;\r\n        if (DB.current_entry == NULL)    // Detect mapper for unknown ROM\r\n        {\r\n            const int m = Mapper_Autodetect();\r\n            if (m != MAPPER_Auto)\r\n                g_machine.mapper = m;\r\n        }\r\n        return;\r\n    default: // All Others (which ?)\r\n        g_machine.mapper = MAPPER_Standard;\r\n        return;\r\n    }\r\n}\r\n\r\nvoid    Machine_Set_Mapping()\r\n{\r\n    sms.SRAM_Mapping_Register = 0;\r\n    sms.SRAM_Pages = 0;\r\n\r\n    g_machine.mapper_regs_count = 3;    // Default\r\n    for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n        g_machine.mapper_regs[i] = 0;\r\n    g_machine.mapper_regs[0] = 0;\r\n    g_machine.mapper_regs[1] = 1;\r\n    g_machine.mapper_regs[2] = 2;\r\n\r\n    switch (g_machine.mapper)\r\n    {\r\n    case MAPPER_32kRAM: // 32k RAM MAPPER --------------------------------------\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(4, 0);\r\n        Map_8k_RAM(5, 1);\r\n        Map_8k_RAM(6, 2);\r\n        Map_8k_RAM(7, 3);\r\n        break;\r\n    case MAPPER_ColecoVision: // COLECOVISION MAPPER ---------------------------\r\n        Map_8k_Other(0, BIOS_ROM_Coleco);\r\n        Map_8k_RAM(1, 1);\r\n        Map_8k_RAM(2, 1);\r\n        Map_8k_RAM(3, 0);\r\n        Map_8k_ROM(4, 0);\r\n        Map_8k_ROM(5, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(6, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(7, 3 & tsms.Pages_Mask_8k);\r\n        break;\r\n    case MAPPER_SMS_ActionReplay: // ACTION REPLAY MAPPER ----------------------\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 1);\r\n        Map_8k_RAM(2, 1);\r\n        Map_8k_RAM(3, 1);\r\n        Map_8k_RAM(4, 2); // FIXME\r\n        Map_8k_RAM(5, 2);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        break;\r\n    case MAPPER_SF7000: // SF-7000 ---------------------------------------------\r\n        Map_16k_Other(0, BIOS_ROM_SF7000);\r\n        Map_8k_RAM(2, 2);\r\n        Map_8k_RAM(3, 3);\r\n        Map_8k_RAM(4, 4);\r\n        Map_8k_RAM(5, 5);\r\n        Map_8k_RAM(6, 6);\r\n        Map_8k_RAM(7, 7);\r\n        break;\r\n    case MAPPER_SMS_DisplayUnit: // DISPLAY UNIT MAPPER ----------------------\r\n        Map_8k_ROM(0, 0);  // ROM\r\n        Map_8k_ROM(1, 1);\r\n        Map_8k_RAM(2, 1);  // RAM - Mapping 2k (0x800) from 4000 to BFFF\r\n        Map_8k_RAM(3, 1);\r\n        Map_8k_RAM(4, 1);\r\n        Map_8k_RAM(5, 1);\r\n        Map_8k_RAM(6, 0);  // RAM - Standard\r\n        Map_8k_RAM(7, 0);\r\n        break;\r\n    case MAPPER_SMS_Korean_MSX_8KB_0003:\r\n    case MAPPER_SMS_Korean_MSX_8KB_0300:\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 1);\r\n        Map_8k_ROM(2, 2);\r\n        Map_8k_ROM(3, 3);\r\n        Map_8k_ROM(4, 4);\r\n        Map_8k_ROM(5, 5);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 4;\r\n\r\n        // Nemesis has boot code on page 0x0F which seems to be auto-mapped at 0x0000-0x1fff on boot\r\n        // I'm not sure what is really \"correct\" but this work and doesn't trigger on other Zemina games for now.\r\n        if (g_machine.mapper == MAPPER_SMS_Korean_MSX_8KB_0003)\r\n            if (tsms.Size_ROM == 16*0x2000 && ROM[0] == 0x00 && ROM[1] == 0x00 && ROM[2] == 0x00 && ROM[15*0x2000+0] == 0xF3 && ROM[15*0x2000+1] == 0xED && ROM[15*0x2000+2] == 0x56)\r\n                Map_8k_ROM(0, 0x0F);\r\n        break;\r\n    case MAPPER_SMS_Korean_Janggun:\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 1);\r\n        Map_8k_ROM(2, 2);\r\n        Map_8k_ROM(3, 3);\r\n        Map_8k_ROM(4, 4);\r\n        Map_8k_ROM(5, 5);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 6;\r\n        g_machine.mapper_janggun_bytes_flipping_flags = 0x00;\r\n        break;\r\n\r\n    case MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA:\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_RAM(1, 0);\r\n        Map_8k_ROM(2, 2);\r\n        Map_8k_ROM(3, 3);\r\n        Map_8k_ROM(4, 4);\r\n        Map_8k_ROM(5, 5);\r\n        Map_8k_RAM(6, 1);\r\n        Map_8k_RAM(7, 1);\r\n        g_machine.mapper_regs_count = 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_FFFF_HiCom:\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0);\r\n        Map_8k_ROM(5, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_2000_xor_1F:\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 0);\r\n        Map_8k_ROM(2, 0x60 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 0x61 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0x62 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 0x63 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_FFFE:\r\n        Map_8k_ROM(0, 0x00 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 0x01 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 0x02 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 0x03 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0x3f & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 0x3f & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = (i == 0) ? 0x01 : 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_FFF3_FFFC:\r\n        Map_8k_ROM(0, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0xFF & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 0xFF & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 2;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_0000_xor_FF:\r\n        Map_8k_ROM(0, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        g_machine.mapper_regs[0] = 0xFF;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_MD_FFF0:\r\n        Map_8k_ROM(0, 0x00 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 0x01 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 0x02 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 0x03 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0x00 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 0x01 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 2;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        g_machine.mapper_regs[2] = 1;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_MD_FFF5:\r\n        Map_8k_ROM(0, 0x00 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 0x01 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 0x02 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 0x03 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0x02 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 0x03 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 2;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        g_machine.mapper_regs[1] = 1;\r\n        g_machine.mapper_regs[2] = 1;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_MD_FFFA:\r\n        Map_8k_ROM(0, 0x00 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 0x01 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 0x02 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 0x03 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0x00 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 0x01 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 3;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        g_machine.mapper_regs[2] = 1;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_MSX_32KB_2000:\r\n        Map_8k_ROM(0, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 4 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 5 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        g_machine.mapper_regs[0] = 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_SMS_32KB_2000:\r\n        Map_8k_ROM(0, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        break;\r\n\r\n    case MAPPER_SMS_Korean_MSX_SMS_8000:\r\n        Map_8k_ROM(0, 0x3c & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, 0x3c & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, 1 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, 0 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, 3 & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, 2 & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        break;\r\n\r\n    case MAPPER_SC3000_Survivors_Multicart:\r\n        g_machine.mapper_regs_count = 1;\r\n        for (int i = 0; i != MAPPER_REGS_MAX; i++)\r\n            g_machine.mapper_regs[i] = 0;\r\n        g_machine.mapper_regs[0] = 0xDF; // $11011111; // Menu\r\n        //Map_8k_ROM(0, g_machine.mapper_regs[0]*4+0);\r\n        //Map_8k_ROM(1, g_machine.mapper_regs[0]*4+1);// & tsms.Pages_Mask_8k);\r\n        //Map_8k_ROM(2, g_machine.mapper_regs[0]*4+2);// & tsms.Pages_Mask_8k);\r\n        //Map_8k_ROM(3, g_machine.mapper_regs[0]*4+3);// & tsms.Pages_Mask_8k);\r\n        Map_8k_RAM(4, 0);\r\n        Map_8k_RAM(5, 1);\r\n        Map_8k_RAM(6, 2);\r\n        Map_8k_RAM(7, 3);\r\n        Out_SMS(0xE0, g_machine.mapper_regs[0]);\r\n        break;\r\n\r\n    default: // Other mappers\r\n        Map_8k_ROM(0, 0);\r\n        Map_8k_ROM(1, 1);\r\n        Map_8k_ROM(2, 2);\r\n        Map_8k_ROM(3, 3);\r\n        Map_8k_ROM(4, 4);\r\n        Map_8k_ROM(5, 5);\r\n        Map_8k_RAM(6, 0);\r\n        Map_8k_RAM(7, 0);\r\n        switch (g_machine.mapper)\r\n        {\r\n        case MAPPER_SMS_NoMapper:\r\n            break;\r\n        case MAPPER_CodeMasters:\r\n            // ROM [0x3FFF] = 0; ROM [0x7FFF] = 1; ROM [0xBFFF] = 2;\r\n            break;\r\n        case MAPPER_SMS_Korean_A000:\r\n        case MAPPER_SMS_Korean_BFFC:\r\n        case MAPPER_SMS_4PakAllAction:\r\n            // ROM [0xA000] = 0;\r\n            break;\r\n        case MAPPER_93c46:\r\n            // RAM [0x1FFC] = 0; RAM [0x1FFD] = 0; RAM [0x1FFE] = 1; RAM [0x1FFF] = 2;\r\n            EEPROM_93c46_Init(EEPROM_93C46_INIT_ALL);\r\n            break;\r\n        case MAPPER_TVOekaki:\r\n            TVOekaki_Init();\r\n            break;\r\n        case MAPPER_MSX_Generic16_8000:\r\n            Map_16k_ROM(0, 0);\r\n            Map_16k_ROM(1, 0); // This is key to getting WonderKid working.\r\n            Map_16k_ROM(2, 0);\r\n            break;\r\n        default:\r\n            // RAM [0x1FFC] = 0; RAM [0x1FFD] = 0; RAM [0x1FFE] = 1; RAM [0x1FFF] = 2;\r\n            memcpy (Game_ROM_Computed_Page_0, ROM, 0x4000);\r\n            //Map_16k_Other (0, Game_ROM_Computed_Page_0);\r\n            Map_16k_ROM(0, 0);  // Mapping may change to Game_ROM_Computed_Page_0 at runtime\r\n            break;\r\n        }\r\n        break;\r\n    }\r\n}\r\n\r\nvoid    Machine_Set_Country()\r\n{\r\n    if (DB.current_entry && DB.current_entry->emu_country != -1)\r\n        sms.Country = DB.current_entry->emu_country;\r\n    else\r\n        sms.Country = g_config.country;\r\n}\r\n\r\nvoid    Machine_Set_IPeriod()\r\n{\r\n    if (DB.current_entry && DB.current_entry->emu_iperiod != -1)\r\n    {\r\n        opt.Cur_IPeriod = DB.current_entry->emu_iperiod;\r\n        return;\r\n    }\r\n\r\n    switch (g_driver->id)\r\n    {\r\n    case DRV_COLECO:\r\n        opt.Cur_IPeriod = opt.IPeriod_Coleco;\r\n        break;\r\n    case DRV_SG1000:\r\n    case DRV_SC3000:\r\n    case DRV_SF7000:\r\n        opt.Cur_IPeriod = opt.IPeriod_Sg1000_Sc3000;\r\n        break;\r\n    default:\r\n        opt.Cur_IPeriod = opt.IPeriod;\r\n        break;\r\n    }\r\n}\r\n\r\n// FIXME: rename function\r\nvoid    Machine_Set_TV_Lines()\r\n{\r\n    if (DB.current_entry && DB.current_entry->emu_tvtype != -1)\r\n        g_machine.TV = &TV_Type_Table [DB.current_entry->emu_tvtype];\r\n    else\r\n        g_machine.TV = TV_Type_User;\r\n    g_machine.TV_lines = g_machine.TV->screen_lines;\r\n}\r\n\r\n// RESET EMULATED MACHINE -----------------------------------------------------\r\nvoid        Machine_Reset()\r\n{\r\n    int     i;\r\n    static byte VDPInit [16] =\r\n    {\r\n        /* Values set by BIOS */\r\n        0x36, /*0xA0*/ 0x80 /* zero for Coleco */, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x00,\r\n        0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00\r\n        /* Old (guessed ?) values */\r\n        // 0x06, 0x00, 0x0E, 0xFF, 0xFF, 0x7F, 0x00, 0x00,\r\n        // 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00\r\n    };\r\n\r\n    #ifdef DEBUG_WHOLE\r\n        Msg(MSGT_DEBUG, \"Machine_Reset();\");\r\n    #endif\r\n\r\n    // Unpause machine if necessary\r\n    if (g_machine_flags & MACHINE_PAUSED)\r\n        Machine_Pause();\r\n\r\n    // Set driver & machine stuff\r\n    drv_set (g_machine.driver_id);\r\n\r\n    Machine_Set_Mapper         ();\r\n    if ((g_machine_flags & MACHINE_RUN) != 0 /*== MACHINE_RUN */)\r\n        Machine_Set_Mapping    (); // ^^ FIXME: the test above isn't beautiful since MACHINE_RUN contains multiple flags, but I'm unsure which of them is actually needed to perform the correct test\r\n    Machine_Set_Handler_IO     ();\r\n    Machine_Set_Handler_MemRW  ();\r\n    Machine_Set_Handler_Loop   ();\r\n    Machine_Set_Country        ();\r\n    Machine_Set_IPeriod        ();\r\n    Machine_Set_TV_Lines       ();\r\n\r\n    // VDP MODEL --------------------------------------------------------------\r\n    if (DB.current_entry && DB.current_entry->emu_vdp_model != -1)\r\n    {\r\n        g_machine.VDP.model = DB.current_entry->emu_vdp_model;\r\n    }\r\n    else\r\n    {\r\n        if (g_driver->id == DRV_GG)\r\n            g_machine.VDP.model = VDP_MODEL_315_5378;\r\n        else\r\n            g_machine.VDP.model = VDP_MODEL_315_5246;\r\n    }\r\n\r\n    // 3-D GLASSES ------------------------------------------------------------\r\n    sms.Glasses_Register = ((Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT) ? 1 : 0);\r\n\r\n    // CPU (MARAT FAIZULLIN'S CORE) -------------------------------------------\r\n    CPU_Loop_Stop = TRUE;\r\n    CPU_ForceNMI  = FALSE;\r\n\r\n#ifdef MARAT_Z80\r\n    sms.R.IPeriod = opt.Cur_IPeriod;\r\n    sms.R.Trace = FALSE;\r\n    ResetZ80 (&sms.R);\r\n    sms.R.IFF |= IFF_IM1;\r\n    sms.R.IAutoReset = FALSE;\r\n    sms.R.TrapBadOps = FALSE;\r\n\r\n    // CPU (MAME'S CORE) ------------------------------------------------------\r\n#elif MAME_Z80\r\n    z80_reset (NULL);\r\n    z80_set_irq_callback (Get_IRQ_Vector);\r\n    z80_set_irq_line (0, ASSERT_LINE);\r\n    z80_set_irq_line (0, CLEAR_LINE);\r\n\r\n    // CPU (RICHARD MITTON'S CORE) --------------------------------------------\r\n#elif RAZE_Z80\r\n    z80_init_memmap();\r\n    z80_add_write (0x0000, 0xFFFF, Z80_MAP_HANDLED, WrZ80);\r\n    for (i = 0; i < 4; i ++)\r\n    {\r\n        z80_add_read ((i * 0x2000), (i * 0x2000) + 0x1FFF, Z80_MAP_DIRECT, Mem_Pages [i]);\r\n        z80_map_fetch ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]);\r\n    }\r\n    for (i = 4; i < 8; i ++)\r\n    {\r\n        z80_map_fetch ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]);\r\n        z80_map_read ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]);\r\n    }\r\n    z80_set_in (InZ80);\r\n    z80_set_out (OutZ80);\r\n    z80_end_memmap();\r\n    z80_reset();\r\n#endif\r\n\r\n    // MEMORY -----------------------------------------------------------------\r\n\r\n    // Clear RAM\r\n    if (g_driver->id == DRV_SMS && sms.Country == COUNTRY_JAPAN)\r\n    {\r\n        // On Japanese SMS clear RAM with 0xF0 patterns\r\n        // I am not sure how reliable is that pattern but this is what I'm seeing on my JSMS\r\n        // In theory this should be applied to all drivers, all countries, etc. but the exact\r\n        // behavior of other systems and bioses should be inspected more in details before\r\n        // generalizing that.\r\n        // The game \"Ali Baba\" require a non-00 and non-FF memory pattern to run to a bug\r\n        // in the code which makes it execute uninitialized memory from 0xFF07 onward.\r\n        // An F0 pattern correspond to RET P which happens to fix the game.\r\n\r\n        memset (RAM, 0xF0, 0x10000);\r\n    }\r\n    else\r\n    {\r\n        memset (RAM, 0x00, 0x10000);\r\n    }\r\n    memset (VRAM, 0, 0x04000);      // Clear all VRAM\r\n    memset (PRAM, 0, 0x00040);      // Clear all PRAM (palette)\r\n\r\n    #ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\r\n        memset (RAM_IsUninitialized, 1, 0x2000);\r\n    #endif\r\n\r\n    // Unload BIOS if...\r\n    if ((g_driver->id != DRV_SMS || sms.Country != COUNTRY_EXPORT) && (g_machine_flags & MACHINE_ROM_LOADED))\r\n    {\r\n        #ifdef DEBUG_WHOLE\r\n            Msg(MSGT_DEBUG, \"Machine_Reset(): BIOS_Unload()\");\r\n        #endif\r\n        BIOS_Unload();\r\n    }\r\n\r\n    // GRAPHICS ---------------------------------------------------------------\r\n    for (i = 0; i < 16; i++)\r\n        Tms_VDP_Out (i, ((i == 1 && g_driver->id == DRV_COLECO) ? 0x00 : VDPInit [i]));\r\n    for (i = 0; i < MAX_TILES; i++)\r\n        tgfx.Tile_Dirty [i] = TILE_DIRTY_DECODE | TILE_DIRTY_REDRAW;\r\n\r\n    VDP_UpdateLineLimits();\r\n\r\n    //assert(!Screenbuffer_IsLocked());\r\n    al_set_target_bitmap(screenbuffer_1);\r\n    al_clear_to_color(COLOR_BLACK);\r\n    al_set_target_bitmap(screenbuffer_2);\r\n    al_clear_to_color(COLOR_BLACK);\r\n    //screenbuffer = screenbuffer_1;\r\n    //screenbuffer_next = screenbuffer_2;\r\n\r\n    g_machine.VDP.sprite_shift_x = 0;\r\n    g_machine.VDP.scroll_x_latched = 0;\r\n    g_machine.VDP.scroll_y_latched = 0;\r\n    memset(g_machine.VDP.scroll_x_latched_table, 0, sizeof(g_machine.VDP.scroll_x_latched_table));\r\n    tsms.VDP_Video_Change = VDP_VIDEO_CHANGE_ALL;\r\n\r\n    // GRAPHICS: SPRITE FLICKERING --------------------------------------------\r\n    if (g_config.sprite_flickering & SPRITE_FLICKERING_AUTO)\r\n    {\r\n        if (DB.current_entry && (DB.current_entry->flags & DB_FLAG_EMU_SPRITE_FLICKER))\r\n            g_config.sprite_flickering |= SPRITE_FLICKERING_ENABLED;\r\n        else\r\n            g_config.sprite_flickering &= ~SPRITE_FLICKERING_ENABLED;\r\n    }\r\n\r\n    // PALETTE ----------------------------------------------------------------\r\n    //if (machine & MACHINE_POWER_ON)\r\n    Palette_Emulation_Reset();\r\n\r\n    // INPUT/OUTPUT/VDP -------------------------------------------------------\r\n    sms.VDP_Status = 0x00;\r\n    sms.VDP_Address = 0x0000;\r\n    sms.VDP_Access_Mode = VDP_Access_Mode_1;\r\n    sms.VDP_Access_First = 0x00;\r\n    sms.VDP_Pal = 0x00;\r\n    sms.VDP_ReadLatch = 0x00;\r\n    sms.Lines_Left = 255;\r\n    sms.Pending_HBlank = FALSE;\r\n    sms.Pending_NMI = FALSE;\r\n    tsms.VDP_Line = 0;\r\n\r\n    // CONTROLLERS ------------------------------------------------------------\r\n    for (i = 0; i < 8; i ++)\r\n        tsms.Control [i] = 0xFFFF; /* 0x3FFF */\r\n    tsms.Control_GG = /*0x20 | 0x80*/ 0;\r\n    tsms.Control_Start_Pause = 0;\r\n    tsms.Port3F = 0;\r\n    sms.Input_Mode = 0x07;\r\n\r\n    // SOUND ------------------------------------------------------------------\r\n    sms.FM_Register = 0;\r\n    sms.FM_Magic = 0;\r\n    // if (fm_use == TRUE) fm_init (FM_ALL_INIT);\r\n    // resume_fm();\r\n    FM_Reset();\r\n    SN76489_Reset (g_machine.TV->CPU_clock, Sound.SampleRate);\r\n    if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_SAMPLE)\r\n        VGM_Update_Timing (&Sound.LogVGM);\r\n\r\n    Sound_ResetCycleCounter();\r\n\r\n    // FIXME: add a reset handler per driver, instead of the code below...\r\n\r\n    // GAME GEAR COMMUNICATION PORT\r\n    if (g_machine.driver_id == DRV_GG)\r\n        Comm_Reset();\r\n\r\n    // SF-7000\r\n    if (g_machine.driver_id == DRV_SF7000)\r\n        SF7000_Reset();\r\n\r\n    // DEBUGGER ---------------------------------------------------------------\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n        Debugger_MachineReset();\r\n    #endif\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/machine.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - machine.h\n// Emulated Machines Initialization - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nextern int g_machine_pause_requests;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Machine_Pause();\nvoid    Machine_Debug_Start();\nvoid    Machine_Debug_Stop();\nvoid    Machine_Reset();\n\nvoid    Machine_Set_Mapper();\nvoid    Machine_Set_Mapping();\nvoid    Machine_Set_Handler_IO();\nvoid    Machine_Set_Handler_Loop();\nvoid    Machine_Set_Handler_MemRW();\nvoid    Machine_Set_Country();\nvoid    Machine_Set_IPeriod();\nvoid    Machine_Set_TV_Lines();\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/mainloop.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - mainloop.c\r\n// Main Emulation / GUI loop - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"debugger.h\"\r\n#include \"effects.h\"\r\n#include \"fskipper.h\"\r\n#include \"video.h\"\r\n#include \"vmachine.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Main_Loop()\r\n{\r\n    #ifdef DEBUG_WHOLE\r\n        Msg(MSGT_DEBUG, \"Main_Loop();\");\r\n    #endif\r\n\r\n    // Print debugging information\r\n    if (g_env.debug_dump_infos)\r\n    {\r\n        Msg(MSGT_DEBUG, \"### Debugging information ###\");\r\n        Msg(MSGT_DEBUG, \"MEKA %s (%s %s)\", MEKA_VERSION, MEKA_BUILD_DATE, MEKA_BUILD_TIME);\r\n        Msg(MSGT_DEBUG, \"allegro_version = %08x\", al_get_allegro_version());\r\n        //Msg(MSGT_DEBUG, \"os_type = { %c%c%c%c (%d.%d) }\", os_type>>24, (os_type>>16)&0xFF, (os_type>>8)&0xFF, (os_type)&0xFF, os_version, os_revision);\r\n        //Msg(MSGT_DEBUG, \"cpu = { fpu: %d, mmx:%d, 3dnow:%d-%d, sse:%d, sse2:%d }\", CPU_FPU?1:0, CPU_MMX?1:0, CPU_3DNOW?1:0, CPU_ENH3DNOW?1:0, CPU_SSE?1:0, CPU_SSE2?1:0);\r\n        //Msg(MSGT_DEBUG, \"gui = { driver:%ld, %d*%d @ %d Hz, depth:%d }\", g_config.video_mode_gui_driver, g_config.video_mode_gui_res_x, g_config.video_mode_gui_res_y, g_config.video_mode_gui_refresh_rate, g_config.video_mode_gui_depth_cfg);\r\n        Msg(MSGT_DEBUG, \"mouse = %d\", g_env.mouse_installed);\r\n        Msg(MSGT_DEBUG, \"joystick = %d\", al_get_num_joysticks());\r\n        Msg(MSGT_DEBUG, \"### Debugging information ###\");\r\n    }\r\n\r\n    for (;;)\r\n    {\r\n        #ifdef DEBUG_WHOLE\r\n            Msg(MSGT_DEBUG, \"Main_Loop(), Loop;\");\r\n        #endif\r\n        CPU_Loop_Stop = FALSE;\r\n        if ((g_machine_flags & (MACHINE_POWER_ON | MACHINE_PAUSED)) == MACHINE_POWER_ON)\r\n        {\r\n            Sound_Playback_Start();\r\n            {\r\n                #ifdef MARAT_Z80\r\n                    #ifdef MEKA_Z80_DEBUGGER\r\n                        if (Debugger.active /* && (Debugger.break_point_set || sms.R.Trace)*/)\r\n                        {\r\n                            // Msg(MSGT_USER, \"Entering RunZ80_Debugging()\");\r\n                            RunZ80_Debugging (&sms.R);\r\n                        }\r\n                        else\r\n                    #endif\r\n                        {\r\n                            // Msg(MSGT_USER, \"Entering RunZ80()\");\r\n                            RunZ80 (&sms.R);\r\n                        }\r\n                #else\r\n                    CPU_Loop();\r\n                #endif\r\n            }\r\n        }\r\n        else // Machine is powered off or paused\r\n        {\r\n            Sound_Playback_Stop();\r\n            Main_Loop_No_Emulation();\r\n        }\r\n        if (opt.Force_Quit)\r\n        {\r\n            break;\r\n        }\r\n    }\r\n\r\n    // Clear screen to black, so that palette switch doesn't look ugly when quitting\r\n    al_set_target_bitmap(al_get_backbuffer(g_display));\r\n    al_clear_to_color(COLOR_BLACK);\r\n\r\n    // Stop sound\r\n    Sound_Playback_Stop();\r\n}\r\n\r\n// MAIN LOOP WHEN FALSE ROM IS LOADED --------------------------------------------\r\nvoid    Main_Loop_No_Emulation()\r\n{\r\n#ifdef DEBUG_WHOLE\r\n    Msg(MSGT_DEBUG, \"Main_Loop_No_Emulation();\");\r\n#endif\r\n\r\n    for (;;)\r\n    {\r\n        Inputs_Sources_Update();\r\n        Inputs_Emulation_Update(FALSE); // [Omar-20050327] Allows changing inputs data from the debugger.// FIXME: but the debugger has exclusive inputs.\r\n        Inputs_Check_GUI(FALSE);\r\n        if ((opt.Force_Quit) || ((g_machine_flags & (MACHINE_POWER_ON | MACHINE_PAUSED)) == MACHINE_POWER_ON))\r\n        {\r\n            return;\r\n        }\r\n        // FIXME: debugger there\r\n        // Update TV effect or Games\r\n        if ((fskipper.Show_Current_Frame) && (!(g_machine_flags & MACHINE_POWER_ON)))\r\n        {\r\n            sms.VDP[0] &= ~0x20; // no mask left 8 (for GUI windows) // FIXME: blah\r\n            Effects_TV_Update();\r\n        }\r\n        // Refresh GUI screen\r\n        Video_RefreshScreen();\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/mainloop.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - mainloop.h\n// Main Emulation / GUI loop - Headers\n//-----------------------------------------------------------------------------\n\nvoid    Main_Loop();\nvoid    Main_Loop_No_Emulation();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/mappers.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - mappers.c\r\n// Memory Mapper Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: Need to refactor this whole file. Some things we want:\r\n// - Create proper named mapper-id and try to standardize with community.\r\n// - Gather all infos and code about a mapper in a central place (grep for MAPPER_*\r\n//   usage in code, mainly the switches in machine.c and saves.c)\r\n// - Generally clean up implementation.\r\n//-----------------------------------------------------------------------------\r\n\r\n//#define DEBUG_MEM\r\n//#define DEBUG_PAGES\r\n#include \"shared.h\"\r\n#include \"mappers.h\"\r\n#include \"eeprom.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\r\nu8 RAM_IsUninitialized[0x2000];\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Macros / Inline functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid Map_8k_Other (int page, void *data)\r\n{\r\n    Mem_Pages [page] = (u8 *)data - (page * 0x2000);\r\n}\r\n\r\nvoid Map_16k_Other (int page, void *data)\r\n{\r\n    Mem_Pages [page] = Mem_Pages [page + 1] = (u8*)data - (page * 0x2000);\r\n}\r\n\r\nvoid Map_8k_RAM (int page, int ram_page)\r\n{\r\n    Mem_Pages [page] = RAM + ((ram_page - page) * 0x2000);\r\n}\r\n\r\nvoid Map_8k_ROM (int page, int rom_page)\r\n{\r\n    Mem_Pages [page] = ROM + ((rom_page - page) * 0x2000);\r\n}\r\n\r\nvoid Map_16k_ROM (int page, int rom_page)\r\n{\r\n    Mem_Pages [page] = Mem_Pages [page + 1] = ROM + ((rom_page - page) * 0x2000);\r\n}\r\n\r\n#ifdef DEBUG_MEM\r\nvoid    Write_Error (int Addr, u8 Value)\r\n{\r\n    Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Write), sms.R.PC.W, Value, Addr);\r\n}\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic u8   Mapper_SMS_Korean_Janggun_BitReverseLUT[256];\r\n\r\nvoid    Mapper_InitializeLookupTables()\r\n{\r\n    for (int i = 0; i != 256; i++)\r\n    {\r\n        int reversed = 0;\r\n        for (int b = 0; b != 8; b++)\r\n            if (i & (1<<b))\r\n                reversed |= (1<<(7-b));\r\n        Mapper_SMS_Korean_Janggun_BitReverseLUT[i] = reversed;\r\n    }\r\n}\r\n\r\nvoid    Out_SC3000_SurvivorsMulticarts_DataWrite(u8 v)\r\n{\r\n    // Control Byte format\r\n    // Q0..Q4 controls the A15 to A19 address lines on the EPROMs.\r\n    //        So these 5 bits let you select a 32KB logical block within one of the EPROMs.  Q0 => A15, Q1 => A16, Q2 => A17, Q3 => A18, Q4 => A19\r\n    // Q5     is not connected to anything\r\n    // Q6     ROM 0 / ROM 1 select (0 =>ROM 0, 1 => ROM 1)\r\n    // Q7     Enables / Disables latch\r\n    //        If the latch is disabled, then pull up resistors ensure that block 31 in ROM 1 is selected\r\n    g_machine.mapper_regs[0] = v;\r\n    int game_no = (v & 0x80) ? ((v & 0x1f) | ((v & 0x40) ? 0x20 : 0x00)) : 0x3F;\r\n\r\n    Map_8k_ROM(0, game_no*4+0);\r\n    Map_8k_ROM(1, game_no*4+1);\r\n    Map_8k_ROM(2, game_no*4+2);\r\n    Map_8k_ROM(3, game_no*4+3);\r\n}\r\n\r\nvoid    Mapper_Get_RAM_Infos(int *plen, int *pstart_addr)\r\n{\r\n    int len, start_addr;\r\n\r\n    switch (g_machine.mapper)\r\n    {\r\n        case MAPPER_32kRAM:                         len = 0x08000; start_addr = 0x8000; break;\r\n        case MAPPER_ColecoVision:                   len = 0x00400; start_addr = 0x6000; break;\r\n        case MAPPER_SG1000:                         len = 0x01000; start_addr = 0xC000; break;\r\n        case MAPPER_TVOekaki:                       len = 0x01000; start_addr = 0xC000; break;\r\n        case MAPPER_SF7000:                         len = 0x10000; start_addr = 0x0000; break;\r\n        case MAPPER_SMS_DisplayUnit:                len = 0x02800; start_addr = 0x4000; break; // FIXME: Incorrect, due to scattered mapping!\r\n        case MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA:len = 0x02000+0x800; start_addr = 0x2000; break; // FIXME: Two memory regions\r\n        case MAPPER_SC3000_Survivors_Multicart:     len = 0x08000; start_addr = 0x8000; break;\r\n        // FIXME: ActionReplay!!\r\n        // default, Codemaster, Korean..\r\n        default:                                len = 0x02000; start_addr = 0xC000; break;\r\n    }\r\n    if (plen)\r\n        *plen = len;\r\n    if (pstart_addr)\r\n        *pstart_addr = start_addr;\r\n}\r\n\r\n// Return -1 if can't tell, else a mapper number\r\nint         Mapper_Autodetect()\r\n{\r\n    // If ROM is smaller than 32KB, auto-detected SMS mapper are not needed\r\n    if (tsms.Size_ROM <= 0x8000)\r\n        return (-1);\r\n\r\n    // Search for code to access mapper -> LD (8000)|(FFFF), A\r\n    int c0002 = 0, c2000 = 0, c8000 = 0, cA000 = 0, cBFFC = 0, cBFFF = 0, cFFFF = 0;\r\n    int c0000 = 0, c0100 = 0, c0200 = 0, c0300 = 0;\r\n    for (int i = 0; i < 0x8000; i++)\r\n    {\r\n        if (ROM[i] == 0x32) // Z80 opcode for: LD (xxxx), A\r\n        {\r\n            const u16 addr = *(u16 *)&ROM [i + 1];\r\n            if (addr == 0xFFFF)\r\n            { i += 2; cFFFF++; continue; }\r\n            if (addr == 0x0002 || addr == 0x0003 || addr == 0x0004)\r\n            { i += 2; c0002++; continue; }\r\n            if (addr == 0x2000)\r\n            { i += 2; c2000++; continue; }\r\n            if (addr == 0x8000)\r\n            { i += 2; c8000++; continue; }\r\n            if (addr == 0xA000)\r\n            { i += 2; cA000++; continue; }\r\n            if (addr == 0xBFFF)\r\n            { i += 2; cBFFF++; continue; }\r\n\r\n            // MAPPER_SMS_Korean_MSX_8KB_0300\r\n            if (addr == 0x0000) { i += 2; c0000++; continue; }\r\n            if (addr == 0x0100) { i += 2; c0100++; continue; }\r\n            if (addr == 0x0200) { i += 2; c0200++; continue; }\r\n            if (addr == 0x0300) { i += 2; c0300++; continue; }\r\n        }\r\n\r\n        if (ROM[i] == 0x21) // Z80 opcode for LD HL,XXXX\r\n        {\r\n            const u16 addr = *(u16*)&ROM[i + 1];\r\n\r\n            // Super Game 200 - 200 Hap ~ Super Game (KR)\r\n            if (addr == 0xBFFC)\r\n                if (ROM[i + 3] == 0x3A) // LD A,XXX\r\n                    if (ROM[i + 6] == 0x77) // LD (HL), A\r\n                        cBFFC++;\r\n        }\r\n    }\r\n\r\n    //Msg(MSGT_USER, \"c002=%d, c8000=%d, cA000=%d, cBFFF=%d, cFFFF=%d\\n\", c0002, c8000, cA000, cBFFF, cFFFF);\r\n\r\n    // 4 Pak All Action \"games\"\r\n    // this is not strictly necessary, since the full 4 Pak All Action is in meka.nam, but this allows extracted games to run standalone\r\n    // NB: twin mouse has a false 0x0002 matching so it must be tested before\r\n    if (cBFFF > 0 && /*c0002 == 0 &&*/ c8000 == 0 && cA000 == 0 && cFFFF == 0)\r\n        return (MAPPER_SMS_4PakAllAction);\r\n\r\n    // 2 is a security measure, although tests on existing ROM showed it was not needed\r\n    if (c0000 >= 1 && c0100 >= 1 && c0200 >= 1 && c0300 >= 1 && (c0000 + c0100 + c0200 + c0300 > cFFFF)) // Need to be BEFORE MAPPER_SMS_Korean_MSX_8KB_0003 for 30-in-1\r\n        return (MAPPER_SMS_Korean_MSX_8KB_0300);\r\n    if (c0002 > cFFFF + 2 || (c0002 > 0 && cFFFF == 0))\r\n        return (MAPPER_SMS_Korean_MSX_8KB_0003);\r\n    if (c2000 >= 2 && cFFFF == 0)\r\n        return (MAPPER_SMS_Korean_2000_xor_1F);\r\n    if (c8000 > cFFFF + 2 || (c8000 > 0 && cFFFF == 0))\r\n        return (MAPPER_CodeMasters);\r\n    if (cBFFC >= 1 && cFFFF == 0)\r\n        return (MAPPER_SMS_Korean_BFFC);\r\n    if (cA000 > cFFFF + 2 || (cA000 > 0 && cFFFF == 0))\r\n        return (MAPPER_SMS_Korean_A000);\r\n\r\n    return (MAPPER_Auto);\r\n}\r\n\r\nWRITE_FUNC (Write_Default)\r\n{\r\n    if ((Addr & 0xFFF8) == 0xFFF8)\r\n    {\r\n        switch (Addr & 0x7)\r\n        {\r\n        case 4: // 0xFFFC: SRAM Register ---------------------------------------------\r\n            RAM [0x1FFC] = sms.SRAM_Mapping_Register = Value;\r\n            if (SRAM_Active)\r\n            {\r\n                if (SRAM_Page)\r\n                {\r\n                    sms.SRAM_Pages = 4; // 4 x 8 KB\r\n                    Map_8k_Other (4, &SRAM [0x4000]);\r\n                }\r\n                else\r\n                {\r\n                    if (sms.SRAM_Pages < 2)\r\n                        sms.SRAM_Pages = 2; // 2 x 8 kB\r\n                    Map_8k_Other (4, &SRAM [0x0000]);\r\n                }\r\n            }\r\n            else\r\n            {\r\n                Map_8k_ROM (4, g_machine.mapper_regs[2] * 2);\r\n            }\r\n            // FIXME: Use Map_16k* above instead of this.\r\n            Mem_Pages [5] = Mem_Pages [4];\r\n            return;\r\n        case 5: // 0xFFFD: Frame 0 ---------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n            if (Value != 0)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 0 set to page %d !\", CPU_GetPC, Value); }\r\n#endif\r\n            Value &= tsms.Pages_Mask_16k;\r\n            if (g_machine.mapper_regs[0] != Value)\r\n            {\r\n                RAM [0x1FFD] = g_machine.mapper_regs[0] = Value;\r\n                if (Value != 0)\r\n                {\r\n                    Map_16k_Other (0, Game_ROM_Computed_Page_0);\r\n                    memcpy (Game_ROM_Computed_Page_0 + 0x400, ROM + (Value << 14) + 0x400, 0x3C00);\r\n                }\r\n                else\r\n                {\r\n                    Map_16k_ROM (0, 0);\r\n                }\r\n                return;\r\n        case 6: // 0xFFFE: Frame 1 ---------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n            if (Value > tsms.Pages_Count_16k)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 1 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n            RAM [0x1FFE] = g_machine.mapper_regs[1] = Value & tsms.Pages_Mask_16k;\r\n            Map_16k_ROM (2, g_machine.mapper_regs[1] * 2);\r\n            return;\r\n        case 7: // 0xFFFF: Frame 2 ---------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n            if (Value > tsms.Pages_Count_16k)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 2 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n            RAM [0x1FFF] = g_machine.mapper_regs[2] = Value & tsms.Pages_Mask_16k;\r\n            if (!SRAM_Active)\r\n            {\r\n                Map_16k_ROM (4, g_machine.mapper_regs[2] * 2);\r\n            }\r\n            return;\r\n        default: // 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB: Glasse Register ------------------\r\n            Mem_Pages [7] [Addr] = sms.Glasses_Register = Value;\r\n            return;\r\n            }\r\n        }\r\n    }\r\n\r\n#ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\r\n    if (Addr >= 0xC000 && Addr <= 0xFFFF)\r\n        RAM_IsUninitialized[Addr&0x1FFF] = 0;\r\n#endif\r\n\r\n    // RAM -----------------------------------------------------------------------\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; return;\r\n        // SaveRAM [0x8000]->[0xC000] ---------------------------------------------\r\n    case 4: if (SRAM_Active) { Mem_Pages [4] [Addr] = Value; return; } break;\r\n    case 5: if (SRAM_Active) { Mem_Pages [5] [Addr] = Value; return; } break;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// [MAPPER: 32K RAM/SC-3000] WRITE BYTE ---------------------------------------\r\nWRITE_FUNC (Write_Mapper_32kRAM)\r\n{\r\n    const unsigned int page = (Addr >> 13);\r\n    if (page >= 4)\r\n    {\r\n        Mem_Pages[page][Addr] = Value; return;\r\n    }\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_SMS_NoMapper)\r\n{\r\n#ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\r\n    if (Addr >= 0xC000 && Addr <= 0xFFFF)\r\n        RAM_IsUninitialized[Addr&0x1FFF] = 0;\r\n#endif\r\n\r\n    // RAM -----------------------------------------------------------------------\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; if (Addr >= 0xFFF8 && Addr <= 0xFFFB) sms.Glasses_Register = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// FIXME: Amount of RAM is totally incorrect.\r\nWRITE_FUNC (Write_Mapper_SG1000)\r\n{\r\n    switch (Addr)\r\n    {\r\n    case 0xFFFD: // Frame 0 ------------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n        if (Value != 0)\r\n        { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 0 set to page %d !\", CPU_GetPC, Value); }\r\n#endif\r\n        Value &= tsms.Pages_Mask_16k;\r\n        if (g_machine.mapper_regs[0] != Value)\r\n        {\r\n            RAM [0x1FFD] = g_machine.mapper_regs[0] = Value;\r\n            if (Value != 0)\r\n            {\r\n                Map_16k_Other (0, Game_ROM_Computed_Page_0);\r\n                memcpy (Game_ROM_Computed_Page_0 + 0x400, ROM + (Value << 14) + 0x400, 0x3C00);\r\n            }\r\n            else\r\n            {\r\n                Map_16k_ROM (0, 0);\r\n            }\r\n        }\r\n        return;\r\n    case 0xFFFE: // Frame 1 ------------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n        if (Value > tsms.Pages_Count_16k)\r\n        { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 1 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n        RAM [0x1FFE] = g_machine.mapper_regs[1] = Value & tsms.Pages_Mask_16k;\r\n        Map_16k_ROM(2, g_machine.mapper_regs[1] * 2);\r\n        return;\r\n    case 0xFFFF: // Frame 2 ------------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n        if (Value > tsms.Pages_Count_16k)\r\n        { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 2 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n        RAM [0x1FFF] = g_machine.mapper_regs[2] = Value & tsms.Pages_Mask_16k;\r\n        Map_16k_ROM (4, g_machine.mapper_regs[2] * 2);\r\n        return;\r\n    }\r\n\r\n#ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\r\n    if (Addr >= 0xC000 && Addr <= 0xFFFF)\r\n        RAM_IsUninitialized[Addr&0x1FFF] = 0;\r\n#endif\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] -----------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr & ~0x1000] = Mem_Pages [6] [Addr | 0x1000] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr & ~0x1000] = Mem_Pages [7] [Addr | 0x1000] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_SG1000_Taiwan_MSX_Adapter_TypeA)\r\n{\r\n    // RAM\r\n    switch (Addr >> 13)\r\n    {\r\n    case 1: Mem_Pages [1] [Addr] = Value; return;\r\n    case 6: Mem_Pages [6] [Addr & ~0x1800] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr & ~0x1800] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_CodeMasters)\r\n{\r\n    switch (Addr)\r\n    {\r\n    case 0x0000: // Frame 0 ----------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n        //if (Value > tsms.Pages_Count_16k)\r\n        { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 0 set to non-existent page: %d\", CPU_GetPC, Value);}\r\n#endif\r\n        Value = (Value & tsms.Pages_Mask_16k);\r\n        /*ROM [0x0000] = */ g_machine.mapper_regs[0] = Value;\r\n        Map_16k_ROM (0, g_machine.mapper_regs[0] * 2);\r\n        return;\r\n    case 0x4000: // Frame 1 ----------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n        //if (Value > tsms.Pages_Count_16k)\r\n        { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 1 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n        if (Value & 0x80) // OnBoard RAM for Ernie Els Golf\r\n        {\r\n            sms.SRAM_Mapping_Register = ONBOARD_RAM_EXIST | ONBOARD_RAM_ACTIVE;\r\n            Map_8k_RAM(5, 1); // Mapped from 0xA000 to 0xC000 only! (0x8000 to 0xA000 has ROM!)\r\n        }\r\n        else\r\n        {\r\n            if (sms.SRAM_Mapping_Register & ONBOARD_RAM_ACTIVE)\r\n            {\r\n                // Map Page 2 back if we just disabled On Board RAM\r\n                Map_8k_ROM(5, g_machine.mapper_regs[2] * 2 + 1);\r\n            }\r\n            sms.SRAM_Mapping_Register &= ~ONBOARD_RAM_ACTIVE;\r\n            Value = (Value & tsms.Pages_Mask_16k);\r\n            /* ROM [0x4000] = */ g_machine.mapper_regs[1] = Value;\r\n            Map_16k_ROM(2, g_machine.mapper_regs[1] * 2);\r\n        }\r\n        return;\r\n    case 0x8000: // Frame 2 ----------------------------------------------------\r\n#ifdef DEBUG_PAGES\r\n        //if (Value > tsms.Pages_Count_16k)\r\n        { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 2 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n        Value = (Value & tsms.Pages_Mask_16k);\r\n        /* ROM [0x8000] = */ /* ROM[0xBFFF] = */ g_machine.mapper_regs[2] = Value;\r\n        Map_16k_ROM(4, g_machine.mapper_regs[2] * 2);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // On Board RAM [0xA000]->[0xC000] ----------------------------------------\r\n        // (for Ernie Els Golf)\r\n    case 5: if (sms.SRAM_Mapping_Register & ONBOARD_RAM_ACTIVE) { Mem_Pages [5] [Addr] = Value; return; } break;\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; return;\r\n        // SaveRAM [0x8000]->[0xC000] ---------------------------------------------\r\n        // case 4: if (SRAM_Active) Mem_Pages [4] [Addr] = Value; return;\r\n        // case 5: if (SRAM_Active) Mem_Pages [5] [Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_SMS_4PakAllAction)\r\n{\r\n    switch (Addr)\r\n    {\r\n    case 0x3FFE: // Frame 0 ----------------------------------------------------\r\n        {\r\n            g_machine.mapper_regs[0] = Value;\r\n            const int page = (g_machine.mapper_regs[0]) & tsms.Pages_Mask_16k;\r\n            Map_16k_ROM(0, page * 2);\r\n            return;\r\n        }\r\n    case 0x7FFF: // Frame 1 ----------------------------------------------------\r\n        {\r\n            g_machine.mapper_regs[1] = Value;\r\n            const int page = (g_machine.mapper_regs[1]) & tsms.Pages_Mask_16k;\r\n            Map_16k_ROM(2, page * 2);\r\n            return;\r\n        }\r\n    case 0xBFFF: // Frame 2 ----------------------------------------------------\r\n        {\r\n            g_machine.mapper_regs[2] = Value;\r\n            const int page = ((g_machine.mapper_regs[0]&0x30) + (g_machine.mapper_regs[2])) & tsms.Pages_Mask_16k;\r\n            Map_16k_ROM(4, page * 2);\r\n            return;\r\n        }\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Write function for Mapper #9: MAPPER_SMS_Korean_A000\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_A000)\r\n{\r\n    if (Addr == 0xA000) // Frame 2 -----------------------------------------------\r\n    {\r\n        Value = (Value & tsms.Pages_Mask_16k);\r\n        /* ROM [0xA000] = */ g_machine.mapper_regs[2] = Value;\r\n        Map_16k_ROM(4, g_machine.mapper_regs[2] * 2);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Write function for Mapper #20: MAPPER_SMS_Korean_BFFC\r\n// (Note: somehow similar to #21)\r\nWRITE_FUNC(Write_Mapper_SMS_Korean_BFFC)\r\n{\r\n    if (Addr == 0xBFFC)\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n\r\n        const int mask_16 = tsms.Pages_Mask_16k; // 0x3F for a 1 MB rom\r\n        u8 lower;\r\n        u8 upper;\r\n        switch (Value & (0x40 | 0x80))\r\n        {\r\n        case 0x00: // 32 KB SMS/SG game\r\n            lower = (Value & 0x3E);\r\n            upper = (Value & 0x3E) | 1;\r\n            Map_16k_ROM(0, (lower & mask_16) * 2);\r\n            Map_16k_ROM(2, (upper & mask_16) * 2);\r\n            Map_8k_ROM(4, (0x3f & mask_16) * 2 + 1); // actually should be open bus\r\n            Map_8k_ROM(5, (0x3f & mask_16) * 2 + 1); // actually should be open bus\r\n            break;\r\n        case 0x40: // 16 KB SMS/SG game\r\n            lower = upper = (Value & 0x3F);\r\n            Map_16k_ROM(0, (lower & mask_16) * 2);\r\n            Map_16k_ROM(2, (upper & mask_16) * 2);\r\n            Map_8k_ROM(4, (0x3f & mask_16) * 2 + 1); // actually should be open bus\r\n            Map_8k_ROM(5, (0x3f & mask_16) * 2 + 1); // actually should be open bus\r\n            break;\r\n        case 0x80: // MSX Regular (16 KB bios + 16 KB ROM)\r\n            lower = 0x20;\r\n            upper = (Value & 0x3F);\r\n            Map_16k_ROM(0, (lower & mask_16) * 2);\r\n            Map_16k_ROM(2, (upper & mask_16) * 2);\r\n            Map_8k_ROM(4, (0x3f & mask_16) * 2 + 1); // actually should be open bus\r\n            Map_8k_ROM(5, (0x3f & mask_16) * 2 + 1); // actually should be open bus\r\n            break;\r\n        case 0xC0: // MSX Namco (16 KB bios + 2x8 KB ROM each mirrored once in A B B A order)\r\n            lower = 0x20;\r\n            upper = (Value & 0x3F);\r\n            Map_16k_ROM(0, (lower & mask_16) * 2);\r\n            Map_16k_ROM(2, (upper & mask_16) * 2);\r\n            Map_8k_ROM(4, (upper & mask_16) * 2 + 1);\r\n            Map_8k_ROM(5, (upper & mask_16) * 2);\r\n            break;\r\n        }\r\n\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\n\r\n// Write function for Mapper #16: MAPPER_SMS_Korean_FFFF_HiCom\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_FFFF_HiCom)\r\n{\r\n    if (Addr == 0xFFFF) // Frame 2 -----------------------------------------------\r\n    {\r\n        RAM[0x1FFF] = Value;\r\n        Value = (Value & tsms.Pages_Mask_16k);\r\n        g_machine.mapper_regs[0] = Value;\r\n        Map_16k_ROM(0, g_machine.mapper_regs[0] * 4);\r\n        Map_16k_ROM(2, g_machine.mapper_regs[0] * 4 + 2);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Mapper #19\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_2000_xor_1F)\r\n{\r\n    if ((Addr & 0x6000) == 0x2000) // Configurable segment -----------------------------------------------\r\n    {\r\n        //RAM[0x1FFF] = Value;\r\n\r\n        // This is technically incorrect: to mimic the actual hardware\r\n        // we would either need to use an overdumped 2MB ROM, or we\r\n        // would need to preserve all the segment base bits, as page\r\n        // numbers past the end of the ROM return zeroes in real\r\n        // hardware.\r\n        g_machine.mapper_regs[0] = Value;\r\n        Value = ((Value ^ 0x1F) & tsms.Pages_Mask_8k) ^ 0x1F;\r\n        Map_8k_ROM(2, Value ^ 0x1f);\r\n        Map_8k_ROM(3, Value ^ 0x1e);\r\n        Map_8k_ROM(4, Value ^ 0x1d);\r\n        Map_8k_ROM(5, Value ^ 0x1c);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Mapper #21\r\n// (Note: somehow similar to #20, see how #20 is written as it is somehow neater)\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_FFFE)\r\n{\r\n    if (Addr == 0xFFFE) // Configurable segment -----------------------------------------------\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        // 0abcccccd\r\n        //  a (1-bit)  when 0 = map MSX BIOS in page 0 and 1, when 1 = use regular register\r\n        //  b (1-bit)\r\n        //  c (5-bits)\r\n        //  d (1-bit)\r\n        Map_8k_ROM(0, (((Value & 0x40) == 0x40) ? ((Value & 0x1e) * 2) : 0) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, (((Value & 0x40) == 0x40) ? ((Value & 0x1e) * 2 + 1) : 1) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, (((Value & 0x40) == 0x40) ? (((Value & 0x1e) + 1) * 2) : ((Value & 0x1f) * 2)) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (((Value & 0x40) == 0x40) ? (((Value & 0x1e) + 1) * 2 + 1) : ((Value & 0x1f) * 2 + 1)) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (((Value & 0x60) == 0x20) ? ((Value & 0x1f) * 2 + 1) : 0x3f) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (((Value & 0x60) == 0x20) ? ((Value & 0x1f) * 2) : 0x3f) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Mapper #22\r\n// Super Game 150, Super Game 270\r\nWRITE_FUNC(Write_Mapper_SMS_Korean_FFF3_FFFC)\r\n{\r\n    const int incomplete_address_decoding = 0x4000;\r\n    const u16 addr_assumed = Addr | incomplete_address_decoding;\r\n    if (addr_assumed == 0xFFF3 || addr_assumed == 0xFFFC) // Configurable segment -----------------------------------------------\r\n    {\r\n        if (addr_assumed == 0xFFF3) {\r\n            g_machine.mapper_regs[0] = Value;\r\n        }\r\n        else if (addr_assumed == 0xFFFC) {\r\n            g_machine.mapper_regs[1] = Value;\r\n        }\r\n        const int Mapper = g_machine.mapper_regs[0];\r\n        const int Mode = g_machine.mapper_regs[1];\r\n\r\n        const int Config = Mode & 0xE0;\r\n\r\n        const int Page0 = (Mode & 0x10) * 8 + (Mapper & 0x3E) * 2;\r\n        const int Page1 = Page0 + 1;\r\n        const int Page2 = Page0 + 2;\r\n        const int Page3 = Page0 + 3;\r\n\r\n        const int Odd = Mapper & 0x01;\r\n\r\n        if (Config == 0x00) {\r\n            // 16KB SMS\r\n            Map_8k_ROM(0, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, 0xFF & tsms.Pages_Mask_8k);\r\n        }\r\n        else if (Config == 0x20) {\r\n            // 32KB SMS\r\n            Map_8k_ROM(0, Page0 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, Page1 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, Page2 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, Page3 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, 0xFF & tsms.Pages_Mask_8k);\r\n        }\r\n        else if (Config == 0x40) {\r\n            // MSX mapped at 0x4000\r\n            Map_8k_ROM(0, 0x80 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, 0x81 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, 0xFF & tsms.Pages_Mask_8k);\r\n        }\r\n        else if (Config == 0x60) {\r\n            // MSX mapped at 0x8000\r\n            Map_8k_ROM(0, 0x80 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, 0x81 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, 0xFE & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n        }\r\n        else if (Config == 0x80) {\r\n            // MSX (8KB permuted)\r\n            Map_8k_ROM(0, 0x80 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, 0x81 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n        }\r\n        else if (Config == 0xA0) {\r\n            // MSX (16KB permuted)\r\n            Map_8k_ROM(0, 0x80 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, 0x81 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, (Odd ? Page2 : Page0) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, (Odd ? Page3 : Page1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, (Odd ? Page0 : Page2) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, (Odd ? Page1 : Page3) & tsms.Pages_Mask_8k);\r\n        }\r\n        else {\r\n            // ???\r\n            Map_8k_ROM(0, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(2, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, 0xFF & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, 0xFF & tsms.Pages_Mask_8k);\r\n        }\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\n// Mapper #23\r\n// Zemina 4-in-1 (Q-Bert, Sports 3, Gulkave, Pooyan)\r\nWRITE_FUNC(Write_Mapper_SMS_Korean_0000_xor_FF)\r\n{\r\n    if (Addr == 0x0000) // Configurable segment -----------------------------------------------\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        if ((Value & 0xF0) == 0xF0)\r\n        {\r\n            // 0xFF maps the same 16KB (of all 0xFF bytes!) twice\r\n            Map_8k_ROM(2, 2 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, 3 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, 2 & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, 3 & tsms.Pages_Mask_8k);\r\n        }\r\n        else {\r\n            int segment_start_8k = ((Value ^ 0xF0) & 0xF0) >> 2;\r\n            Map_8k_ROM(2, segment_start_8k & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(3, (segment_start_8k + 1) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(4, (segment_start_8k + 2) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(5, (segment_start_8k + 3) & tsms.Pages_Mask_8k);\r\n        }\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\n// Mapper #24\r\n// Mega Mode Super Game 30 [SMS-MD] (KR)\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF0)\r\n{\r\n    if (Addr == 0xFFF0) // Configurable segment -----------------------------------------------\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        g_machine.mapper_regs[1] = 0;\r\n        g_machine.mapper_regs[2] = 1;\r\n        Map_8k_ROM(0, (Value * 4) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, (Value * 4 + 1) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, (Value * 4 + 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (Value * 4 + 3) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (Value * 4) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (Value * 4 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n    if (Addr == 0xFFFE)\r\n    {\r\n        g_machine.mapper_regs[1] = Value;\r\n        Map_8k_ROM(2, (g_machine.mapper_regs[0] * 4 + (Value & 0x0F) * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (g_machine.mapper_regs[0] * 4 + (Value & 0x0F) * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n    if (Addr == 0xFFFF)\r\n    {\r\n        g_machine.mapper_regs[2] = Value;\r\n        Map_8k_ROM(4, (g_machine.mapper_regs[0] * 4 + (Value & 0x0F) * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (g_machine.mapper_regs[0] * 4 + (Value & 0x0F) * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Mapper #25\r\n// Jaemiissneun Game Mo-eumjip 42/65 Hap [SMS-MD]\r\n// Pigu-Wang 7 Hap ~ Jaemiiss-neun Game Mo-eumjip [SMS-MD]\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF5)\r\n{\r\n    // These bits in the address apparently are not checked when\r\n    // determining whether a write corresponds to a mapper register\r\n    // and are assumed to be set. Some cartridges using this mapper\r\n    // contain code that accesses the registers by their aliases.\r\n    const int incomplete_address_decoding = 0x4010;\r\n    if ((Addr | incomplete_address_decoding) == 0xFFF5) // Configurable segment -----------------------------------------------\r\n    {\r\n        // Not yet implemented: some multicarts with this mapper seem\r\n        // to require the mapping to be left-rotated through the\r\n        // register one bit at a time. So instead of writing simple\r\n        // 0x04, you would need to write (in sequence) 0x08, 0x10,\r\n        // 0x20, 0x40, 0x80, 0x01, 0x02, 0x04.\r\n        //\r\n        // However other cartridges have a mapper that does not\r\n        // require this \"unlock\" and their code does not perform the unlock.\r\n        //\r\n        // For now, only the simpler mapper implementation is present,\r\n        // as this is apparently sufficient to run the menus and games\r\n        // for both mapper types.\r\n        g_machine.mapper_regs[0] = Value;\r\n        g_machine.mapper_regs[1] = 1;\r\n        g_machine.mapper_regs[2] = 1;\r\n        Map_8k_ROM(0, (Value * 4) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, (Value * 4 + 1) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, (Value * 4 + 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (Value * 4 + 3) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (Value * 4 + 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (Value * 4 + 3) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n    const unsigned int mapper_page_mask_16k = g_machine.mapper_regs[0] >= 0x10 ? 0x1f : 0x0f;\r\n    if ((Addr | incomplete_address_decoding) == 0xFFFE)\r\n    {\r\n        g_machine.mapper_regs[1] = Value;\r\n        Map_8k_ROM(2, (g_machine.mapper_regs[0] * 4 + (Value & mapper_page_mask_16k) * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (g_machine.mapper_regs[0] * 4 + (Value & mapper_page_mask_16k) * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n    if ((Addr | incomplete_address_decoding) == 0xFFFF)\r\n    {\r\n        g_machine.mapper_regs[2] = Value;\r\n        Map_8k_ROM(4, (g_machine.mapper_regs[0] * 4 + (Value & mapper_page_mask_16k) * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (g_machine.mapper_regs[0] * 4 + (Value & mapper_page_mask_16k) * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Mapper #26\r\n// Game Jiphap 30 Hap [SMS-MD] (KR)\r\nWRITE_FUNC(Write_Mapper_SMS_Korean_MD_FFFA)\r\n{\r\n    if (Addr == 0xFFFA) // Configurable segment -----------------------------------------------\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        g_machine.mapper_regs[1] = 0;\r\n        g_machine.mapper_regs[2] = 1;\r\n        Map_8k_ROM(0, (Value * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, (Value * 2 + 1) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, (Value * 2 + 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (Value * 2 + 3) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (Value * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (Value * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n    if (Addr == 0xFFFF)\r\n    {\r\n        g_machine.mapper_regs[1] = Value;\r\n        Map_8k_ROM(4, (g_machine.mapper_regs[0] * 2 + (Value & 0x0F) * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (g_machine.mapper_regs[0] * 2 + (Value & 0x0F) * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n    if (Addr == 0xFFFE)\r\n    {\r\n        g_machine.mapper_regs[2] = Value;\r\n        Map_8k_ROM(2, (g_machine.mapper_regs[0] * 2 + (Value & 0x0F) * 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (g_machine.mapper_regs[0] * 2 + (Value & 0x0F) * 2 + 1) & tsms.Pages_Mask_8k);\r\n        //return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\n// Mapper #27\r\n// 2 Hap in 1 (Moai-ui bomul, David-2)\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000)\r\n{\r\n    if (Addr == 0x2000) // Configurable segment -----------------------------------------------\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        Map_8k_ROM(2, (Value * 4 + 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (Value * 4 + 3) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (Value * 4 + 4) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (Value * 4 + 5) & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Mapper #39\r\n// 11 Hap Gam-Boy (KR)\r\nWRITE_FUNC(Write_Mapper_SMS_Korean_SMS_32KB_2000)\r\n{\r\n    if (Addr == 0x2000) // Configurable segment -----------------------------------------------\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        Map_8k_ROM(0, (Value * 4) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(1, (Value * 4 + 1) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(2, (Value * 4 + 2) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (Value * 4 + 3) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (Value * 4) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (Value * 4 + 1) & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\n// Mapper #40\r\n// Zemina Best 88 (KR)\r\n// Zemina Best 25 (KR)\r\n// Zemina Best 39 (KR)\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_SMS_8000)\r\n{\r\n    if (Addr == 0x8000) // Configurable segment -----------------------------------------------\r\n    {\r\n        // Special case to support Zemina Best 25 [Best 88] (KR)\r\n        if (g_machine.mapper_regs[0] == 0xFF) {\r\n            Value ^= 0x22;\r\n        }\r\n        g_machine.mapper_regs[0] = Value;\r\n        if (Value & 0x80) {\r\n            Map_8k_ROM(0, (Value ^ 3) & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, (Value ^ 2) & tsms.Pages_Mask_8k);\r\n        } else {\r\n            Map_8k_ROM(0, 0x3c & tsms.Pages_Mask_8k);\r\n            Map_8k_ROM(1, 0x3c & tsms.Pages_Mask_8k);\r\n        }\r\n        Map_8k_ROM(2, (Value ^ 1) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(3, (Value ^ 0) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(4, (Value ^ 3) & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, (Value ^ 2) & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Based on MSX ASCII 8KB mapper? http://bifi.msxnet.org/msxnet/tech/megaroms.html#ascii8\r\n// - This mapper requires 4 registers to save bank switching state.\r\n//   However, all other mappers so far used only 3 registers, stored as 3 bytes.\r\n//   Because of the current development state of MEKA and to avoid breaking save-state format\r\n//   for emulators that import the current MEKA save format (because the 3 mapper bytes are\r\n//   in the static \"SMS_TYPE\" structure), I decided to store those 4 registers packed each\r\n//   into 4-bits of 2 of the available bytes. It's not technically incorrect anyway since\r\n//   those variable are just our own representation of the hardware, but its error prone.\r\n// - Using 4-bits limits number of banks to 16 which is 128 KB, corresponding to the maximum\r\n//   game size currently known for this mapper.\r\n// - Using 4-bits chunks in 2 bytes instead of 6-bits chunks in all 3 bytes allows seeing\r\n//   the values in techinfo.c box in more intuitive way (since the first 2 8KB pages are\r\n//   not switchable the first register is kept as zero).\r\n// - If ever it happens that Sega 8-bits mappers gets standardized this whole system will\r\n//   be reworked and per-mapper state be taken into account in save states.\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_8KB_0003)\r\n{\r\n    switch (Addr)\r\n    {\r\n    case 0x0000:\r\n        {\r\n#ifdef DEBUG_PAGES\r\n            if (Value > tsms.Pages_Count_8k)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 4 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n            g_machine.mapper_regs[0] = Value;\r\n            Map_8k_ROM(4, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    case 0x0001:\r\n        {\r\n#ifdef DEBUG_PAGES\r\n            if (Value > tsms.Pages_Count_8k)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 5 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n            g_machine.mapper_regs[1] = Value;\r\n            Map_8k_ROM(5, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    case 0x0002:\r\n        {\r\n#ifdef DEBUG_PAGES\r\n            if (Value > tsms.Pages_Count_8k)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 2 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n            g_machine.mapper_regs[2] = Value;\r\n            Map_8k_ROM(2, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    case 0x0003:\r\n        {\r\n#ifdef DEBUG_PAGES\r\n            if (Value > tsms.Pages_Count_8k)\r\n            { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 3 set to non-existent page: %d\", CPU_GetPC, Value); }\r\n#endif\r\n            g_machine.mapper_regs[3] = Value;\r\n            Map_8k_ROM(3, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Write function for mapper #18: MAPPER_SMS_Korean_MSX_8KB_0300\r\nWRITE_FUNC(Write_Mapper_SMS_Korean_MSX_8KB_0300)\r\n{\r\n    const int incomplete_address_decoding_mask = 0xFF00;\r\n    const u16 addr_assumed = Addr & incomplete_address_decoding_mask;\r\n    switch (addr_assumed)\r\n    {\r\n    case 0x0000:\r\n    {\r\n        g_machine.mapper_regs[0] = Value;\r\n        Map_8k_ROM(4, Value & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n    case 0x0100:\r\n    {\r\n        g_machine.mapper_regs[1] = Value;\r\n        Map_8k_ROM(2, Value & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n    case 0x0200:\r\n    {\r\n        g_machine.mapper_regs[2] = Value;\r\n        Map_8k_ROM(1, Value & tsms.Pages_Mask_8k);\r\n        Map_8k_ROM(5, Value & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n    case 0x0300:\r\n    {\r\n        g_machine.mapper_regs[3] = Value;\r\n        Map_8k_ROM(3, Value & tsms.Pages_Mask_8k);\r\n        return;\r\n    }\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_SMS_Korean_Janggun)\r\n{\r\n    switch (Addr)\r\n    {\r\n    case 0xFFFE:\r\n        {\r\n            g_machine.mapper_regs[0] = Value;\r\n            if (Value & 0x40)\r\n                g_machine.mapper_janggun_bytes_flipping_flags |= ((1 << 2)|(1 << 3));\r\n            else\r\n                g_machine.mapper_janggun_bytes_flipping_flags &= ~((1 << 2)|(1 << 3));\r\n            Map_16k_ROM(2, (Value & tsms.Pages_Mask_16k)*2);\r\n            break;\r\n        }\r\n    case 0x4000:\r\n        {\r\n            g_machine.mapper_regs[1] = Value;\r\n            Map_8k_ROM(2, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    case 0x6000:\r\n        {\r\n            g_machine.mapper_regs[2] = Value;\r\n            Map_8k_ROM(3, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    case 0xFFFF:\r\n        {\r\n            g_machine.mapper_regs[3] = Value;\r\n            if (Value & 0x40)\r\n                g_machine.mapper_janggun_bytes_flipping_flags |= ((1 << 4)|(1 << 5));\r\n            else\r\n                g_machine.mapper_janggun_bytes_flipping_flags &= ~((1 << 4)|(1 << 5));\r\n            Map_16k_ROM(4, (Value & tsms.Pages_Mask_16k)*2);\r\n            break;\r\n        }\r\n    case 0x8000:\r\n        {\r\n            g_machine.mapper_regs[4] = Value;\r\n            Map_8k_ROM(4, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    case 0xA000:\r\n        {\r\n            g_machine.mapper_regs[5] = Value;\r\n            Map_8k_ROM(5, Value & tsms.Pages_Mask_8k);\r\n            return;\r\n        }\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\n// Write function for mapper #41\r\nWRITE_FUNC(Write_Mapper_MSX_Generic16_8000)\r\n{\r\n    switch (Addr)\r\n    {\r\n    case 0x8000:\r\n    Value = (Value & tsms.Pages_Mask_16k);\r\n    g_machine.mapper_regs[2] = Value;\r\n    Map_16k_ROM(4, g_machine.mapper_regs[2] * 2);\r\n    return;\r\n    }\r\n\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages[6][Addr] = Value; return;\r\n    case 7: Mem_Pages[7][Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error(Addr, Value);\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_SMS_DisplayUnit)\r\n{\r\n    switch (Addr >> 13)\r\n    {\r\n        // RAM [0x4000]\r\n        case 2: Mem_Pages [2] [0x4000 + (Addr & 0x07FF)] = Value; return;\r\n        // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n        case 6: Mem_Pages [6] [Addr] = Value; return;\r\n        case 7: Mem_Pages [7] [Addr] = Value; return;\r\n    }\r\n\r\n    Write_Error (Addr, Value);\r\n}\r\n\r\nREAD_FUNC (Read_Mapper_SMS_DisplayUnit)\r\n{\r\n   // if (Addr == 0x4000)\r\n   //     return (0xff);//Mem_Pages [2] [0x4000] | 0x80);  // FIXME\r\n    if (Addr == 0x8000)\r\n        return (Mem_Pages [2] [0x4000] | 0x80);  // FIXME\r\n    return (Mem_Pages [Addr >> 13] [Addr]);\r\n}\r\n\r\nWRITE_FUNC (Write_Mapper_93c46)\r\n{\r\n switch (Addr)\r\n   {\r\n   case 0x8000: // 93c46 Write (Set Lines)\r\n        EEPROM_93c46_Set_Lines (Value);\r\n        return;\r\n   case 0xFFFC: // 93c46 Control Register\r\n        EEPROM_93c46_Control (Value);\r\n        RAM [0x1FFC] = Value;\r\n        return;\r\n   case 0xFFFD: // Frame 0 ----------------------------------------------------\r\n        #ifdef DEBUG_PAGES\r\n          if (Value > tsms.Pages_Count_16k)\r\n             { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 0 set to non-existent page: %d\", CPU_GetPC, Value); return; }\r\n        #endif\r\n        RAM [0x1FFD] = g_machine.mapper_regs[0] = Value & tsms.Pages_Mask_16k;\r\n        Map_16k_ROM (0, g_machine.mapper_regs[0] * 2);\r\n        return;\r\n   case 0xFFFE: // Frame 1 ----------------------------------------------------\r\n        #ifdef DEBUG_PAGES\r\n          if (Value > tsms.Pages_Count_16k)\r\n             { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 1 set to non-existent page: %d\", CPU_GetPC, Value); return; }\r\n        #endif\r\n        RAM [0x1FFE] = g_machine.mapper_regs[1] = Value & tsms.Pages_Mask_16k;\r\n        Map_16k_ROM (2, g_machine.mapper_regs[1] * 2);\r\n        return;\r\n   case 0xFFFF: // Frame 2 ----------------------------------------------------\r\n        #ifdef DEBUG_PAGES\r\n          if (Value > tsms.Pages_Count_16k)\r\n             { Msg(MSGT_DEBUG, \"At PC=%04X: Frame 2 set to non-existent page: %d\", CPU_GetPC, Value); return; }\r\n        #endif\r\n        RAM [0x1FFF] = g_machine.mapper_regs[2] = Value & tsms.Pages_Mask_16k;\r\n        Map_16k_ROM (4, g_machine.mapper_regs[2] * 2);\r\n        return;\r\n   }\r\n switch (Addr >> 13)\r\n   {\r\n   // 93c46? Direct Access ----------------------------------------------------\r\n   case 4: if (Addr >= 0x8008 && Addr < 0x8088) { EEPROM_93c46_Direct_Write (Addr - 0x8008, Value); return; } break;\r\n   // RAM [0xC000] = [0xE000] -------------------------------------------------\r\n   case 6: Mem_Pages [6] [Addr] = Value; return;\r\n   case 7: Mem_Pages [7] [Addr] = Value; return;\r\n   }\r\n\r\n Write_Error (Addr, Value);\r\n}\r\n\r\n// FIXME-WIP\r\nWRITE_FUNC (Write_Mapper_SMS_ActionReplay)\r\n{\r\n switch (Addr >> 13)\r\n    {\r\n    // RAM [0x4000]..\r\n    case 2: Mem_Pages [2] [Addr] = Value; return;\r\n    case 3: Mem_Pages [3] [Addr] = Value; return;\r\n    // RAM [0xC000] = [0xE000] ------------------------------------------------\r\n    case 6: Mem_Pages [6] [Addr] = Value; return;\r\n    case 7: Mem_Pages [7] [Addr] = Value; return;\r\n    }\r\n\r\n Write_Error (Addr, Value);\r\n}\r\n\r\nREAD_FUNC (Read_Default)\r\n{\r\n    #ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\r\n    if (Addr >= 0xC000 && Addr <= 0xFFFF)\r\n    {\r\n        if (RAM_IsUninitialized[Addr&0x1FFF])\r\n        {\r\n            Msg(MSGT_DEBUG, \"At PC=$%04x, Read uninitialized RAM[$%04x]\", sms.R.PC.W, Addr);\r\n            //sms.R.Trace = 1;\r\n        }\r\n    }\r\n    #endif\r\n\r\n    const unsigned int page = (Addr >> 13);\r\n    return (Mem_Pages [page] [Addr]);\r\n}\r\n\r\nREAD_FUNC (Read_Mapper_SMS_Korean_Janggun)\r\n{\r\n    const unsigned int page = (Addr >> 13);\r\n    u8 b = Mem_Pages[page][Addr];\r\n\r\n    if (g_machine.mapper_janggun_bytes_flipping_flags & (1<<page))\r\n        b = Mapper_SMS_Korean_Janggun_BitReverseLUT[b];\r\n\r\n    return b;\r\n}\r\n\r\nREAD_FUNC (Read_Mapper_SG1000_Taiwan_MSX_Adapter_TypeA)\r\n{\r\n    const unsigned int page = (Addr >> 13);\r\n\r\n    // 0xC000->0xFFFF: SG-1000 work RAM\r\n    if (page >= 6)\r\n        Addr &= ~0x1800;\r\n\r\n    return Mem_Pages[page][Addr];\r\n}\r\n\r\nREAD_FUNC (Read_Mapper_93c46)\r\n{\r\n    // Addresses in the [8000h] range --------------------------------------------\r\n    if ((Addr >> 13) == 0x04 && (EEPROM_93c46.Enabled))\r\n    {\r\n        // 93c46 Serial Access ----------------------------------------------------\r\n        if (Addr == 0x8000)\r\n        {\r\n            // Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Read), sms.R.PC.W, Addr);\r\n            return EEPROM_93c46_Read();\r\n        }\r\n        // 93c46? Direct Access ---------------------------------------------------\r\n        if (Addr >= 0x8008 && Addr < 0x8088)\r\n            return EEPROM_93c46_Direct_Read(Addr - 0x8008);\r\n    }\r\n\r\n    return (Mem_Pages [Addr >> 13] [Addr]);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/mappers.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - mappers.h\n// Memory Mapper Emulation - Headers\n//-----------------------------------------------------------------------------\n\n#define LOG_READ()      \\\n   { Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Read), CPU_GetPC, Addr); }\n\n#define LOG_WRITE()      \\\n   { Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Write), CPU_GetPC, Value, Addr); }\n\n#ifdef DEBUG_MEM\n  void    Write_Error (int Addr, byte Value);\n#else\n  #define Write_Error(a,v)\n#endif\n\n//#define DEBUG_UNINITIALIZED_RAM_ACCESSES\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define MAPPER_Auto                             (-1)\n#define MAPPER_Standard                         (0)         // Standard Sega mapper.\n#define MAPPER_32kRAM                           (1)\n#define MAPPER_ColecoVision                     (2)\n#define MAPPER_CodeMasters                      (3)\n#define MAPPER_93c46                            (4)\n#define MAPPER_SG1000                           (5)         // FIXME: Emulating 4KB RAM when it should be 2KB !#@?\n#define MAPPER_SMS_ActionReplay                 (6)\n#define MAPPER_TVOekaki                         (7)\n#define MAPPER_SF7000                           (8)\n#define MAPPER_SMS_Korean_A000                  (9)         // Register at 0xA000.\n#define MAPPER_SMS_DisplayUnit                  (10)\n#define MAPPER_SMS_NoMapper                     (11)        // 0x0000->0xBFFF map to ROM. No mapper register.\n#define MAPPER_SMS_Korean_MSX_8KB_0003          (12)        // 8KB bank-switching (4 banks)\n#define MAPPER_SMS_Korean_Janggun               (13)        // 8KB bank-switching (4 banks) mixed with 16KB bank-switching\n#define MAPPER_SMS_4PakAllAction                (14)\n#define MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA  (15)        // 8KB RAM from 0x2000->0x3FFF + regular 2KB ram in 0xC000-0xFFFF range\n#define MAPPER_SMS_Korean_FFFF_HiCom            (16)        // Register at 0xFFFF to map 32 KB at 0x0000->0x8000\n#define MAPPER_SC3000_Survivors_Multicart       (17)\n#define MAPPER_SMS_Korean_MSX_8KB_0300          (18)        // Registers at 0x0000,0x0100,0x0200,0x0300 (Super Multi Game Super 75 in 1, Super Game World 75 etc.)\n#define MAPPER_SMS_Korean_2000_xor_1F           (19)        // Register at 0x2000 (128 Hap, Game Mo-eumjip 188 Hap etc.)\n#define MAPPER_SMS_Korean_BFFC                  (20)        // Register at 0xBFFC\n#define MAPPER_SMS_Korean_FFFE                  (21)        // Register at 0xFFFE (Super Game 45)\n#define MAPPER_SMS_Korean_FFF3_FFFC             (22)        // Registers at 0xFFF3 and 0xFFFC (Super Game 150, Super Game 270)\n#define MAPPER_SMS_Korean_0000_xor_FF           (23)        // Register at 0x0000 with MSX-oriented paging\n#define MAPPER_SMS_Korean_MD_FFF0               (24)        // Registers at 0xFFF0 and 0xFFFF (Mega Mode Super Game 30 [SMS-MD])\n#define MAPPER_SMS_Korean_MD_FFF5               (25)        // Registers at 0xFFF5 and 0xFFFF (Jaemiissneun Game Mo-eumjip 42/65 Hap [SMS-MD], Pigu Wang Hap ~ Jaemiiss-neun Game Mo-eumjip [SMS-MD])\n#define MAPPER_SMS_Korean_MD_FFFA               (26)        // Registers at 0xFFFA and 0xFFFF (Game Jiphap 30 Hap [SMS-MD])\n#define MAPPER_SMS_Korean_MSX_32KB_2000         (27)        // Register at 0x2000 (2 Hap in 1 (Moai-ui bomul, David-2))\n#define MAPPER_SMS_Korean_SMS_32KB_2000         (39)        // Register at 0x2000 (11 Hap Gam-Boy)\n#define MAPPER_SMS_Korean_MSX_SMS_8000          (40)        // Register at 0x8000 with 8KB granularity and both MSX and SMS game support (Zemina Best 88 [MISSING 64K])\n#define MAPPER_MSX_Generic16_8000               (41)        // Register at 0x8000 with 16KB granularity. Same as CodeMasters except initial mapping is 0 for all slots.\n\n#define READ_FUNC(_NAME)   u8 _NAME(register u16 Addr)\n#define WRITE_FUNC(_NAME)  void _NAME(register u16 Addr, register u8 Value)\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Mapper_InitializeLookupTables();\nvoid    Mapper_Get_RAM_Infos(int *plen, int *pstart_addr);\nint     Mapper_Autodetect();\n\n// Memory Handler -------------------------------------------------------------\nREAD_FUNC  (Read_Default);\nREAD_FUNC  (Read_Mapper_93c46);\nREAD_FUNC  (Read_Mapper_TVOekaki);\nREAD_FUNC  (Read_Mapper_SMS_DisplayUnit);\nREAD_FUNC  (Read_Mapper_SMS_Korean_Janggun);\nREAD_FUNC  (Read_Mapper_SG1000_Taiwan_MSX_Adapter_TypeA);\n//-----------------------------------------------------------------------------\nWRITE_FUNC (Write_Default);\nWRITE_FUNC (Write_Mapper_SG1000);\nWRITE_FUNC (Write_Mapper_32kRAM);\nWRITE_FUNC (Write_Mapper_CodeMasters);\nWRITE_FUNC (Write_Mapper_93c46);\nWRITE_FUNC (Write_Mapper_SMS_ActionReplay);\nWRITE_FUNC (Write_Mapper_TVOekaki);\nWRITE_FUNC (Write_Mapper_SF7000);\nWRITE_FUNC (Write_Mapper_SMS_Korean_A000);\nWRITE_FUNC (Write_Mapper_SMS_Korean_BFFC);\nWRITE_FUNC (Write_Mapper_SMS_DisplayUnit);\nWRITE_FUNC (Write_Mapper_SMS_NoMapper);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_8KB_0003);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_8KB_0300);\nWRITE_FUNC (Write_Mapper_SMS_Korean_Janggun);\nWRITE_FUNC (Write_Mapper_SMS_4PakAllAction);\nWRITE_FUNC (Write_Mapper_SG1000_Taiwan_MSX_Adapter_TypeA);\nWRITE_FUNC (Write_Mapper_SMS_Korean_FFFF_HiCom);\nWRITE_FUNC (Write_Mapper_SMS_Korean_2000_xor_1F);\nWRITE_FUNC (Write_Mapper_SMS_Korean_FFFE);\nWRITE_FUNC (Write_Mapper_SMS_Korean_FFF3_FFFC);\nWRITE_FUNC (Write_Mapper_SMS_Korean_0000_xor_FF);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF0);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF5);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFFA);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000);\nWRITE_FUNC (Write_Mapper_SMS_Korean_SMS_32KB_2000);\nWRITE_FUNC (Write_Mapper_SMS_Korean_MSX_SMS_8000);\nWRITE_FUNC (Write_Mapper_MSX_Generic16_8000);\n//-----------------------------------------------------------------------------\nvoid Out_SC3000_SurvivorsMulticarts_DataWrite(u8 v);\n\nextern void Map_8k_RAM    (int page, int ram_page);\nextern void Map_8k_ROM    (int page, int rom_page);\nextern void Map_8k_Other  (int page, void *);\n\nextern void Map_16k_ROM   (int page, int rom_page);\nextern void Map_16k_Other (int page, void *);\n\n//-----------------------------------------------------------------------------\n\n#ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES\nextern u8 RAM_IsUninitialized[0x2000];\n#endif\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/meka.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA\n// Sega Master System / Game Gear / SG-1000 / SC-3000 / SF-7000 / ColecoVision emulator\n//-----------------------------------------------------------------------------\n// Omar Cornut (Bock) & MEKA team 1998-2025\n// Sound engine by Hiromitsu Shioya (Hiroshi) in 1998-1999\n// Z80 CPU core by Marat Faizullin, 1994-1998\n//-----------------------------------------------------------------------------\n// MEKA - meka.c\n// Entry points and various initialization functions\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"app_filebrowser.h\"\n#include \"app_options.h\"\n#include \"app_tileview.h\"\n#include \"bios.h\"\n#include \"blit.h\"\n#include \"blitintf.h\"\n#include \"capture.h\"\n#include \"config.h\"\n#include \"coleco.h\"\n#include \"db.h\"\n#include \"debugger.h\"\n#include \"desktop.h\"\n#include \"effects.h\"\n#include \"fdc765.h\"\n#include \"file.h\"\n#include \"fskipper.h\"\n#include \"glasses.h\"\n#include \"inputs_f.h\"\n#include \"inputs_i.h\"\n#include \"mappers.h\"\n#include \"palette.h\"\n#include \"patch.h\"\n#include \"setup.h\"\n#include \"textbox.h\"\n#include \"tvtype.h\"\n#include \"video.h\"\n#include \"video_m5.h\"\n#include \"vlfn.h\"\n#include \"vmachine.h\"\n#ifdef ARCH_WIN32\n#include <commctrl.h>\n#endif\n#include <allegro5/allegro_image.h>\n#include <allegro5/allegro_ttf.h>\n\n//-----------------------------------------------------------------------------\n// Globals\n//-----------------------------------------------------------------------------\n\nextern \"C\" // C-style mangling for ASM linkage\n{\nOPT_TYPE                opt;\nTGFX_TYPE               tgfx;\nSMS_TYPE                sms;\nTSMS_TYPE               tsms;\n}\n\nt_machine               g_machine;\nt_meka_env              g_env;\nt_media_image           g_media_rom;            // FIXME-WIP: Not fully used\nt_meka_config    g_config;\n\nextern \"C\"  // C-style mangling for ASM linkage\n{\nu8      RAM[0x10000];               // RAM\nu8      SRAM[0x8000];               // Save RAM\nu8      VRAM[0x4000];               // Video RAM\nu8      PRAM[0x40];                 // Palette RAM\nu8 *    ROM;                        // Emulated ROM\nu8 *    Game_ROM;                   // Cartridge ROM\nu8 *    Game_ROM_Computed_Page_0;   // Cartridge ROM computed first page\nu8 *    Mem_Pages [8];              // Pointer to memory pages\n}\n\nALLEGRO_DISPLAY*        g_display = NULL;\nALLEGRO_EVENT_QUEUE*    g_display_event_queue = NULL;\nALLEGRO_LOCKED_REGION*  g_screenbuffer_locked_region = NULL;\nALLEGRO_BITMAP*         g_screenbuffer_locked_buffer = NULL;\nint                     g_screenbuffer_format = 0;\nint                     g_gui_buffer_format = 0;\n\nALLEGRO_BITMAP *screenbuffer = NULL, *screenbuffer_next = NULL;\nALLEGRO_BITMAP *screenbuffer_1 = NULL, *screenbuffer_2 = NULL;\nALLEGRO_BITMAP *fs_out = NULL;\nALLEGRO_BITMAP *gui_buffer = NULL;\nALLEGRO_BITMAP *gui_background = NULL;\n\n// Note: non floating-point constructors seems to fail at static construction.\nALLEGRO_COLOR COLOR_BLACK = al_map_rgb_f(0.0f,0.0f,0.0f);\nALLEGRO_COLOR COLOR_WHITE = al_map_rgb_f(1.0f,1.0f,1.0f);\nALLEGRO_COLOR COLOR_DEBUG_BACKDROP = al_map_rgb_f(222.0f/255.0f,222.0f/255.0f,101.0f/255.0f);\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n#if defined(_MSC_VER)\nFILE _iob[] = { *stdin, *stdout, *stderr };\n\nextern \"C\" FILE * __cdecl __iob_func()\n{\n    return _iob;\n}\n#endif\n\n//-----------------------------------------------------------------------------\n// FIXME: this function is pretty old and is basically a left-over or\n// everything that was not moved elsewhere.\n//-----------------------------------------------------------------------------\nstatic void Init_Emulator()\n{\n    Video_Init();\n\n    memset(RAM, 0, 0x10000);        // RAM: 64 Kb (max=SF-7000)\n    memset(SRAM, 0, 0x8000);        // SRAM: 32 Kb (max)\n    memset(VRAM, 0, 0x4000);        // VRAM: 16 Kb\n    memset(PRAM, 0, 0x0040);        // PRAM: 64 bytes\n    ROM = Game_ROM_Computed_Page_0 = (u8*)Memory_Alloc(0x4000); // 16 kbytes (one page)\n    memset(Game_ROM_Computed_Page_0, 0, 0x4000);\n    Game_ROM = NULL;\n\n    tsms.Pages_Count_8k = 1;\n    tsms.Pages_Count_16k = 1;\n\n    RdZ80 = RdZ80_NoHook = Read_Default;\n    drv_set (g_machine.driver_id);\n}\n\nstatic void Init_LookUpTables()\n{\n    Coleco_Init_Table_Inputs();\n    Mapper_InitializeLookupTables();\n}\n\n// Initialize default configuration settings\nstatic void Init_Default_Values()\n{\n    g_env.debug_dump_infos = false;\n\n    // IPeriod\n    opt.IPeriod = opt.Cur_IPeriod = 228;\n    opt.IPeriod_Coleco = 228; // 215\n    opt.IPeriod_Sg1000_Sc3000 = 228;\n\n    opt.Layer_Mask = LAYER_BACKGROUND | LAYER_SPRITES;\n\n    opt.GUI_Inited = false;\n    opt.Current_Key_Pressed = 0;\n    opt.State_Current = 0;\n    opt.State_Load = -1;\n    opt.Setup_Interactive_Execute = false;\n    opt.Force_Quit = false;\n\n    // Machine\n    g_machine.driver_id = DRV_SMS;\n\n    g_config.loaded_configuration_file     = false;\n\n    g_config.country                       = COUNTRY_EXPORT;\n    g_config.sprite_flickering             = SPRITE_FLICKERING_AUTO;\n    g_config.enable_BIOS                   = true;\n    g_config.show_product_number           = false;\n    g_config.show_fullscreen_messages      = true;\n    g_config.enable_NES                    = false;\n    g_config.allow_opposite_directions     = false;\n    g_config.start_in_gui                  = true;\n\n    // Applet: Game Screen\n    g_config.game_window_scale             = 1.0f;\n\n    // Applet: File Browser\n    g_config.fb_close_after_load           = false;\n    g_config.fb_uses_DB                    = true;\n    g_config.fullscreen_after_load         = true;\n\n    // Applet: Debugger\n    g_config.debugger_disassembly_display_labels = true;\n    g_config.debugger_log_enabled          = true;\n\n    // Applet: Memory Editor\n    g_config.memory_editor_lines             = 16;\n    g_config.memory_editor_columns           = 16;\n\n    // Video\n    g_config.video_driver                    = g_video_driver_default;\n    g_config.video_fullscreen                = false;\n    g_config.video_game_format_request       = ALLEGRO_PIXEL_FORMAT_ANY_16_NO_ALPHA;\n    g_config.video_gui_format_request        = ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA;\n\n    g_config.video_mode_game_vsync           = false;\n    g_config.video_mode_gui_res_x            = 1024;\n    g_config.video_mode_gui_res_y            = 768;\n    g_config.video_mode_gui_refresh_rate     = 0;    // Auto\n    g_config.video_mode_gui_vsync            = false;\n\n    // Capture\n    g_config.capture_filename_template       = \"%s-%02d.png\";\n    g_config.capture_crop_scrolling_column   = true;\n    g_config.capture_crop_align_8x8          = false;\n    g_config.capture_include_gui             = true;\n\n    // Fonts\n    g_config.font_menus                      = FONTID_LARGE; // FONTID_CRISP;\n    g_config.font_messages                   = FONTID_PROGGY_CLEAN; //FONTID_PROGGYCLEAN;\n    g_config.font_options                    = FONTID_PROGGY_CLEAN; //FONTID_PROGGYCLEAN;\n    g_config.font_debugger                   = FONTID_PROGGY_SQUARE; //FONTID_PROGGYCLEAN;\n    g_config.font_documentation              = FONTID_PROGGY_CLEAN; //FONTID_PROGGYCLEAN;\n    g_config.font_techinfo                   = FONTID_PROGGY_SQUARE; //FONTID_PROGGYCLEAN;\n    g_config.font_filebrowser                = FONTID_PROGGY_CLEAN; //FONTID_PROGGYCLEAN;\n    g_config.font_about                      = FONTID_PROGGY_CLEAN; //FONTID_PROGGYCLEAN;\n\n    // Media\n    // FIXME: yet not fully used\n    g_media_rom.type        = MEDIA_IMAGE_ROM;\n    g_media_rom.data        = NULL;\n    g_media_rom.data_size   = 0;\n    g_media_rom.mekacrc.v[0]= 0;\n    g_media_rom.mekacrc.v[1]= 0;\n    g_media_rom.crc32       = 0;\n\n    g_machine_pause_requests = 0;\n\n    Blitters_Init_Values();\n    Frame_Skipper_Init_Values();\n\n    strcpy(FB.current_directory, \".\");\n\n    TB_Message_Init_Values();\n    Sound_Init_Config();\n    TVType_Init_Values();\n    Glasses_Init_Values();\n    TileViewer_Init_Values();\n    Skins_Init_Values();\n\n    #ifdef MEKA_Z80_DEBUGGER\n        Debugger_Init_Values();\n    #endif\n}\n\nstatic void Free_Memory()\n{\n    free(Game_ROM_Computed_Page_0);\n    BIOS_Free_Roms();\n    if (Game_ROM)\n    {\n        free(Game_ROM);\n        Game_ROM = NULL;\n    }\n}\n\nstatic void Close_Emulator()\n{\n    Sound_Close         ();\n    Desktop_Close       ();\n    Fonts_Close         ();\n    FDC765_Close        ();\n    Palette_Close       ();\n    Inputs_Sources_Close();\n#ifdef MEKA_JOYPAD\n    Inputs_Joystick_Close();\n#endif\n    GUI_Close           ();\n    Free_Memory         ();\n    FB_Close            ();\n    DB_Close            ();\n    Blitters_Close      ();\n    Glasses_Close       ();\n    Data_Close          ();\n}\n\n// Remove Allegro installed callback\n// This is the first function to call on shutdown, to avoid getting called\n// during the shutdown process (which sometimes makes things crash).\n/*\nstatic void Close_Callback()\n{\n    al_set_close_button_callback(NULL);\n}\n*/\n\n// Change to starting directory\n// This function is registered in the atexit() table to be called on quit\nstatic void Close_Emulator_Starting_Dir()\n{\n    chdir(g_env.Paths.StartingDirectory);\n}\n\nstatic int Init_Allegro()\n{\n    ConsolePrint(Msg_Get(MSG_Init_Allegro));\n\n    // Initialize timer BEFORE allegro\n    // OSD_Timer_Initialize();\n\n    al_init();\n    al_init_image_addon();\n    al_init_font_addon();\n    al_init_ttf_addon();\n    al_init_primitives_addon();\n\n    // Keyboard, mouse\n    al_install_keyboard();\n    g_env.mouse_installed = al_install_mouse();\n\n    // Create event queues\n    g_display_event_queue = al_create_event_queue();\n\n    // Get Allegro version and print it in console\n    const unsigned int allegro_version = al_get_allegro_version();\n    ConsolePrintf(\" version %d.%d.%d (release %d)\\n\", (allegro_version >> 24), (allegro_version >> 16) & 0xFF, (allegro_version >> 8) & 0xFF, (allegro_version & 0xFF));\n\n    return (1);\n}\n\nstatic void Close_Allegro()\n{\n    al_shutdown_primitives_addon();\n    al_shutdown_ttf_addon();\n    al_shutdown_font_addon();\n    al_shutdown_image_addon();\n\n    al_uninstall_mouse();\n    al_uninstall_audio();\n    al_uninstall_system();\n}\n\nstatic void Init_GUI()\n{\n    ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Init_GUI));\n    GUI_Init();\n}\n\n// MAIN FUNCTION --------------------------------------------------------------\nint main(int argc, char **argv)\n{\n    #ifdef ARCH_WIN32\n        // Need for XP manifest stuff\n        InitCommonControls();\n        #pragma comment(lib, \"comctl32.lib\")\n    #endif\n\n#ifdef ARCH_WIN32\n    //_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );\n#endif\n\n    ConsoleInit(); // First thing to do\n    #ifdef ARCH_WIN32\n        ConsolePrintf (\"%s (built %s %s)\\n(c) %s %s\\n--\\n\", MEKA_NAME_VERSION, MEKA_BUILD_DATE, MEKA_BUILD_TIME, MEKA_DATE, MEKA_AUTHORS);\n    #else\n        ConsolePrintf (\"\\n%s (c) %s %s\\n--\\n\", MEKA_NAME_VERSION, MEKA_DATE, MEKA_AUTHORS);\n    #endif\n\n    // Wait for Win32 console signal\n    if (!ConsoleWaitForAnswer(true))\n        return (0);\n\n    // Save command line parameters\n    g_env.argc = argc;\n    g_env.argv = (char**)malloc (sizeof(char *) * (g_env.argc + 1));\n    int i;\n    for (i = 0; i != g_env.argc; i++)\n        g_env.argv[i] = strdup(argv[i]);\n    g_env.argv[i] = NULL;\n\n    // FIXME: add 'init system' here\n\n    // Initializations\n    g_env.state = MEKA_STATE_INIT;\n    Filenames_Init         (); // Set Filenames Values\n    Messages_Init          (); // Load MEKA.MSG and init messaging system\n    Init_Default_Values    (); // Set Defaults Variables\n    Command_Line_Parse     (); // Parse Command Line (1)\n    Init_Allegro           (); // Initialize Allegro Library\n    Fonts_Init             (); // Initialize Fonts system\n    Capture_Init           (); // Initialize Screen capture\n    Configuration_Load     (); // Load Configuration File\n    atexit (Close_Emulator_Starting_Dir);\n\n    Setup_Interactive_Init (); // Show Interactive Setup if asked to\n    Frame_Skipper_Init     (); // Initialize Auto Frame Skipper\n    DB_Init                (g_env.Paths.DataBaseFile); // Initialize and load DataBase file\n    Patches_List_Init      (); // Load Patches List\n    VLFN_Init              (); // Load Virtual Long Filename List\n    Skins_Init             (); // Load Skin List\n    Blitters_Init          (); // Load Blitter List\n    Inputs_Init            (); // Initialize Inputs and load inputs sources list\n    Blit_Init              (); // Initialize Blitter\n    Random_Init            (); // Initialize Random Number Generator\n    Effects_TV_Init        ();  // Initialize TV snow effect\n    FDC765_Init            (); // Initialize Floppy Disk emulation\n    Data_Init              (); // Load datafile\n    Init_Emulator          (); // Initialize Emulation\n    Palette_Init           (); // Initialize Palette system\n    Init_LookUpTables      (); // Initialize Look-up tables\n    Machine_Init           (); // Initialize Virtual Machine\n\n    Sound_Init             (); // Initialize Sound\n#ifdef MEKA_JOYPAD\n    Inputs_Joystick_Init   (); // Initialize Joysticks. \n#endif\n\n    // Initialization complete\n    ConsolePrintf (\"%s\\n--\\n\", Msg_Get(MSG_Init_Completed));\n\n    // Save configuration file early on (so that bad drivers, will still create a default .cfg file etc.)\n    if (!g_config.loaded_configuration_file)\n        Configuration_Save();\n\n    // Setup display (fullscreen/GUI)\n    if ((g_machine_flags & MACHINE_RUN) == MACHINE_RUN && !g_config.start_in_gui)\n        g_env.state = MEKA_STATE_GAME;\n    else\n        g_env.state = MEKA_STATE_GUI;\n    Video_Setup_State();\n\n    Machine_Reset          (); // Reset Emulated Machine (set default values)\n    Init_GUI               (); // Initialize Graphical User Interface\n    FB_Init_2              (); // Finish initializing the file browser\n\n    // Load ROM from command line if necessary\n    Load_ROM_Command_Line();\n\n    // Wait for Win32 console signal\n    if (!ConsoleWaitForAnswer(true))\n        return (0);\n    ConsoleClose(); // Close Console\n\n    // Start main program loop\n    // Everything runs from there.\n    // Z80_Opcodes_Usage_Reset();\n    Main_Loop(); \n    // Z80_Opcodes_Usage_Print();\n\n    // Shutting down emulator...\n    g_env.state = MEKA_STATE_SHUTDOWN;\n    Video_Setup_State      (); // Switch back to text mode\n    BMemory_Save           (); // Write Backed Memory if necessary\n    Configuration_Save     (); // Write Configuration File\n    Write_Inputs_Src_List  (); // Write Inputs Definition File\n    VLFN_Close             (); // Write Virtual Long Filename List\n    Close_Emulator         (); // Close Emulator\n    Show_End_Message       (); // Show End Message\n\n    Messages_Close();\n    Close_Allegro();\n\n    return (0);\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/meka.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - meka.h\r\n// Main variables, headers, prototypes and constants\r\n//-----------------------------------------------------------------------------\r\n\r\n// Z80 CPU Clock (3.579540 MHz) -----------------------------------------------\r\n// FIXME: this should be obsoleted by what is in TVTYPE.C/.H\r\n#define Z80_DEFAULT_CPU_CLOCK   (3579540 /*3579545*/) // Emu use 60*262*228 = 3584160?\r\n\r\n// Emulated screen resolutions ------------------------------------------------\r\n#define SMS_RES_X               (256)\r\n#define SMS_RES_Y               (192)\r\n#define SMS_RES_Y_TOTAL         (224)\r\n#define GG_RES_X                (160)\r\n#define GG_RES_Y                (144)\r\n#define MAX_RES_X               SMS_RES_X\r\n#define MAX_RES_Y               SMS_RES_Y_TOTAL\r\n\r\n// Max length of a message ----------------------------------------------------\r\n#define MSG_MAX_LEN             (16384)\r\n\r\n// Max tiles (in video mode 5)\r\n#define MAX_TILES               (512)\r\n\r\n// Fixed colors\r\nextern ALLEGRO_COLOR            COLOR_BLACK;\r\nextern ALLEGRO_COLOR            COLOR_WHITE;\r\nextern ALLEGRO_COLOR            COLOR_DEBUG_BACKDROP;   // When background render is disabled\r\n\r\n#define COLOR_BLACK16           0x0000\r\n#define COLOR_WHITE16           0xFFFF\r\n\r\n// Border Color\r\n// FIXME: Unsupported\r\n#define BORDER_COLOR            COLOR_BLACK     //((sms.VDP[7] & 15) + 16)\r\n#define BORDER_COLOR16          COLOR_BLACK16\r\n\r\nextern \"C\"  // C-style mangling\r\n{\r\nextern u8      RAM[0x10000];               // RAM\r\nextern u8      SRAM[0x8000];               // Save RAM\r\nextern u8      VRAM[0x4000];               // Video RAM\r\nextern u8      PRAM[0x40];                 // Palette RAM\r\nextern u8 *    ROM;                        // Emulated ROM\r\nextern u8 *    Game_ROM;                   // Cartridge ROM\r\nextern u8 *    Game_ROM_Computed_Page_0;   // Cartridge ROM computed first page\r\nextern u8 *    Mem_Pages[8];               // Pointer to memory pages\r\n};\r\n\r\n// Flags for layer handling ---------------------------------------------------\r\n#define LAYER_BACKGROUND        (0x01)\r\n#define LAYER_SPRITES           (0x02)\r\n\r\n// Main MEKA state ------------------------------------------------------------\r\nenum t_meka_state\r\n{\r\n    MEKA_STATE_INIT,\r\n    MEKA_STATE_GAME,\r\n    MEKA_STATE_GUI,\r\n    MEKA_STATE_SHUTDOWN,\r\n};\r\n\r\n// Battery Backed RAM Macros --------------------------------------------------\r\n#define SRAM_Active             (sms.SRAM_Mapping_Register & 0x08)\r\n#define SRAM_Page               (sms.SRAM_Mapping_Register & 0x04)\r\n\r\n// On Board RAM Macros (currently only for Ernie Els Golf)\r\n#define ONBOARD_RAM_EXIST       (0x20)\r\n#define ONBOARD_RAM_ACTIVE      (0x40)\r\n\r\n// Variables needed by one emulated SMS\r\n// FIXME: reconceptualize those stuff, this is pure, old crap\r\nstruct SMS_TYPE\r\n{\r\n    // CPU State\r\n#ifdef MARAT_Z80\r\n    Z80   R;                              // CPU Registers (Marat Faizullin)\r\n#elif RAZE_Z80\r\n    void *CPU;                            // CPU Registers (Richard Mitton)\r\n#elif MAME_Z80\r\n    // nothing. currently implemented as global\r\n#endif\r\n    // Other State\r\n    u8      VDP [16];                      // VDP Registers\r\n    u8      __UNUSED__PRAM_Address;        // Current palette address\r\n    // NOTE: variable below (VDP_Status) is modified from videoasm.asm, do NOT move it\r\n    u8      VDP_Status;                    // Current VDP status\r\n    u16     VDP_Address;                   // Current VDP address\r\n    u8      VDP_Access_Mode;               // 0: Address Low - 1: Address High\r\n    u8      VDP_Access_First;              // Address Low Latch\r\n    u8      VDP_ReadLatch;                 // Read Latch\r\n    u8      VDP_Pal;                       // Currently Reading Palette ?\r\n    u8      Country;                       // 0: English - 1: Japanese\r\n    int     Lines_Left;                    // Lines Left before H-Blank\r\n    u8      Pending_HBlank;                // Pending HBL interrupt\r\n    u8      Pending_NMI;                   // Pending NMI interrupt (for Coleco emulation)\r\n    u8      Glasses_Register;              // 3-D Glasses Register\r\n    u8      SRAM_Pages;                    // SRAM pages used\r\n    u8      SRAM_Mapping_Register;         // SRAM status + mapping offset\r\n    u8      FM_Magic;                      // FM Latch (for detection)\r\n    u8      FM_Register;                   // FM Register\r\n    u8      Input_Mode;   // Port 0xDE     // 0->6: Keyboard - 7: Joypad\r\n};\r\n\r\n// Temporary (not saved) data for one machine\r\n// FIXME: re-conceptualize those stuff, this is pure, old crap\r\nstruct TSMS_TYPE\r\n{\r\n    u16     Control [8];                   // 0->6 = Keyboard - 7: Joypads\r\n    u8      Control_GG;\r\n    u8      Control_Check_GUI;\r\n    u8      Control_Start_Pause;\r\n    int     VDP_Line;\r\n    int     Pages_Mask_8k,  Pages_Count_8k;\r\n    int     Pages_Mask_16k, Pages_Count_16k;\r\n    long    Size_ROM;\r\n    u8      Port3F;\r\n    int     VDP_VideoMode, VDP_New_VideoMode;\r\n    int     VDP_Video_Change;\r\n};\r\n\r\n// Bits for gfx.Tile_Dirty\r\n#define TILE_DIRTY_DECODE       (0x01)\r\n#define TILE_DIRTY_REDRAW       (0x02)\r\n\r\n// Variables related to graphics - not saved in savestate\r\nstruct TGFX_TYPE\r\n{\r\n    u8  Tile_Dirty [MAX_TILES];\r\n    u8  Tile_Decoded [MAX_TILES] [64];\r\n};\r\n\r\nstruct OPT_TYPE\r\n{\r\n    bool        GUI_Inited;\r\n    int         IPeriod, IPeriod_Coleco, IPeriod_Sg1000_Sc3000, Cur_IPeriod;\r\n    int         Layer_Mask;\r\n    int         Current_Key_Pressed;\r\n    //----\r\n    bool        Force_Quit;                         // Set to TRUE for program to quit\r\n    int         State_Current;                      // Current savestate number\r\n    int         State_Load;                         // Set to != 1 to set and load a state on Machine_Reset();\r\n    bool        Setup_Interactive_Execute;          // Set to TRUE to execute an interactive setup on startup\r\n    int         GUI_Current_Page;\r\n};\r\n\r\n// Max path length\r\n#if defined(ARCH_UNIX) || defined(ARCH_MACOSX)\r\n#define FILENAME_LEN    (PATH_MAX)\r\n#else\r\n#define FILENAME_LEN    (1024)\r\n#endif\r\n\r\nextern \"C\"\r\n{\r\nextern OPT_TYPE   opt;\r\nextern TGFX_TYPE  tgfx;\r\nextern SMS_TYPE   sms;\r\nextern TSMS_TYPE  tsms;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// NEW STRUCTURES\r\n// Below are new structures which should hopefully obsolete everything above.\r\n// Members can eventually be moved out of old structure to those new ones.\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Emulated machine\r\n//-----------------------------------------------------------------------------\r\n\r\n// 'STATE' denote fields that should be saved in a savestate\r\n// 'CACHE' denote fields that directly derive from emulated machine data (eg: vdp register)\r\n// 'CONFIG' denote fields that derive from emulator configuration\r\nstruct t_machine_vdp_smsgg\r\n{\r\n    int                     model;                              // CONFIG\r\n    int                     sprite_shift_x;                     // CACHE    // 0 or 8\r\n    u8*                     name_table_address;                 // CACHE\r\n    u8*                     sg_color_table_address;             // CACHE    // Was g_machine.VDP.sg_color_table_address\r\n    u8*                     sg_pattern_gen_address;             // CACHE    // Was g_machine.VDP.pattern_gen_address\r\n    int                     sprite_pattern_gen_index;           // CACHE    // 0 or 256, SMS/GG only\r\n    u8*                     sprite_pattern_gen_address;         // CACHE\r\n    u8*                     sprite_attribute_table;             // CACHE\r\n\r\n    // Scrolling latches\r\n    u8                      scroll_x_latched;                   // STATE\r\n    u8                      scroll_y_latched;                   // STATE\r\n    u8                      scroll_x_latched_table[MAX_RES_Y];  // CACHE    // For tools\r\n};\r\n\r\n#define MAPPER_REGS_MAX     (6)                                 // Janggun-ui Adeul uses up to 6\r\n\r\nstruct t_machine\r\n{\r\n    int                     driver_id;                          // STATE    // t_machine_driver\r\n    int                     mapper;                             // STATE\r\n    u8                      mapper_regs[MAPPER_REGS_MAX];       // STATE\r\n    int                     mapper_regs_count;                  // CACHE    // Derived from 'mapper'\r\n    int                     mapper_janggun_bytes_flipping_flags;// CACHE\r\n    t_machine_vdp_smsgg     VDP;\r\n    struct t_tv_type*       TV;                                 // CONFIG\r\n    int                     TV_lines;                           // CONFIG   // Copy of TV->screen_lines\r\n};\r\n\r\nextern t_machine   g_machine;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Runtime environment\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_meka_env_paths\r\n{\r\n    char    EmulatorDirectory       [FILENAME_LEN];\r\n    char    StartingDirectory       [FILENAME_LEN];\r\n    char    ConfigurationFile       [FILENAME_LEN];\r\n    char    DataBaseFile            [FILENAME_LEN];\r\n    char    DataFile                [FILENAME_LEN];\r\n    char    SkinFile                [FILENAME_LEN];\r\n    char    ScreenshotDirectory     [FILENAME_LEN];\r\n    char    SavegameDirectory       [FILENAME_LEN];\r\n    char    BatteryBackedMemoryFile [FILENAME_LEN];\r\n    char    MusicDirectory          [FILENAME_LEN];\r\n    char    DebugDirectory          [FILENAME_LEN];\r\n\r\n    char    MediaImageFile          [FILENAME_LEN];     // FIXME: abstract media (per type/slot)\r\n\r\n    char    DocumentationMain       [FILENAME_LEN];\r\n    char    DocumentationCompat     [FILENAME_LEN];\r\n    char    DocumentationMulti      [FILENAME_LEN];\r\n    char    DocumentationChanges    [FILENAME_LEN];\r\n    char    DocumentationDebugger   [FILENAME_LEN];\r\n    // FIXME: add and use TECH.TXT ?\r\n};\r\n\r\nstruct t_meka_env\r\n{\r\n    t_meka_env_paths    Paths;\r\n    int                 mouse_installed;\r\n    int                 argc;\r\n    char**              argv;\r\n\r\n    t_meka_state        state;\r\n    bool                debug_dump_infos;\r\n};\r\n\r\nextern t_meka_env  g_env;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Configuration\r\n// All MEKA configuration options\r\n// Note: this is dependent of runtime emulation configuration, which can\r\n// be affected by various factors.\r\n// This structure should basically reflect the content of MEKA.CFG\r\n//-----------------------------------------------------------------------------\r\n\r\n// Values for g_config.sprite_flickering\r\n#define SPRITE_FLICKERING_NO        (0)\r\n#define SPRITE_FLICKERING_ENABLED   (1)\r\n#define SPRITE_FLICKERING_AUTO      (2) // Default\r\n\r\nstruct t_video_driver;\r\n\r\nstruct t_meka_config\r\n{\r\n    bool    loaded_configuration_file;\r\n\r\n    // Country\r\n    int     country;                    // Country to use\r\n    int     sprite_flickering;          // Set to emulate sprite flickering.\r\n    bool    allow_opposite_directions;  // Allows pressing of LEFT-RIGHT / UP-DOWN simultaneously.\r\n    bool    enable_BIOS;\r\n    bool    enable_NES;\r\n    bool    show_fullscreen_messages;\r\n    bool    show_product_number;\r\n    bool    start_in_gui;\r\n\r\n    // Applet: Game Screen\r\n    float   game_window_scale;\r\n\r\n    // Applet: File Browser\r\n    bool    fb_close_after_load;\r\n    bool    fb_uses_DB;\r\n    bool    fullscreen_after_load;\r\n\r\n    // Applet: Debugger\r\n    bool    debugger_disassembly_display_labels;\r\n    bool    debugger_log_enabled;\r\n\r\n    // Applet: Memory Editor\r\n    int             memory_editor_lines;\r\n    int             memory_editor_columns;\r\n\r\n    // Video\r\n    t_video_driver* video_driver;\r\n    bool            video_fullscreen;\r\n    int             video_game_format_request;\r\n    int             video_gui_format_request;\r\n\r\n    bool            video_mode_game_vsync;\r\n    int             video_mode_gui_res_x;\r\n    int             video_mode_gui_res_y;\r\n    bool            video_mode_gui_vsync;\r\n    int             video_mode_gui_refresh_rate;\r\n\r\n    // Capture\r\n    const char*     capture_filename_template;\r\n    bool            capture_crop_scrolling_column;\r\n    bool            capture_crop_align_8x8;\r\n    bool            capture_include_gui;\r\n\r\n    // Fonts (t_font_id)\r\n    int             font_menus;\r\n    int             font_messages;\r\n    int             font_options;\r\n    int             font_debugger;\r\n    int             font_documentation;\r\n    int             font_techinfo;\r\n    int             font_filebrowser;\r\n    int             font_about;\r\n};\r\n\r\nextern t_meka_config    g_config;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Media image\r\n// Old image of a loaded media (ROM, disk, etc...).\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_meka_crc\r\n{\r\n    u32         v[2];\r\n};\r\n\r\n#define MEDIA_IMAGE_ROM     (0)\r\n\r\nstruct t_media_image\r\n{\r\n    int         type;\r\n    u8*         data;\r\n    int         data_size;\r\n    t_meka_crc  mekacrc;\r\n    u32         crc32;\r\n    // char*    filename ?\r\n};\r\n\r\n// Currently a global to hold ROM infos.\r\n// Note that the structure is currently only half used and supported.\r\n// We only use the 'meka_checksum' and 'crc32' fields yet.\r\nextern t_media_image   g_media_rom;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data (video buffers)\r\n//-----------------------------------------------------------------------------\r\n\r\nextern ALLEGRO_DISPLAY*         g_display;\r\nextern ALLEGRO_EVENT_QUEUE*     g_display_event_queue;\r\nextern ALLEGRO_LOCKED_REGION*   g_screenbuffer_locked_region;\r\nextern ALLEGRO_BITMAP*          g_screenbuffer_locked_buffer;\r\nextern int                      g_screenbuffer_format;\r\nextern int                      g_gui_buffer_format;\r\n\r\n// Video buffers\r\nextern ALLEGRO_BITMAP* screenbuffer;            // Pointers to screen memory buffers\r\nextern ALLEGRO_BITMAP* screenbuffer_next;\r\nextern ALLEGRO_BITMAP* screenbuffer_1;          // Screen memory buffers\r\nextern ALLEGRO_BITMAP* screenbuffer_2;\r\nextern ALLEGRO_BITMAP* fs_out;                  // Fullscreen video buffer\r\nextern ALLEGRO_BITMAP* gui_buffer;              // GUI memory buffer\r\nextern ALLEGRO_BITMAP* gui_background;          // GUI Background\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/message.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - message.c\r\n// Messaging System, Languages, Console - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_game.h\"\r\n#include \"textbox.h\"\r\n#include \"libparse.h\"\r\n#ifdef ARCH_WIN32\r\n#include \"projects/msvc/resource.h\"\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     Lang_Set(t_menu_event *event);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_messages Messages;\r\n\r\nstruct S2I_TYPE\r\n{\r\n    const char *    name;\r\n    int             value;\r\n};\r\n\r\n#define __MSG_ADD(ID)   { #ID, ID }\r\nstatic const S2I_TYPE Msg_Translation_Table [] =\r\n{\r\n    __MSG_ADD(MSG_Welcome),\r\n    __MSG_ADD(MSG_Window_Title),\r\n    __MSG_ADD(MSG_Quit),\r\n\r\n    __MSG_ADD(MSG_About_BoxTitle),\r\n    __MSG_ADD(MSG_About_Line_Meka_Date),\r\n    __MSG_ADD(MSG_About_Line_Authors),\r\n    __MSG_ADD(MSG_About_Line_Homepage),\r\n\r\n    __MSG_ADD(MSG_Ok),\r\n    __MSG_ADD(MSG_Failed),\r\n    __MSG_ADD(MSG_Error_Base),\r\n    __MSG_ADD(MSG_Error_Error),\r\n    __MSG_ADD(MSG_Error_Memory),\r\n    __MSG_ADD(MSG_Error_Param),\r\n    __MSG_ADD(MSG_Error_Syntax),\r\n\r\n    __MSG_ADD(MSG_Error_Video_Mode),\r\n    __MSG_ADD(MSG_Error_Video_Mode_Back_To_GUI),\r\n\r\n    __MSG_ADD(MSG_Error_File_Not_Found),\r\n    __MSG_ADD(MSG_Error_File_Read),\r\n    __MSG_ADD(MSG_Error_File_Empty),\r\n\r\n    __MSG_ADD(MSG_Error_ZIP_Not_Supported),\r\n    __MSG_ADD(MSG_Error_ZIP_Loading),\r\n    __MSG_ADD(MSG_Error_ZIP_Internal),\r\n\r\n    __MSG_ADD(MSG_Error_Directory_Open),\r\n\r\n    __MSG_ADD(MSG_Must_Reset),\r\n    __MSG_ADD(MSG_No_ROM),\r\n\r\n    __MSG_ADD(MSG_Init_Allegro),\r\n    __MSG_ADD(MSG_Init_GUI),\r\n    __MSG_ADD(MSG_Init_Completed),\r\n\r\n    __MSG_ADD(MSG_Setup_Running),\r\n    __MSG_ADD(MSG_Setup_Setup),\r\n    __MSG_ADD(MSG_Setup_Video_Driver),\r\n    __MSG_ADD(MSG_Setup_Video_DisplayMode),\r\n    __MSG_ADD(MSG_Setup_SampleRate_Select),\r\n\r\n    __MSG_ADD(MSG_Capture_Done),\r\n    __MSG_ADD(MSG_Capture_Error),\r\n    __MSG_ADD(MSG_Capture_Error_File),\r\n\r\n    __MSG_ADD(MSG_SRAM_Loaded),\r\n    __MSG_ADD(MSG_SRAM_Load_Unable),\r\n    __MSG_ADD(MSG_SRAM_Wrote),\r\n    __MSG_ADD(MSG_SRAM_Write_Unable),\r\n\r\n    __MSG_ADD(MSG_93c46_Reset),\r\n    __MSG_ADD(MSG_93c46_Loaded),\r\n    __MSG_ADD(MSG_93c46_Load_Unable),\r\n    __MSG_ADD(MSG_93c46_Wrote),\r\n    __MSG_ADD(MSG_93c46_Write_Unable),\r\n\r\n    __MSG_ADD(MSG_TVType_Set),\r\n    __MSG_ADD(MSG_TVType_Info_Speed),\r\n\r\n    __MSG_ADD(MSG_Blitters_Loading),\r\n    __MSG_ADD(MSG_Blitters_Error_Not_Enough),\r\n    __MSG_ADD(MSG_Blitters_Error_Not_Found),\r\n    __MSG_ADD(MSG_Blitters_Error_Missing),\r\n    __MSG_ADD(MSG_Blitters_Error_Unrecognized),\r\n    __MSG_ADD(MSG_Blitters_Error_Incorrect_Value),\r\n    __MSG_ADD(MSG_Blitters_Set),\r\n\r\n    __MSG_ADD(MSG_NES_Activate),\r\n    __MSG_ADD(MSG_NES_Sucks),\r\n    __MSG_ADD(MSG_NES_Mapper_Unknown),\r\n    __MSG_ADD(MSG_NES_Deny_Facts),\r\n\r\n    __MSG_ADD(MSG_Debug_Init),\r\n    __MSG_ADD(MSG_Debug_Welcome),\r\n    __MSG_ADD(MSG_Debug_Not_Available),\r\n    __MSG_ADD(MSG_Debug_Trap_Read),\r\n    __MSG_ADD(MSG_Debug_Trap_Write),\r\n    __MSG_ADD(MSG_Debug_Trap_Port_Read),\r\n    __MSG_ADD(MSG_Debug_Trap_Port_Write),\r\n    __MSG_ADD(MSG_Debug_Symbols_Loaded),\r\n    __MSG_ADD(MSG_Debug_Symbols_Error),\r\n    __MSG_ADD(MSG_Debug_Symbols_Error_Line),\r\n\r\n    __MSG_ADD(MSG_DataDump_Mode_Ascii),\r\n    __MSG_ADD(MSG_DataDump_Mode_Raw),\r\n    __MSG_ADD(MSG_DataDump_Error),\r\n    __MSG_ADD(MSG_DataDump_Error_OB_Memory),\r\n    __MSG_ADD(MSG_DataDump_Error_Palette),\r\n    __MSG_ADD(MSG_DataDump_Error_Sprites),\r\n    __MSG_ADD(MSG_DataDump_Main),\r\n\r\n    __MSG_ADD(MSG_Doc_BoxTitle),\r\n    __MSG_ADD(MSG_Doc_File_Error),\r\n    __MSG_ADD(MSG_Doc_Enabled),\r\n    __MSG_ADD(MSG_Doc_Disabled),\r\n\r\n    __MSG_ADD(MSG_Flickering_Auto),\r\n    __MSG_ADD(MSG_Flickering_Yes),\r\n    __MSG_ADD(MSG_Flickering_No),\r\n\r\n    __MSG_ADD(MSG_Layer_BG_Disabled),\r\n    __MSG_ADD(MSG_Layer_BG_Enabled),\r\n    __MSG_ADD(MSG_Layer_Spr_Disabled),\r\n    __MSG_ADD(MSG_Layer_Spr_Enabled),\r\n\r\n    __MSG_ADD(MSG_FDC765_Unknown_Read),\r\n    __MSG_ADD(MSG_FDC765_Unknown_Write),\r\n    __MSG_ADD(MSG_FDC765_Disk_Too_Large1),\r\n    __MSG_ADD(MSG_FDC765_Disk_Too_Large2),\r\n    __MSG_ADD(MSG_FDC765_Disk_Too_Small1),\r\n    __MSG_ADD(MSG_FDC765_Disk_Too_Small2),\r\n\r\n    __MSG_ADD(MSG_Palette_BoxTitle),\r\n    __MSG_ADD(MSG_Palette_Disabled),\r\n    __MSG_ADD(MSG_Palette_Enabled),\r\n\r\n    __MSG_ADD(MSG_Message_BoxTitle),\r\n    __MSG_ADD(MSG_Message_Disabled),\r\n    __MSG_ADD(MSG_Message_Enabled),\r\n\r\n    __MSG_ADD(MSG_TechInfo_BoxTitle),\r\n    __MSG_ADD(MSG_TechInfo_Disabled),\r\n    __MSG_ADD(MSG_TechInfo_Enabled),\r\n\r\n    __MSG_ADD(MSG_TilesViewer_BoxTitle),\r\n    __MSG_ADD(MSG_TilesViewer_Disabled),\r\n    __MSG_ADD(MSG_TilesViewer_Enabled),\r\n    __MSG_ADD(MSG_TilesViewer_Tile),\r\n\r\n    __MSG_ADD(MSG_MemoryEditor_BoxTitle),\r\n    __MSG_ADD(MSG_MemoryEditor_Disabled),\r\n    __MSG_ADD(MSG_MemoryEditor_Enabled),\r\n    __MSG_ADD(MSG_MemoryEditor_WriteZ80_Unable),\r\n    __MSG_ADD(MSG_MemoryEditor_Address_Out_of_Bound),\r\n\r\n    __MSG_ADD(MSG_RapidFire_JxBx_On),\r\n    __MSG_ADD(MSG_RapidFire_JxBx_Off),\r\n\r\n    __MSG_ADD(MSG_FM_Enabled),\r\n    __MSG_ADD(MSG_FM_Disabled),\r\n\r\n    __MSG_ADD(MSG_Country_European_US),\r\n    __MSG_ADD(MSG_Country_JAP),\r\n\r\n    __MSG_ADD(MSG_Patch_Loading),\r\n    __MSG_ADD(MSG_Patch_Missing),\r\n    __MSG_ADD(MSG_Patch_Unrecognized),\r\n    __MSG_ADD(MSG_Patch_Value_Not_a_Byte),\r\n    __MSG_ADD(MSG_Patch_Out_of_Bound),\r\n\r\n    __MSG_ADD(MSG_Glasses_Enabled),\r\n    __MSG_ADD(MSG_Glasses_Disabled),\r\n    __MSG_ADD(MSG_Glasses_Show_Both),\r\n    __MSG_ADD(MSG_Glasses_Show_Left),\r\n    __MSG_ADD(MSG_Glasses_Show_Right),\r\n    __MSG_ADD(MSG_Glasses_Com_Port),\r\n    __MSG_ADD(MSG_Glasses_Com_Port2),\r\n    __MSG_ADD(MSG_Glasses_Com_Port_Open_Error),\r\n    __MSG_ADD(MSG_Glasses_Unsupported),\r\n\r\n    __MSG_ADD(MSG_Inputs_Joy_Init),\r\n    __MSG_ADD(MSG_Inputs_Joy_Init_None),\r\n    __MSG_ADD(MSG_Inputs_Joy_Init_Found),\r\n    __MSG_ADD(MSG_Inputs_Joy_Calibrate_Error),\r\n\r\n    __MSG_ADD(MSG_Inputs_Joypad),\r\n    __MSG_ADD(MSG_Inputs_LightPhaser),\r\n    __MSG_ADD(MSG_Inputs_PaddleControl),\r\n    __MSG_ADD(MSG_Inputs_SportsPad),\r\n    __MSG_ADD(MSG_Inputs_GraphicBoard),\r\n    __MSG_ADD(MSG_Inputs_GraphicBoardV2),\r\n    __MSG_ADD(MSG_Inputs_Play_Digital),\r\n    __MSG_ADD(MSG_Inputs_Play_Mouse),\r\n    __MSG_ADD(MSG_Inputs_Play_Digital_Unrecommended),\r\n    __MSG_ADD(MSG_Inputs_Play_Pen),\r\n    __MSG_ADD(MSG_Inputs_SK1100_Enabled),\r\n    __MSG_ADD(MSG_Inputs_SK1100_Disabled),\r\n\r\n    __MSG_ADD(MSG_Inputs_Config_BoxTitle),\r\n    __MSG_ADD(MSG_Inputs_Config_Peripheral_Click),\r\n    __MSG_ADD(MSG_Inputs_Config_Source_Enabled),\r\n    __MSG_ADD(MSG_Inputs_Config_Source_Player),\r\n    __MSG_ADD(MSG_Inputs_Config_Source_Emulate_Joypad),\r\n\r\n    __MSG_ADD(MSG_Inputs_Src_Loading),\r\n    __MSG_ADD(MSG_Inputs_Src_Not_Enough),\r\n    __MSG_ADD(MSG_Inputs_Src_Missing),\r\n    __MSG_ADD(MSG_Inputs_Src_Equal),\r\n    __MSG_ADD(MSG_Inputs_Src_Unrecognized),\r\n    __MSG_ADD(MSG_Inputs_Src_Syntax_Param),\r\n    __MSG_ADD(MSG_Inputs_Src_Inconsistency),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Keyboard),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Keyboard_Ok),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Joypad),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Joypad_Ok_A),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Joypad_Ok_B),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Mouse),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Mouse_Ok_B),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Mouse_No_A),\r\n    __MSG_ADD(MSG_Inputs_Src_Map_Cancelled),\r\n\r\n    __MSG_ADD(MSG_Machine_Pause),\r\n    __MSG_ADD(MSG_Machine_Resume),\r\n    __MSG_ADD(MSG_Machine_Reset),\r\n\r\n    __MSG_ADD(MSG_FDB_Loading),\r\n\r\n    __MSG_ADD(MSG_DB_Loading),\r\n    __MSG_ADD(MSG_DB_Name_Default),\r\n    __MSG_ADD(MSG_DB_Name_NoCartridge),\r\n    __MSG_ADD(MSG_DB_SyntaxError),\r\n\r\n    __MSG_ADD(MSG_Config_Loading),\r\n\r\n    __MSG_ADD(MSG_Datafile_Loading),\r\n\r\n    __MSG_ADD(MSG_Driver_Unknown),\r\n\r\n    __MSG_ADD(MSG_OverDump),\r\n\r\n    __MSG_ADD(MSG_Sound_Init),\r\n    __MSG_ADD(MSG_Sound_Init_Error_Audio),\r\n    __MSG_ADD(MSG_Sound_Init_Error_Blaster),\r\n    __MSG_ADD(MSG_Sound_Init_Error_Blaster_A),\r\n    __MSG_ADD(MSG_Sound_Init_Error_Voices),\r\n    __MSG_ADD(MSG_Sound_Init_Error_Voice_N),\r\n    __MSG_ADD(MSG_Sound_Init_Soundcard),\r\n    __MSG_ADD(MSG_Sound_Init_Soundcard_No),\r\n    __MSG_ADD(MSG_Sound_Init_SN76496),\r\n    __MSG_ADD(MSG_Sound_Init_YM2413_Digital),\r\n    __MSG_ADD(MSG_Sound_Stream_Error),\r\n    __MSG_ADD(MSG_Sound_Volume_Changed),\r\n\r\n    __MSG_ADD(MSG_Theme_Loading),\r\n    __MSG_ADD(MSG_Theme_Error_Not_Enough),\r\n    __MSG_ADD(MSG_Theme_Error_Missing_Theme_Name),\r\n    __MSG_ADD(MSG_Theme_Error_Syntax),\r\n    __MSG_ADD(MSG_Theme_Error_Attribute_Defined),\r\n    __MSG_ADD(MSG_Theme_Error_Out_of_Bound),\r\n    __MSG_ADD(MSG_Theme_Error_Theme_Missing_Data),\r\n    __MSG_ADD(MSG_Theme_Error_BG_Big),\r\n    __MSG_ADD(MSG_Theme_Error_BG),\r\n    __MSG_ADD(MSG_Theme_Error_BG_FileName),\r\n\r\n    __MSG_ADD(MSG_LoadROM_Loading),\r\n    __MSG_ADD(MSG_LoadROM_Success),\r\n    __MSG_ADD(MSG_LoadDisk_Success),\r\n    __MSG_ADD(MSG_LoadROM_Comment),\r\n    __MSG_ADD(MSG_LoadROM_SMSGG_Mode_Comment),\r\n    __MSG_ADD(MSG_LoadROM_Warning),\r\n    __MSG_ADD(MSG_LoadROM_Bad_Dump_Long),\r\n    __MSG_ADD(MSG_LoadROM_Bad_Dump_Short),\r\n    __MSG_ADD(MSG_LoadROM_Product_Num),\r\n    __MSG_ADD(MSG_LoadROM_SDSC),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Name),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Version),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Date),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Author),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Release_Note),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Unknown),\r\n    __MSG_ADD(MSG_LoadROM_SDSC_Error),\r\n    __MSG_ADD(MSG_LoadROM_Reload_Reloaded),\r\n    __MSG_ADD(MSG_LoadROM_Reload_No_ROM),\r\n\r\n    __MSG_ADD(MSG_FileBrowser_BoxTitle),\r\n    __MSG_ADD(MSG_FileBrowser_Drive),\r\n    __MSG_ADD(MSG_FileBrowser_Load),\r\n    __MSG_ADD(MSG_FileBrowser_Close),\r\n    __MSG_ADD(MSG_FileBrowser_LoadNames),\r\n    __MSG_ADD(MSG_FileBrowser_ReloadDir),\r\n\r\n    __MSG_ADD(MSG_FM_Editor_BoxTitle),\r\n    __MSG_ADD(MSG_FM_Editor_Enabled),\r\n    __MSG_ADD(MSG_FM_Editor_Disabled),\r\n\r\n    __MSG_ADD(MSG_Frameskip_Auto),\r\n    __MSG_ADD(MSG_Frameskip_Standard),\r\n    __MSG_ADD(MSG_FPS_Counter_Enabled),\r\n    __MSG_ADD(MSG_FPS_Counter_Disabled),\r\n\r\n    __MSG_ADD(MSG_Log_Need_Param),\r\n    __MSG_ADD(MSG_Log_Session_Start),\r\n\r\n    __MSG_ADD(MSG_Load_Need_Param),\r\n    __MSG_ADD(MSG_Load_Error),\r\n    __MSG_ADD(MSG_Load_Not_Valid),\r\n    __MSG_ADD(MSG_Load_Success),\r\n    __MSG_ADD(MSG_Load_Version),\r\n    __MSG_ADD(MSG_Load_Wrong_System),\r\n    __MSG_ADD(MSG_Load_Massage),\r\n    __MSG_ADD(MSG_Save_Not_in_BIOS),\r\n    __MSG_ADD(MSG_Save_Error),\r\n    __MSG_ADD(MSG_Save_Success),\r\n    __MSG_ADD(MSG_Save_Slot),\r\n\r\n    __MSG_ADD(MSG_Options_BoxTitle),\r\n    __MSG_ADD(MSG_Options_Close),\r\n    __MSG_ADD(MSG_Options_BIOS_Enable),\r\n    __MSG_ADD(MSG_Options_DB_Display),\r\n    __MSG_ADD(MSG_Options_Product_Number),\r\n    __MSG_ADD(MSG_Options_Bright_Palette),\r\n    __MSG_ADD(MSG_Options_Allow_Opposite_Directions),\r\n    __MSG_ADD(MSG_Options_Load_Close),\r\n    __MSG_ADD(MSG_Options_Load_FullScreen),\r\n    __MSG_ADD(MSG_Options_FullScreen_Messages),\r\n    __MSG_ADD(MSG_Options_GUI_VSync),\r\n    __MSG_ADD(MSG_Options_Capture_Crop_Align),\r\n    __MSG_ADD(MSG_Options_NES_Enable),\r\n    __MSG_ADD(MSG_Options_GUI_GameWindowScale),\r\n\r\n    __MSG_ADD(MSG_Language_Set),\r\n    __MSG_ADD(MSG_Language_Set_Warning),\r\n\r\n    __MSG_ADD(MSG_Sound_Dumping_Start),\r\n    __MSG_ADD(MSG_Sound_Dumping_Stop),\r\n    __MSG_ADD(MSG_Sound_Dumping_Error_File_1),\r\n    __MSG_ADD(MSG_Sound_Dumping_Error_File_2),\r\n    __MSG_ADD(MSG_Sound_Dumping_VGM_Acc_Frame),\r\n    __MSG_ADD(MSG_Sound_Dumping_VGM_Acc_Sample),\r\n    __MSG_ADD(MSG_Sound_Dumping_VGM_Acc_Change),\r\n\r\n    __MSG_ADD(MSG_Menu_Main),\r\n    __MSG_ADD(MSG_Menu_Main_LoadROM),\r\n    __MSG_ADD(MSG_Menu_Main_FreeROM),\r\n    __MSG_ADD(MSG_Menu_Main_SaveState_Save),\r\n    __MSG_ADD(MSG_Menu_Main_SaveState_Load),\r\n    __MSG_ADD(MSG_Menu_Main_SaveState_PrevSlot),\r\n    __MSG_ADD(MSG_Menu_Main_SaveState_NextSlot),\r\n    __MSG_ADD(MSG_Menu_Main_Options),\r\n    __MSG_ADD(MSG_Menu_Main_Language),\r\n    __MSG_ADD(MSG_Menu_Main_Quit),\r\n\r\n    __MSG_ADD(MSG_Menu_Debug),\r\n    __MSG_ADD(MSG_Menu_Debug_Enabled),\r\n    __MSG_ADD(MSG_Menu_Debug_ReloadROM),\r\n    __MSG_ADD(MSG_Menu_Debug_ReloadSymbols),\r\n    __MSG_ADD(MSG_Menu_Debug_StepFrame),\r\n    __MSG_ADD(MSG_Menu_Debug_LoadStateAndContinue),\r\n    __MSG_ADD(MSG_Menu_Debug_Dump),\r\n\r\n    __MSG_ADD(MSG_Menu_Machine),\r\n    __MSG_ADD(MSG_Menu_Machine_Power),\r\n    __MSG_ADD(MSG_Menu_Machine_Power_On),\r\n    __MSG_ADD(MSG_Menu_Machine_Power_Off),\r\n    __MSG_ADD(MSG_Menu_Machine_Region),\r\n    __MSG_ADD(MSG_Menu_Machine_Region_Export),\r\n    __MSG_ADD(MSG_Menu_Machine_Region_Japan),\r\n    __MSG_ADD(MSG_Menu_Machine_TVType),\r\n    __MSG_ADD(MSG_Menu_Machine_TVType_NTSC),\r\n    __MSG_ADD(MSG_Menu_Machine_TVType_PALSECAM),\r\n    __MSG_ADD(MSG_Menu_Machine_PauseEmulation),\r\n    __MSG_ADD(Msg_Menu_Machine_ResetEmulation),\r\n\r\n    __MSG_ADD(MSG_Menu_Video),\r\n    __MSG_ADD(MSG_Menu_Video_FullScreen),\r\n    __MSG_ADD(MSG_Menu_Video_Themes),\r\n    __MSG_ADD(MSG_Menu_Video_Blitters),\r\n    __MSG_ADD(MSG_Menu_Video_Layers),\r\n    __MSG_ADD(MSG_Menu_Video_Layers_Sprites),\r\n    __MSG_ADD(MSG_Menu_Video_Layers_Background),\r\n    __MSG_ADD(MSG_Menu_Video_Flickering),\r\n    __MSG_ADD(MSG_Menu_Video_Flickering_Auto),\r\n    __MSG_ADD(MSG_Menu_Video_Flickering_Yes),\r\n    __MSG_ADD(MSG_Menu_Video_Flickering_No),\r\n    __MSG_ADD(MSG_Menu_Video_3DGlasses),\r\n    __MSG_ADD(MSG_Menu_Video_3DGlasses_Enabled),\r\n    __MSG_ADD(MSG_Menu_Video_3DGlasses_ShowBothSides),\r\n    __MSG_ADD(MSG_Menu_Video_3DGlasses_ShowLeftSide),\r\n    __MSG_ADD(MSG_Menu_Video_3DGlasses_ShowRightSide),\r\n    __MSG_ADD(MSG_Menu_Video_3DGlasses_UsesCOMPort),\r\n    __MSG_ADD(Msg_Menu_Video_ScreenCapture),\r\n    __MSG_ADD(Msg_Menu_Video_ScreenCapture_Capture),\r\n    __MSG_ADD(Msg_Menu_Video_ScreenCapture_CaptureRepeat),\r\n    __MSG_ADD(Msg_Menu_Video_ScreenCapture_IncludeGui),\r\n\r\n    __MSG_ADD(MSG_Menu_Sound),\r\n    __MSG_ADD(MSG_Menu_Sound_FM),\r\n    __MSG_ADD(MSG_Menu_Sound_FM_Enabled),\r\n    __MSG_ADD(MSG_Menu_Sound_FM_Disabled),\r\n    __MSG_ADD(MSG_Menu_Sound_FM_Editor),\r\n    __MSG_ADD(MSG_Menu_Sound_Volume),\r\n    __MSG_ADD(MSG_Menu_Sound_Volume_Mute),\r\n    __MSG_ADD(MSG_Menu_Sound_Volume_Value),\r\n    __MSG_ADD(MSG_Menu_Sound_Rate),\r\n    __MSG_ADD(MSG_Menu_Sound_Rate_Hz),\r\n    __MSG_ADD(MSG_Menu_Sound_Channels),\r\n    __MSG_ADD(MSG_Menu_Sound_Channels_Tone),\r\n    __MSG_ADD(MSG_Menu_Sound_Channels_Noises),\r\n    __MSG_ADD(MSG_Menu_Sound_Capture),\r\n    __MSG_ADD(MSG_Menu_Sound_Capture_WAV_Start),\r\n    __MSG_ADD(MSG_Menu_Sound_Capture_WAV_Stop),\r\n    __MSG_ADD(MSG_Menu_Sound_Capture_VGM_Start),\r\n    __MSG_ADD(MSG_Menu_Sound_Capture_VGM_Stop),\r\n    __MSG_ADD(MSG_Menu_Sound_Capture_VGM_SampleAccurate),\r\n\r\n    __MSG_ADD(MSG_Menu_Inputs),\r\n    __MSG_ADD(MSG_Menu_Inputs_Joypad),\r\n    __MSG_ADD(MSG_Menu_Inputs_LightPhaser),\r\n    __MSG_ADD(MSG_Menu_Inputs_PaddleControl),\r\n    __MSG_ADD(MSG_Menu_Inputs_SportsPad),\r\n    __MSG_ADD(MSG_Menu_Inputs_GraphicBoard),\r\n    __MSG_ADD(MSG_Menu_Inputs_GraphicBoardV2),\r\n    __MSG_ADD(MSG_Menu_Inputs_SK1100),\r\n    __MSG_ADD(MSG_Menu_Inputs_RapidFire),\r\n    __MSG_ADD(MSG_Menu_Inputs_RapidFire_PxBx),\r\n    __MSG_ADD(MSG_Menu_Inputs_Configuration),\r\n\r\n    __MSG_ADD(MSG_Menu_Tools),\r\n    __MSG_ADD(MSG_Menu_Tools_Messages),\r\n    __MSG_ADD(MSG_Menu_Tools_Palette),\r\n    __MSG_ADD(MSG_Menu_Tools_TilesViewer),\r\n    __MSG_ADD(MSG_Menu_Tools_TilemapViewer),\r\n    __MSG_ADD(MSG_Menu_Tools_CheatFinder),\r\n    __MSG_ADD(MSG_Menu_Tools_TechInfo),\r\n    __MSG_ADD(MSG_Menu_Tools_MemoryEditor),\r\n\r\n    __MSG_ADD(MSG_Menu_Help),\r\n    __MSG_ADD(MSG_Menu_Help_Documentation),\r\n    __MSG_ADD(MSG_Menu_Help_Compat),\r\n    __MSG_ADD(MSG_Menu_Help_Multiplayer_Games),\r\n    __MSG_ADD(MSG_Menu_Help_Changes),\r\n    __MSG_ADD(MSG_Menu_Help_Debugger),\r\n    __MSG_ADD(MSG_Menu_Help_About),\r\n\r\n    { NULL, MSG_NULL }\r\n};\r\n#undef __MSG_ADD\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Win32 Console\r\n#ifdef ARCH_WIN32\r\n\r\nstruct t_console_win32\r\n{\r\n    HINSTANCE   hinstance;\r\n    HWND        hwnd_parent;\r\n    HWND        hwnd;\r\n    HWND        hwnd_edit;\r\n    HANDLE      thread;\r\n    DWORD       thread_id;\r\n    HANDLE      semaphore_init;\r\n    HANDLE      semaphore_wait;\r\n    bool        waiting_for_answer;\r\n    bool        quit;\r\n};\r\n\r\nstatic int          ConsoleWin32_Initialize(t_console_win32 *c, HINSTANCE hInstance, HWND hWndParent);\r\nstatic void         ConsoleWin32_Close(t_console_win32 *c);\r\nstatic void         ConsoleWin32_Show(t_console_win32 *c);\r\nstatic void         ConsoleWin32_Hide(t_console_win32 *c);\r\nstatic void         ConsoleWin32_Clear(t_console_win32 *c);\r\nstatic void         ConsoleWin32_CopyToClipboard(t_console_win32 *c);\r\nstatic void         ConsoleWin32_Print(t_console_win32 *c, char *s);\r\nstatic bool         ConsoleWin32_WaitForAnswer(t_console_win32 *c, bool allow_run);\r\nstatic int CALLBACK ConsoleWin32_DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r\nstatic DWORD WINAPI ConsoleWin32_Thread(LPVOID data);\r\n\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic bool             ConsolePause;\r\n\r\n#ifdef ARCH_WIN32\r\nstatic t_console_win32  ConsoleWin32;\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// LANGUAGES\r\n//-----------------------------------------------------------------------------\r\n\r\nt_lang *    Lang_New(char *name)\r\n{\r\n    for (t_list* langs = Messages.Langs; langs; langs = langs->next)\r\n    {\r\n        t_lang* lang = (t_lang*)langs->elem;\r\n        if (stricmp (name, lang->Name) == 0)\r\n            return lang;\r\n    }\r\n\r\n    t_lang* lang = (t_lang*)malloc(sizeof (t_lang));\r\n    lang->Name = strdup (name);\r\n    for (int i = 0; i < MSG_MAX; i++)\r\n        lang->Messages[i] = NULL;\r\n    lang->WIP = FALSE;\r\n    list_add_to_end (&Messages.Langs, lang);\r\n    return (lang);\r\n}\r\n\r\nvoid    Lang_Delete(t_lang* lang)\r\n{\r\n    for (int i = 0; i < MSG_MAX; i++)\r\n        free(lang->Messages[i]);\r\n    free(lang->Name);\r\n    free(lang);\r\n}\r\n\r\nint     Lang_Post_Check (t_lang *lang)\r\n{\r\n    // Count available messages (skipping MSG_NULL) and set default for when one is missing\r\n    int cnt = 0;\r\n    for (int i = 1; i < MSG_MAX; i++)\r\n        if (lang->Messages[i])\r\n            cnt++;\r\n    if (cnt < MSG_MAX - 1)\r\n    {\r\n        // We need to display the first line even in WIP mode, if this is the\r\n        // default language, else MEKA will screw up later, with missing strings..\r\n        if (lang->WIP == FALSE || lang == Messages.Lang_Default)\r\n        {\r\n            ConsolePrintf (\"Language \\\"%s\\\" is incomplete (%d/%d messages found) !\\n\", lang->Name, cnt, MSG_MAX - 1);\r\n            ConsoleEnablePause();\r\n        }\r\n        if (lang->WIP == FALSE)\r\n        {\r\n            ConsolePrintf (\"The following messages are missing:\\n\");\r\n            for (int i = 1; i < MSG_MAX; i++)\r\n                if (lang->Messages[i] == NULL)\r\n                    for (int j = 0; Msg_Translation_Table[j].name; j++)\r\n                        if (Msg_Translation_Table[j].value == i)\r\n                            ConsolePrintf (\"  %s\\n\", Msg_Translation_Table[j].name);\r\n            ConsoleEnablePause();\r\n        }\r\n        return (MEKA_ERR_INCOMPLETE);\r\n    }\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\nint     Lang_Message_Add (t_lang *lang, char *msg_id, char *msg)\r\n{\r\n    // Find message number (#define) by name\r\n    int n = -1;\r\n    for (int i = 0; Msg_Translation_Table[i].name; i++)\r\n    {\r\n        if (stricmp (msg_id, Msg_Translation_Table[i].name) == 0)\r\n        {\r\n            n = Msg_Translation_Table[i].value;\r\n            break;\r\n        }\r\n    }\r\n    if (n == -1)\r\n        return (MEKA_ERR_UNKNOWN);\r\n\r\n    // Store message\r\n    if (lang->Messages [n])\r\n    {\r\n        free (lang->Messages [n]);\r\n        ConsolePrintf (\"In %s: message \\\"%s\\\" redefined! Keeping new value.\\n\",\r\n            lang->Name, msg_id);\r\n    }\r\n\r\n    // lang->Messages [n] = strdup (msg);\r\n    lang->Messages[n] = parse_getword(NULL, 0, &msg, \"\\\"\", 0);\r\n\r\n    // Verify that there's nothing after this line\r\n    parse_skip_spaces(&msg);\r\n    if (msg[0])\r\n        return (MEKA_ERR_SYNTAX);\r\n\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\nstatic void     Lang_Set (t_menu_event *event)\r\n{\r\n    Messages.Lang_Cur = (t_lang *)event->user_data;\r\n    gui_menu_uncheck_all (menus_ID.languages);\r\n    gui_menu_check (menus_ID.languages, event->menu_item_idx);\r\n    Msg(MSGT_USER, Msg_Get(MSG_Language_Set), Messages.Lang_Cur->Name);\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Language_Set_Warning));\r\n\r\n    // Post-process\r\n    // FIXME: Rebuild menus\r\n    gamebox_rename_all();\r\n    gui_relayout_all();\r\n}\r\n\r\nvoid            Lang_Set_by_Name (char *name)\r\n{\r\n    for (t_list* langs = Messages.Langs; langs; langs = langs->next)\r\n    {\r\n        t_lang* lang = (t_lang*)langs->elem;\r\n        if (stricmp (lang->Name, name) == 0)\r\n        {\r\n            Messages.Lang_Cur = lang;\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\nvoid            Langs_Menu_Add (int menu_id)\r\n{\r\n    const int s = list_size(Messages.Langs);\r\n    if (s > 1)\r\n    {\r\n        menus_ID.languages = menu_add_menu (menu_id, Msg_Get(MSG_Menu_Main_Language), MENU_ITEM_FLAG_ACTIVE);\r\n        for (t_list* langs = Messages.Langs; langs; langs = langs->next)\r\n        {\r\n            t_lang* lang = (t_lang*)langs->elem;\r\n            menu_add_item(menus_ID.languages, lang->Name, NULL, MENU_ITEM_FLAG_ACTIVE | Is_Checked (lang == Messages.Lang_Cur), (t_menu_callback)Lang_Set, lang);\r\n        }\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// MESSAGING SYSTEM\r\n//-----------------------------------------------------------------------------\r\n\r\nint             Messages_Init_Parse_Line (char *line)\r\n{\r\n    char *      p;\r\n\r\n    if (line[0] == '[')\r\n    {\r\n        line = strdup(line);    // Work on a copy\r\n        if ((p = strchr(line, ']')) != NULL)\r\n            *p = EOSTR;\r\n        Messages.Lang_Cur = Lang_New(line + 1);\r\n        if (Messages.Lang_Default == NULL)\r\n            Messages.Lang_Default = Messages.Lang_Cur;\r\n        free(line);\r\n        return (MEKA_ERR_OK);\r\n    }\r\n\r\n    if (Messages.Lang_Cur == NULL)\r\n        return (MEKA_ERR_MISSING);\r\n\r\n    if (stricmp(line, MSG_LANG_WIP_STR) == 0)\r\n    {\r\n        Messages.Lang_Cur->WIP = TRUE;\r\n        return (MEKA_ERR_OK);\r\n    }\r\n\r\n    line = strdup(line);    // Work on a copy\r\n    if ((p = strchr(line, '=')) == NULL)\r\n    {\r\n        free(line);\r\n        return (MEKA_ERR_SYNTAX);\r\n    }\r\n    *p = EOSTR;\r\n    StrTrim (line);\r\n    StrUpper(line);\r\n    StrTrim (p + 1);\r\n    if ((p = strchr (p + 1, '\\\"')) == NULL)\r\n    {\r\n        free(line);\r\n        return (MEKA_ERR_SYNTAX);\r\n    }\r\n    // if ((p2 = strrchr (p + 1, '\\\"')) == NULL)\r\n    //    return (MEKA_ERR_SYNTAX);\r\n    // *p2 = EOSTR;\r\n    int ret = Lang_Message_Add(Messages.Lang_Cur, line, p + 1);\r\n    free(line);\r\n    return (ret);\r\n}\r\n\r\n// Load messages from MEKA.MSG file (path given in structure)\r\n// Return a MEKA_ERR_xxx code\r\nint     Messages_Init()\r\n{\r\n    Messages.Lang_Cur = Messages.Lang_Default = NULL;\r\n    Messages.Langs = NULL;\r\n\r\n    // Note: this is one of the few cases were the string has to be hardcoded.\r\n    // That is of course because the messages/localization system is not\r\n    // initialized as of yet..\r\n    ConsolePrint(\"Loading MEKA.MSG (messages).. \");\r\n\r\n    // Open and read file --------------------------------------------------------\r\n    t_tfile* tf = tfile_read (Messages.FileName);\r\n    if (tf == NULL)\r\n        Quit_Msg(\"MISSING!\\nTry re-installing your version of Meka.\");\r\n    ConsolePrint(\"\\n\");\r\n\r\n    // Parse each line -----------------------------------------------------------\r\n    int line_cnt = 0;\r\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        char *line = (char*)lines->elem;\r\n        line_cnt += 1;\r\n\r\n        // Cut Comments\r\n        char* p = strchr (line, ';');\r\n        if (p != NULL)\r\n            *p = EOSTR;\r\n\r\n        StrTrim (line);\r\n        if (StrIsNull (line))\r\n            continue;\r\n\r\n        // Parse Line and handle errors\r\n        // ConsolePrintf (\"%d: %s--\\n\", line_cnt, line);\r\n        switch (Messages_Init_Parse_Line(line))\r\n        {\r\n        case MEKA_ERR_MISSING:\r\n            ConsolePrintf (\"On line %d: No language defined for storing message !\", line_cnt);\r\n            tfile_free(tf);\r\n            Quit();\r\n            break;\r\n        case MEKA_ERR_UNKNOWN:\r\n            ConsolePrintf (\"On line %d: Unknown message \\\"%s\\\", skipping it.\\n\", line_cnt, line);\r\n            // tfile_free(tf);\r\n            // Quit();\r\n            break;\r\n        case MEKA_ERR_SYNTAX:\r\n            ConsolePrintf (\"On line %d: Syntax error.\\n%s\\n\", line_cnt, line);\r\n            tfile_free(tf);\r\n            Quit();\r\n            break;\r\n        }\r\n    }\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n\r\n    // Verify language completion\r\n    {\r\n        if (Messages.Lang_Cur == NULL)\r\n            Quit_Msg(\"No language defined. Try re-installing your version of Meka.\");\r\n        Messages.Lang_Cur = Messages.Lang_Default;\r\n        for (t_list* langs = Messages.Langs; langs; langs = langs->next)\r\n        {\r\n            t_lang* lang = (t_lang*)langs->elem;\r\n            if (Lang_Post_Check (lang) != MEKA_ERR_OK)\r\n                if (lang == Messages.Lang_Default)\r\n                    Quit_Msg(\"This is the default language, so we need to abort.\");\r\n        }\r\n    }\r\n\r\n    // Ok\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\nvoid    Messages_Close()\r\n{\r\n    for (t_list* langs = Messages.Langs; langs; langs = langs->next)\r\n    {\r\n        t_lang* lang = (t_lang*)langs->elem;\r\n        Lang_Delete(lang);\r\n    }\r\n    list_free_no_elem(&Messages.Langs);\r\n}\r\n\r\n// Initialize text output console.\r\nvoid            ConsoleInit()\r\n{\r\n    // Reset pause flag\r\n    ConsolePause = FALSE;\r\n\r\n    // Initialize Win32 console\r\n    #ifdef ARCH_WIN32\r\n        const HINSTANCE hInstance = GetModuleHandle(NULL);\r\n        const HWND hWndParent = 0; // win_get_window()\r\n        ConsoleWin32_Initialize(&ConsoleWin32, hInstance, hWndParent);\r\n        // ConsoleWin32_Show(&ConsoleWin32);\r\n    #endif\r\n}\r\n\r\n// Close console.\r\nvoid            ConsoleClose()\r\n{\r\n    // Close Win32 console\r\n    #ifdef ARCH_WIN32\r\n        ConsoleWin32_Close(&ConsoleWin32);\r\n    #endif\r\n}\r\n\r\nstatic char Msg_Buf [MSG_MAX_LEN];\r\n\r\n//-----------------------------------------------------------------------------\r\n// ConsolePrintf (const char *format, ...)\r\n// Print formatted message to console.\r\n//-----------------------------------------------------------------------------\r\nvoid            ConsolePrintf (const char *format, ...)\r\n{\r\n    va_list       params;\r\n\r\n    va_start (params, format);\r\n    vsprintf (Msg_Buf, format, params);\r\n    va_end   (params);\r\n\r\n    ConsolePrint(Msg_Buf);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ConsolePrint(const char *msg)\r\n// Print message to console.\r\n//-----------------------------------------------------------------------------\r\nvoid            ConsolePrint(const char *msg)\r\n{\r\n    // FIXME: to do\r\n    #ifdef ARCH_WIN32\r\n        if (ConsoleWin32.hwnd != 0)\r\n            ConsoleWin32_Print(&ConsoleWin32, (char *)msg);\r\n        else\r\n        {\r\n            //printf(\"[CONSOLE]%s\", msg);\r\n            printf(\"%s\", msg);\r\n            fflush (stdout);\r\n        }\r\n    #else\r\n        printf(\"%s\", msg);\r\n        fflush (stdout);\r\n        // ...\r\n    #endif\r\n}\r\n\r\n// Enable console pausing. The Win32 console will display until user has chosen \"Quit\" or \"Run\".\r\nvoid            ConsoleEnablePause()\r\n{\r\n    // Set pause flag\r\n    ConsolePause = TRUE;\r\n}\r\n\r\nbool            ConsoleWaitForAnswer(bool allow_run)\r\n{\r\n#ifndef ARCH_WIN32\r\n    return TRUE;\r\n#else\r\n    if (!ConsolePause)\r\n        return TRUE;\r\n\r\n    // Else... wait for signal\r\n    return ConsoleWin32_WaitForAnswer(&ConsoleWin32, allow_run);\r\n\r\n#endif\r\n}\r\n\r\nconst char*     Msg_Get(int n)\r\n{\r\n    const char* msg = Messages.Lang_Cur->Messages[n];\r\n    if (msg)\r\n        return msg;\r\n    msg = Messages.Lang_Default->Messages[n];\r\n    return msg;\r\n}\r\n\r\n// Send a message to the user and/or debugging message\r\nvoid            Msg(int attr, const char *format, ...)\r\n{\r\n    va_list     params;\r\n    char *      src;\r\n    char *      p;\r\n\r\n    va_start (params, format);\r\n    vsprintf (Msg_Buf, format, params);\r\n    va_end   (params);\r\n\r\n    #ifdef MSG_USER\r\n        if (attr == MSG_USER) // Allegro constant!!\r\n            Quit_Msg(\"Fatal: avoid using MSG_USER, it is an Allegro constant!\");\r\n    #endif\r\n\r\n    // Handle Bock-is-lazy-to-type-a-full-constant mode\r\n    if (attr == 0)\r\n        attr = MSGT_USER;\r\n\r\n    // Split message by line (\\n) and send it to the various places\r\n    p = NULL;\r\n    do\r\n    {\r\n        src = p ? p : Msg_Buf;\r\n        p = strpbrk (src, \"\\n\\r\");\r\n        if (p)\r\n        {\r\n            *p = EOSTR;\r\n            p += 1;\r\n        }\r\n\r\n        // Set status line\r\n        if (attr & MSGT_STATUS_BAR)\r\n        {\r\n            strcpy(g_gui_status.message, src);\r\n            g_gui_status.timeleft = 120;\r\n        }\r\n\r\n        // Add to user text box\r\n        if (attr & MSGT_USER_LOG)\r\n            TB_Message_Print(src);\r\n\r\n#ifdef WIN32\r\n        if (attr & MSGT_ATTR_DEBUG)\r\n        {\r\n            OutputDebugString(src);\r\n            OutputDebugString(\"\\n\");\r\n        }\r\n#endif\r\n    }\r\n    while (p != NULL);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// WINDOWS CONSOLE\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef ARCH_WIN32\r\n\r\nstatic int     ConsoleWin32_Initialize(t_console_win32 *c, HINSTANCE hInstance, HWND hWndParent)\r\n{\r\n    c->hinstance = hInstance;\r\n    c->hwnd_parent = hWndParent;\r\n    c->hwnd = 0;\r\n    c->hwnd_edit = 0;\r\n    c->waiting_for_answer = FALSE;\r\n    c->quit = FALSE;\r\n    c->semaphore_init = NULL;\r\n    c->semaphore_wait = NULL;\r\n\r\n#if 0\r\n    return (0);\r\n#else\r\n\r\n    // Create initialization semaphore\r\n    c->semaphore_init = CreateSemaphore(NULL, 0, 1, NULL);\r\n    if (c->semaphore_init == 0)\r\n    {\r\n        meka_errno = MEKA_ERR_CONSOLE_WIN32_INIT;\r\n        return (-1);\r\n    }\r\n\r\n    // Create thread\r\n    c->thread = CreateThread(NULL, 0, ConsoleWin32_Thread, (void *)c, 0, &c->thread_id);\r\n    if (c->thread == 0)\r\n    {\r\n        meka_errno = MEKA_ERR_CONSOLE_WIN32_INIT;\r\n        return (-1);\r\n    }\r\n    SetThreadPriority(c->thread, THREAD_PRIORITY_LOWEST);\r\n\r\n    // Wait for semaphore value to be set before continuing\r\n    {\r\n        DWORD dwWaitResult = WaitForSingleObject(c->semaphore_init, 3000L);\r\n        if (dwWaitResult != WAIT_OBJECT_0)\r\n        {\r\n            TerminateThread(c->thread, 1);\r\n            meka_errno = MEKA_ERR_CONSOLE_WIN32_INIT;\r\n            return (-1);\r\n        }\r\n    }\r\n\r\n    return (0);\r\n#endif\r\n}\r\n\r\nstatic void    ConsoleWin32_Close(t_console_win32 *c)\r\n{\r\n    // Stop thread\r\n    TerminateThread(c->thread, 1);\r\n\r\n    // Destroy window\r\n    if (c->hwnd == 0)\r\n        return;\r\n    DestroyWindow(c->hwnd);\r\n    c->hwnd = 0;\r\n    c->hwnd_edit = 0;\r\n}\r\n\r\nstatic void    ConsoleWin32_Show(t_console_win32 *c)\r\n{\r\n    if (c->hwnd == 0)\r\n        return;\r\n    ShowWindow(c->hwnd, SW_SHOWNORMAL);\r\n}\r\n\r\nstatic void    ConsoleWin32_Hide(t_console_win32 *c)\r\n{\r\n    if (c->hwnd == 0)\r\n        return;\r\n    ShowWindow(c->hwnd, SW_HIDE);\r\n}\r\n\r\nstatic bool     ConsoleWin32_WaitForAnswer(t_console_win32 *c, bool allow_run)\r\n{\r\n    bool        ret;\r\n\r\n    // Create wait semaphore\r\n    c->semaphore_wait = CreateSemaphore(NULL, 0, 1, NULL);\r\n    if (c->semaphore_wait == 0)\r\n        return false;\r\n\r\n    // Send message to window handler\r\n    PostMessage(c->hwnd, WM_USER+1, allow_run ? 1 : 0, 0);\r\n\r\n    // Wait for semaphore value to be set before continuing\r\n    WaitForSingleObject(c->semaphore_wait, INFINITE);\r\n\r\n    // Close console and get result\r\n    ret = !c->quit;\r\n    ConsoleWin32_Close(c);\r\n    return (ret);\r\n}\r\n\r\nstatic DWORD WINAPI ConsoleWin32_Thread(LPVOID data)\r\n{\r\n    MSG             msg;\r\n    BOOL            bRet;\r\n    t_console_win32* c = (t_console_win32*)data;\r\n\r\n    // Create window\r\n    c->hwnd = CreateDialog(c->hinstance, MAKEINTRESOURCE(IDD_CONSOLE), c->hwnd_parent, ConsoleWin32_DialogProc);\r\n    if (c->hwnd == 0)\r\n    {\r\n        meka_errno = MEKA_ERR_CONSOLE_WIN32_INIT;\r\n        return (DWORD)-1;\r\n    }\r\n    c->hwnd_edit = GetDlgItem(c->hwnd, IDC_CONSOLE_TEXT);\r\n\r\n    // Show window\r\n    ConsoleWin32_Show(c);\r\n\r\n    // Release initialization semaphore\r\n    ReleaseSemaphore(c->semaphore_init, 1, NULL);\r\n\r\n    // Main Win32 message Loop\r\n    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)\r\n    {\r\n        if (bRet == -1)\r\n        {\r\n            printf (\"Message pump error!\");\r\n            break;\r\n        }\r\n        else\r\n        {\r\n            if (!IsDialogMessage(c->hwnd, &msg))\r\n            {\r\n                TranslateMessage(&msg);\r\n                DispatchMessage(&msg);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Release waiting semaphore\r\n    ReleaseSemaphore(c->semaphore_wait, 1, NULL);\r\n\r\n    return (DWORD)0;\r\n}\r\n\r\nstatic int CALLBACK ConsoleWin32_DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r\n{\r\n    t_console_win32 *c = &ConsoleWin32;\r\n\r\n    switch (message)\r\n    {\r\n    case WM_INITDIALOG:\r\n        {\r\n            // char buffer[256];\r\n            // dialogInit(hDlg, message, wParam, lParam);\r\n            //sprintf(buffer, \"MEKA %s\\nStartup in progress...\", MEKA_VERSION);\r\n            //SetWindowText(GetDlgItem(hDlg, IDC_CONSOLE_INFO), buffer);\r\n            return 0;\r\n        }\r\n    case WM_COMMAND:\r\n        {\r\n            switch (LOWORD(wParam))\r\n            {\r\n            //case IDC_CONSOLE_CLEAR:\r\n            //    ConsoleWin32_Clear(&ConsoleWin32);\r\n            //    break;\r\n            case IDC_CONSOLE_COPY:\r\n                {\r\n                    ConsoleWin32_CopyToClipboard(c);\r\n                    break;\r\n                }\r\n            case IDCANCEL:\r\n            case IDC_CONSOLE_QUIT:\r\n                {\r\n                    c->quit = TRUE;\r\n                    PostQuitMessage(0);\r\n                    break;\r\n                }\r\n            case IDC_CONSOLE_RUN:\r\n                {\r\n                    c->quit = FALSE;\r\n                    PostQuitMessage(0);\r\n                    break;\r\n                }\r\n            }\r\n\r\n            // ...\r\n            return 0;\r\n        }\r\n    case WM_CLOSE:\r\n        {\r\n            if (c->waiting_for_answer)\r\n            {\r\n                c->quit = TRUE;\r\n                PostQuitMessage(0);\r\n            }\r\n            return 0;\r\n        }\r\n    case WM_KEYDOWN:\r\n        {\r\n            if (c->waiting_for_answer && wParam == VK_ESCAPE)\r\n            {\r\n                c->quit = TRUE;\r\n                PostQuitMessage(0);\r\n            }\r\n            return 0;\r\n        }\r\n    case WM_USER+1:\r\n        {\r\n            c->waiting_for_answer = TRUE;\r\n            //SetFocus(hDlg);\r\n            if (wParam != 0)\r\n            {\r\n                EnableWindow(GetDlgItem(hDlg, IDC_CONSOLE_QUIT), TRUE);\r\n                EnableWindow(GetDlgItem(hDlg, IDC_CONSOLE_RUN), TRUE);\r\n                SetFocus(GetDlgItem(hDlg, IDC_CONSOLE_RUN));\r\n                SetWindowText(GetDlgItem(hDlg, IDC_CONSOLE_INFO), \"WARNING - Continue?\");\r\n            }\r\n            else\r\n            {\r\n                EnableWindow(GetDlgItem(hDlg, IDC_CONSOLE_QUIT), TRUE);\r\n                SetFocus(GetDlgItem(hDlg, IDC_CONSOLE_QUIT));\r\n                SetWindowText(GetDlgItem(hDlg, IDC_CONSOLE_INFO), \"ERROR - Have to quit\");\r\n            }\r\n            return 0;\r\n        }\r\n    }\r\n    return 0;\r\n    //return DefDlgProc(hDlg, message, wParam, lParam);\r\n}\r\n\r\nstatic void    ConsoleWin32_Clear(t_console_win32 *c)\r\n{\r\n    SetDlgItemText(c->hwnd, IDC_CONSOLE_TEXT, \"\");\r\n}\r\n\r\nstatic void    ConsoleWin32_CopyToClipboard(t_console_win32 *c)\r\n{\r\n    if (OpenClipboard(c->hwnd))\r\n    {\r\n        int     text_length;\r\n        HGLOBAL clipbuffer;\r\n        char *  buffer;\r\n\r\n        // First empty the clipboard\r\n        EmptyClipboard();\r\n\r\n        // Allocate memory in global scope and read current text into it\r\n        text_length = GetWindowTextLength(c->hwnd_edit);\r\n        clipbuffer = GlobalAlloc(GMEM_DDESHARE, text_length + 1);\r\n        buffer = (char*)GlobalLock(clipbuffer);\r\n        GetDlgItemText(c->hwnd, IDC_CONSOLE_TEXT, buffer, text_length + 1);\r\n        GlobalUnlock(clipbuffer);\r\n\r\n        // Set clipboard to our data\r\n        SetClipboardData(CF_TEXT, clipbuffer);\r\n        CloseClipboard();\r\n    }\r\n}\r\n\r\nstatic void        ConsoleWin32_Print(t_console_win32 *c, char *s)\r\n{\r\n    char *  text;\r\n    int     text_length;\r\n    int     newlines_counter;\r\n\r\n    if (c->hwnd == 0)\r\n        return;\r\n\r\n    // Count '\\n' in new text\r\n    newlines_counter = 0;\r\n    for (text = s; *text != EOSTR; text++)\r\n        if (*text == '\\n')\r\n            newlines_counter++;\r\n\r\n    // Fill text buffer\r\n    // Replace all occurences single \"\\n\" by \"\\r\\n\" since windows edit box wants that\r\n    text = (char*)Memory_Alloc(strlen(s) + (newlines_counter * sizeof(char)) + 2 + 1);\r\n    {\r\n        char* dst = text;\r\n        while (*s != EOSTR)\r\n        {\r\n            if (*s == '\\n')\r\n                *dst++ = '\\r';\r\n            *dst++ = *s++;\r\n        }\r\n        *dst = EOSTR;\r\n        //  sprintf(text + text_length, \"%s\", s);\r\n    }\r\n\r\n    // Set new text\r\n    // Tips: set an empty selection at the end then replace selection, to avoid flickering (better than a WM_SETTEXT)\r\n    text_length = GetWindowTextLength(c->hwnd_edit);\r\n    SendMessage(c->hwnd_edit, EM_SETSEL, text_length, text_length);\r\n    SendMessage(c->hwnd_edit, EM_REPLACESEL, FALSE, (LPARAM)text);\r\n    free(text);\r\n}\r\n\r\n#endif // ARCH_WIN32\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/message.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - message.h\r\n// Messaging System, Languages, Console - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Messages types\r\n#define MSGT_USER_LOG                   (0x01)\r\n#define MSGT_STATUS_BAR                 (0x02)\r\n#define MSGT_ATTR_DEBUG                 (0x04)\r\n\r\n#define MSGT_USER                       (MSGT_USER_LOG | MSGT_STATUS_BAR)\r\n#define MSGT_DEBUG                      (MSGT_USER_LOG | MSGT_ATTR_DEBUG)\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n// String used to enable WIP for a language\r\n#define MSG_LANG_WIP_STR                \"WIP\"\r\n\r\n// Messages definitions\r\nenum\r\n{\r\n    MSG_NULL                                    = 0,\r\n\r\n    MSG_Welcome,\r\n    MSG_Window_Title,\r\n    MSG_Quit,\r\n\r\n    MSG_About_BoxTitle,\r\n    MSG_About_Line_Meka_Date,\r\n    MSG_About_Line_Authors,\r\n    MSG_About_Line_Homepage,\r\n\r\n    MSG_Ok,\r\n    MSG_Failed,\r\n    MSG_Error_Base,\r\n    MSG_Error_Error,\r\n    MSG_Error_Memory,\r\n    MSG_Error_Param,\r\n    MSG_Error_Syntax,\r\n\r\n    MSG_Error_Video_Mode,\r\n    MSG_Error_Video_Mode_Back_To_GUI,\r\n\r\n    MSG_Error_File_Not_Found,\r\n    MSG_Error_File_Read,\r\n    MSG_Error_File_Empty,\r\n\r\n    MSG_Error_ZIP_Not_Supported,\r\n    MSG_Error_ZIP_Loading,\r\n    MSG_Error_ZIP_Internal,\r\n\r\n    MSG_Error_Directory_Open,\r\n\r\n    MSG_Must_Reset,\r\n    MSG_No_ROM,\r\n\r\n    MSG_Init_Allegro,\r\n    MSG_Init_GUI,\r\n    MSG_Init_Completed,\r\n\r\n    MSG_Setup_Running,\r\n    MSG_Setup_Setup,\r\n    MSG_Setup_Video_Driver,\r\n    MSG_Setup_Video_DisplayMode,\r\n    MSG_Setup_SampleRate_Select,\r\n\r\n    MSG_Capture_Done,\r\n    MSG_Capture_Error,\r\n    MSG_Capture_Error_File,\r\n\r\n    MSG_SRAM_Loaded,\r\n    MSG_SRAM_Load_Unable,\r\n    MSG_SRAM_Wrote,\r\n    MSG_SRAM_Write_Unable,\r\n\r\n    MSG_93c46_Reset,\r\n    MSG_93c46_Loaded,\r\n    MSG_93c46_Load_Unable,\r\n    MSG_93c46_Wrote,\r\n    MSG_93c46_Write_Unable,\r\n\r\n    MSG_TVType_Set,\r\n    MSG_TVType_Info_Speed,\r\n\r\n    MSG_Blitters_Loading,\r\n    MSG_Blitters_Error_Not_Enough,\r\n    MSG_Blitters_Error_Not_Found,\r\n    MSG_Blitters_Error_Missing,\r\n    MSG_Blitters_Error_Unrecognized,\r\n    MSG_Blitters_Error_Incorrect_Value,\r\n    MSG_Blitters_Set,\r\n\r\n    MSG_NES_Activate,\r\n    MSG_NES_Sucks,\r\n    MSG_NES_Mapper_Unknown,\r\n    MSG_NES_Deny_Facts,\r\n\r\n    MSG_Debug_Init,\r\n    MSG_Debug_Welcome,\r\n    MSG_Debug_Not_Available,\r\n    MSG_Debug_Trap_Read,\r\n    MSG_Debug_Trap_Write,\r\n    MSG_Debug_Trap_Port_Read,\r\n    MSG_Debug_Trap_Port_Write,\r\n    MSG_Debug_Symbols_Loaded,\r\n    MSG_Debug_Symbols_Error,\r\n    MSG_Debug_Symbols_Error_Line,\r\n\r\n    MSG_DataDump_Mode_Ascii,\r\n    MSG_DataDump_Mode_Raw,\r\n    MSG_DataDump_Error,\r\n    MSG_DataDump_Error_OB_Memory,\r\n    MSG_DataDump_Error_Palette,\r\n    MSG_DataDump_Error_Sprites,\r\n    MSG_DataDump_Main,\r\n\r\n    MSG_Doc_BoxTitle,\r\n    MSG_Doc_File_Error,\r\n    MSG_Doc_Enabled,\r\n    MSG_Doc_Disabled,\r\n\r\n    MSG_Flickering_Auto,\r\n    MSG_Flickering_Yes,\r\n    MSG_Flickering_No,\r\n\r\n    MSG_Layer_BG_Disabled,\r\n    MSG_Layer_BG_Enabled,\r\n    MSG_Layer_Spr_Disabled,\r\n    MSG_Layer_Spr_Enabled,\r\n\r\n    MSG_FDC765_Unknown_Read,\r\n    MSG_FDC765_Unknown_Write,\r\n    MSG_FDC765_Disk_Too_Large1,\r\n    MSG_FDC765_Disk_Too_Large2,\r\n    MSG_FDC765_Disk_Too_Small1,\r\n    MSG_FDC765_Disk_Too_Small2,\r\n\r\n    MSG_Palette_BoxTitle,\r\n    MSG_Palette_Disabled,\r\n    MSG_Palette_Enabled,\r\n\r\n    MSG_Message_BoxTitle,\r\n    MSG_Message_Disabled,\r\n    MSG_Message_Enabled,\r\n\r\n    MSG_TechInfo_BoxTitle,\r\n    MSG_TechInfo_Disabled,\r\n    MSG_TechInfo_Enabled,\r\n\r\n    MSG_TilesViewer_BoxTitle,\r\n    MSG_TilesViewer_Disabled,\r\n    MSG_TilesViewer_Enabled,\r\n    MSG_TilesViewer_Tile,\r\n\r\n    MSG_MemoryEditor_BoxTitle,\r\n    MSG_MemoryEditor_Disabled,\r\n    MSG_MemoryEditor_Enabled,\r\n    MSG_MemoryEditor_WriteZ80_Unable,\r\n    MSG_MemoryEditor_Address_Out_of_Bound,\r\n\r\n    MSG_RapidFire_JxBx_On,\r\n    MSG_RapidFire_JxBx_Off,\r\n\r\n    MSG_FM_Enabled,\r\n    MSG_FM_Disabled,\r\n\r\n    MSG_Country_European_US,\r\n    MSG_Country_JAP,\r\n\r\n    MSG_Patch_Loading,\r\n    MSG_Patch_Missing,\r\n    MSG_Patch_Unrecognized,\r\n    MSG_Patch_Value_Not_a_Byte,\r\n    MSG_Patch_Out_of_Bound,\r\n\r\n    MSG_Glasses_Enabled,\r\n    MSG_Glasses_Disabled,\r\n    MSG_Glasses_Show_Both,\r\n    MSG_Glasses_Show_Left,\r\n    MSG_Glasses_Show_Right,\r\n    MSG_Glasses_Com_Port,\r\n    MSG_Glasses_Com_Port2,\r\n    MSG_Glasses_Com_Port_Open_Error,\r\n    MSG_Glasses_Unsupported,\r\n\r\n    MSG_Inputs_Joy_Init,\r\n    MSG_Inputs_Joy_Init_None,\r\n    MSG_Inputs_Joy_Init_Found,\r\n    MSG_Inputs_Joy_Calibrate_Error,\r\n\r\n    MSG_Inputs_Joypad,\r\n    MSG_Inputs_LightPhaser,\r\n    MSG_Inputs_PaddleControl,\r\n    MSG_Inputs_SportsPad,\r\n    MSG_Inputs_GraphicBoard,\r\n    MSG_Inputs_GraphicBoardV2,\r\n    MSG_Inputs_Play_Digital,\r\n    MSG_Inputs_Play_Mouse,\r\n    MSG_Inputs_Play_Digital_Unrecommended,\r\n    MSG_Inputs_Play_Pen,\r\n    MSG_Inputs_SK1100_Enabled,\r\n    MSG_Inputs_SK1100_Disabled,\r\n\r\n    MSG_Inputs_Config_BoxTitle,\r\n    MSG_Inputs_Config_Peripheral_Click,\r\n    MSG_Inputs_Config_Source_Enabled,\r\n    MSG_Inputs_Config_Source_Player,\r\n    MSG_Inputs_Config_Source_Emulate_Joypad,\r\n\r\n    MSG_Inputs_Src_Loading,\r\n    MSG_Inputs_Src_Not_Enough,\r\n    MSG_Inputs_Src_Missing,\r\n    MSG_Inputs_Src_Equal,\r\n    MSG_Inputs_Src_Unrecognized,\r\n    MSG_Inputs_Src_Syntax_Param,\r\n    MSG_Inputs_Src_Inconsistency,\r\n    MSG_Inputs_Src_Map_Keyboard,\r\n    MSG_Inputs_Src_Map_Keyboard_Ok,\r\n    MSG_Inputs_Src_Map_Joypad,\r\n    MSG_Inputs_Src_Map_Joypad_Ok_A,\r\n    MSG_Inputs_Src_Map_Joypad_Ok_B,\r\n    MSG_Inputs_Src_Map_Mouse,\r\n    MSG_Inputs_Src_Map_Mouse_Ok_B,\r\n    MSG_Inputs_Src_Map_Mouse_No_A,\r\n    MSG_Inputs_Src_Map_Cancelled,\r\n\r\n    MSG_Machine_Pause,\r\n    MSG_Machine_Resume,\r\n    MSG_Machine_Reset,\r\n\r\n    MSG_FDB_Loading,\r\n\r\n    MSG_DB_Loading,\r\n    MSG_DB_Name_Default,\r\n    MSG_DB_Name_NoCartridge,\r\n    MSG_DB_SyntaxError,\r\n\r\n    MSG_Config_Loading,\r\n\r\n    MSG_Datafile_Loading,\r\n\r\n    MSG_Driver_Unknown,\r\n\r\n    MSG_OverDump,\r\n\r\n    MSG_Sound_Init,\r\n    MSG_Sound_Init_Error_Audio,\r\n    MSG_Sound_Init_Error_Blaster,\r\n    MSG_Sound_Init_Error_Blaster_A,\r\n    MSG_Sound_Init_Error_Voices,\r\n    MSG_Sound_Init_Error_Voice_N,\r\n    MSG_Sound_Init_Soundcard,\r\n    MSG_Sound_Init_Soundcard_No,\r\n    MSG_Sound_Init_SN76496,\r\n    MSG_Sound_Init_YM2413_Digital,\r\n    MSG_Sound_Stream_Error,\r\n    MSG_Sound_Volume_Changed,\r\n\r\n    MSG_Theme_Loading,\r\n    MSG_Theme_Error_Not_Enough,\r\n    MSG_Theme_Error_Missing_Theme_Name,\r\n    MSG_Theme_Error_Syntax,\r\n    MSG_Theme_Error_Attribute_Defined,\r\n    MSG_Theme_Error_Out_of_Bound,\r\n    MSG_Theme_Error_Theme_Missing_Data,\r\n    MSG_Theme_Error_BG_Big,\r\n    MSG_Theme_Error_BG,\r\n    MSG_Theme_Error_BG_FileName,\r\n\r\n    MSG_LoadROM_Loading,\r\n    MSG_LoadROM_Success,\r\n    MSG_LoadDisk_Success,\r\n    MSG_LoadROM_Comment,\r\n    MSG_LoadROM_SMSGG_Mode_Comment,\r\n    MSG_LoadROM_Warning,\r\n    MSG_LoadROM_Bad_Dump_Long,\r\n    MSG_LoadROM_Bad_Dump_Short,\r\n    MSG_LoadROM_Product_Num,\r\n    MSG_LoadROM_SDSC,\r\n    MSG_LoadROM_SDSC_Name,\r\n    MSG_LoadROM_SDSC_Version,\r\n    MSG_LoadROM_SDSC_Date,\r\n    MSG_LoadROM_SDSC_Author,\r\n    MSG_LoadROM_SDSC_Release_Note,\r\n    MSG_LoadROM_SDSC_Unknown,\r\n    MSG_LoadROM_SDSC_Error,\r\n    MSG_LoadROM_Reload_Reloaded,\r\n    MSG_LoadROM_Reload_No_ROM,\r\n\r\n    MSG_FileBrowser_BoxTitle,\r\n    MSG_FileBrowser_Drive,\r\n    MSG_FileBrowser_Load,\r\n    MSG_FileBrowser_Close,\r\n    MSG_FileBrowser_LoadNames,\r\n    MSG_FileBrowser_ReloadDir,\r\n\r\n    MSG_FM_Editor_BoxTitle,\r\n    MSG_FM_Editor_Enabled,\r\n    MSG_FM_Editor_Disabled,\r\n\r\n    MSG_Frameskip_Auto,\r\n    MSG_Frameskip_Standard,\r\n    MSG_FPS_Counter_Enabled,\r\n    MSG_FPS_Counter_Disabled,\r\n\r\n    MSG_Log_Need_Param,\r\n    MSG_Log_Session_Start,\r\n\r\n    MSG_Load_Need_Param,\r\n    MSG_Load_Error,\r\n    MSG_Load_Not_Valid,\r\n    MSG_Load_Success,\r\n    MSG_Load_Version,\r\n    MSG_Load_Wrong_System,\r\n    MSG_Load_Massage,\r\n    MSG_Save_Not_in_BIOS,\r\n    MSG_Save_Error,\r\n    MSG_Save_Success,\r\n    MSG_Save_Slot,\r\n\r\n    MSG_Options_BoxTitle,\r\n    MSG_Options_Close,\r\n    MSG_Options_BIOS_Enable,\r\n    MSG_Options_DB_Display,\r\n    MSG_Options_Product_Number,\r\n    MSG_Options_Bright_Palette,\r\n    MSG_Options_Allow_Opposite_Directions,\r\n    MSG_Options_Load_Close,\r\n    MSG_Options_Load_FullScreen,\r\n    MSG_Options_FullScreen_Messages,\r\n    MSG_Options_GUI_VSync,\r\n    MSG_Options_Capture_Crop_Align,\r\n    MSG_Options_NES_Enable,\r\n    MSG_Options_GUI_GameWindowScale,\r\n\r\n    MSG_Language_Set,\r\n    MSG_Language_Set_Warning,\r\n\r\n    MSG_Sound_Dumping_Start,\r\n    MSG_Sound_Dumping_Stop,\r\n    MSG_Sound_Dumping_Error_File_1,\r\n    MSG_Sound_Dumping_Error_File_2,\r\n    MSG_Sound_Dumping_VGM_Acc_Frame,\r\n    MSG_Sound_Dumping_VGM_Acc_Sample,\r\n    MSG_Sound_Dumping_VGM_Acc_Change,\r\n\r\n    MSG_Menu_Main,\r\n    MSG_Menu_Main_LoadROM,\r\n    MSG_Menu_Main_FreeROM,\r\n    MSG_Menu_Main_SaveState_Save,\r\n    MSG_Menu_Main_SaveState_Load,\r\n    MSG_Menu_Main_SaveState_PrevSlot,\r\n    MSG_Menu_Main_SaveState_NextSlot,\r\n    MSG_Menu_Main_Options,\r\n    MSG_Menu_Main_Language,\r\n    MSG_Menu_Main_Quit,\r\n\r\n    MSG_Menu_Debug,\r\n    MSG_Menu_Debug_Enabled,\r\n    MSG_Menu_Debug_ReloadROM,\r\n    MSG_Menu_Debug_ReloadSymbols,\r\n    MSG_Menu_Debug_StepFrame,\r\n    MSG_Menu_Debug_LoadStateAndContinue,\r\n    MSG_Menu_Debug_Dump,\r\n\r\n    MSG_Menu_Machine,\r\n    MSG_Menu_Machine_Power,\r\n    MSG_Menu_Machine_Power_On,\r\n    MSG_Menu_Machine_Power_Off,\r\n    MSG_Menu_Machine_Region,\r\n    MSG_Menu_Machine_Region_Export,\r\n    MSG_Menu_Machine_Region_Japan,\r\n    MSG_Menu_Machine_TVType,\r\n    MSG_Menu_Machine_TVType_NTSC,\r\n    MSG_Menu_Machine_TVType_PALSECAM,\r\n    MSG_Menu_Machine_PauseEmulation,\r\n    Msg_Menu_Machine_ResetEmulation,\r\n\r\n    MSG_Menu_Video,\r\n    MSG_Menu_Video_FullScreen,\r\n    MSG_Menu_Video_Themes,\r\n    MSG_Menu_Video_Blitters,\r\n    MSG_Menu_Video_Layers,\r\n    MSG_Menu_Video_Layers_Sprites,\r\n    MSG_Menu_Video_Layers_Background,\r\n    MSG_Menu_Video_Flickering,\r\n    MSG_Menu_Video_Flickering_Auto,\r\n    MSG_Menu_Video_Flickering_Yes,\r\n    MSG_Menu_Video_Flickering_No,\r\n    MSG_Menu_Video_3DGlasses,\r\n    MSG_Menu_Video_3DGlasses_Enabled,\r\n    MSG_Menu_Video_3DGlasses_ShowBothSides,\r\n    MSG_Menu_Video_3DGlasses_ShowLeftSide,\r\n    MSG_Menu_Video_3DGlasses_ShowRightSide,\r\n    MSG_Menu_Video_3DGlasses_UsesCOMPort,\r\n    Msg_Menu_Video_ScreenCapture,\r\n    Msg_Menu_Video_ScreenCapture_Capture,\r\n    Msg_Menu_Video_ScreenCapture_CaptureRepeat,\r\n    Msg_Menu_Video_ScreenCapture_IncludeGui,\r\n\r\n    MSG_Menu_Sound,\r\n    MSG_Menu_Sound_FM,\r\n    MSG_Menu_Sound_FM_Enabled,\r\n    MSG_Menu_Sound_FM_Disabled,\r\n    MSG_Menu_Sound_FM_Editor,\r\n    MSG_Menu_Sound_Volume,\r\n    MSG_Menu_Sound_Volume_Mute,\r\n    MSG_Menu_Sound_Volume_Value,\r\n    MSG_Menu_Sound_Rate,\r\n    MSG_Menu_Sound_Rate_Hz,\r\n    MSG_Menu_Sound_Channels,\r\n    MSG_Menu_Sound_Channels_Tone,\r\n    MSG_Menu_Sound_Channels_Noises,\r\n    MSG_Menu_Sound_Capture,\r\n    MSG_Menu_Sound_Capture_WAV_Start,\r\n    MSG_Menu_Sound_Capture_WAV_Stop,\r\n    MSG_Menu_Sound_Capture_VGM_Start,\r\n    MSG_Menu_Sound_Capture_VGM_Stop,\r\n    MSG_Menu_Sound_Capture_VGM_SampleAccurate,\r\n\r\n    MSG_Menu_Inputs,\r\n    MSG_Menu_Inputs_Joypad,\r\n    MSG_Menu_Inputs_LightPhaser,\r\n    MSG_Menu_Inputs_PaddleControl,\r\n    MSG_Menu_Inputs_SportsPad,\r\n    MSG_Menu_Inputs_GraphicBoard,\r\n    MSG_Menu_Inputs_GraphicBoardV2,\r\n    MSG_Menu_Inputs_SK1100,\r\n    MSG_Menu_Inputs_RapidFire,\r\n    MSG_Menu_Inputs_RapidFire_PxBx,\r\n    MSG_Menu_Inputs_Configuration,\r\n\r\n    MSG_Menu_Tools,\r\n    MSG_Menu_Tools_Messages,\r\n    MSG_Menu_Tools_Palette,\r\n    MSG_Menu_Tools_TilesViewer,\r\n    MSG_Menu_Tools_TilemapViewer,\r\n    MSG_Menu_Tools_CheatFinder,\r\n    MSG_Menu_Tools_TechInfo,\r\n    MSG_Menu_Tools_MemoryEditor,\r\n\r\n    MSG_Menu_Help,\r\n    MSG_Menu_Help_Documentation,\r\n    MSG_Menu_Help_Compat,\r\n    MSG_Menu_Help_Multiplayer_Games,\r\n    MSG_Menu_Help_Changes,\r\n    MSG_Menu_Help_Debugger,\r\n    MSG_Menu_Help_About,\r\n\r\n    // Number of messages\r\n    MSG_MAX,\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n// Structure storing messages for one supported language\r\nstruct t_lang\r\n{\r\n    char *      Name;\r\n    char *      Messages[MSG_MAX];\r\n    int         WIP;\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid            Lang_Set_by_Name (char *name);\r\nvoid            Langs_Menu_Add (int menu_id);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n// Structure storing localization basis stuff and all supported languages\r\nstruct t_messages\r\n{\r\n    char        FileName [FILENAME_LEN];      // path to the MEKA.MSG file\r\n    t_lang *    Lang_Cur;\r\n    t_lang *    Lang_Default;\r\n    t_list *    Langs;\r\n};\r\n\r\nextern t_messages Messages;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions - Message\r\n//-----------------------------------------------------------------------------\r\n\r\n// Load messages from MEKA.MSG file (path given in structure)\r\n// Return a MEKA_ERR_xxx code\r\nint     Messages_Init();\r\nvoid    Messages_Close();\r\n\r\n// Get specified message string\r\nconst char* Msg_Get(int n);\r\n\r\n// Send a message to the user and/or debugging message\r\nvoid        Msg(int attr, const char *format, ...) FORMAT_PRINTF (2);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions - Console\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    ConsoleInit();\r\nvoid    ConsoleClose();\r\nvoid    ConsolePrintf(const char *format, ...) FORMAT_PRINTF (1);\r\nvoid    ConsolePrint(const char *msg);\r\nvoid    ConsoleEnablePause();\r\nbool    ConsoleWaitForAnswer(bool allow_run);\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/misc.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - misc.c\r\n// Miscellaneous - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_game.h\"\r\n#include \"app_memview.h\"\r\n#include \"capture.h\"\r\n#include \"debugger.h\"\r\n#include \"inputs_i.h\"\r\n#include \"palette.h\"\r\n#include \"sound/sound_logging.h\"\r\n#include \"video.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid *  Memory_Alloc(size_t size)\r\n{\r\n    u8* p = (u8*)malloc(size);\r\n    if (p == NULL)\r\n    {\r\n        meka_errno = MEKA_ERR_MEMORY;\r\n        Quit_Msg(\"%s\", meka_strerror());\r\n    }\r\n    return (p);\r\n}\r\n\r\n// Called when media (ROM) changes\r\nvoid    Change_System_Misc()\r\n{\r\n    gamebox_resize_all();\r\n    Capture_Init_Game();\r\n    Sound_Log_Init_Game();\r\n    MemoryViewers_MediaReload();\r\n#ifdef MEKA_Z80_DEBUGGER\r\n    Debugger_MediaReload();\r\n#endif // MEKA_Z80_DEBUGGER\r\n}\r\n\r\nbool    OSD_ClipboardSetText(const char* text, const char* text_end)\r\n{\r\n#ifdef ARCH_WIN32\r\n    if (!OpenClipboard(NULL))\r\n        return false;\r\n\r\n    if (!text_end)\r\n        text_end = text + strlen(text);\r\n\r\n    const int buf_length = (text_end - text) + 1;\r\n    HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, buf_length * sizeof(char));\r\n    if (buf_handle == NULL)\r\n        return false;\r\n\r\n    char* buf_global = (char *)GlobalLock(buf_handle);\r\n    sprintf(buf_global, \"%.*s\", text_end - text, text);\r\n    GlobalUnlock(buf_handle);\r\n\r\n    EmptyClipboard();\r\n    SetClipboardData(CF_TEXT, buf_handle);\r\n    CloseClipboard();\r\n\r\n    return true;\r\n#else\r\n    return false;\r\n#endif\r\n}\r\n\r\nchar*   OSD_ClipboardGetText()\r\n{\r\n#ifdef ARCH_WIN32\r\n    if (!OpenClipboard(NULL))\r\n        return NULL;\r\n\r\n    HANDLE buf_handle = GetClipboardData(CF_TEXT);\r\n    if (buf_handle == NULL)\r\n        return NULL;\r\n\r\n    char* buf_global = (char*)GlobalLock(buf_handle);\r\n    char* buf_local = buf_global ? strdup(buf_global) : NULL;\r\n    GlobalUnlock(buf_handle);\r\n    CloseClipboard();\r\n\r\n    return buf_local;\r\n#else\r\n    return NULL;\r\n#endif\r\n}\r\n\r\nvoid    Random_Init()\r\n{\r\n    srand ((unsigned int)time (NULL));\r\n#ifndef ARCH_WIN32\r\n    srandom (time (NULL));\r\n#endif\r\n}\r\n\r\nint     RandomInt(int max)\r\n{\r\n#ifndef ARCH_WIN32\r\n    return random() % max;\r\n#else\r\n    return rand() % max;\r\n#endif\r\n}\r\n\r\n// FIXME: shit\r\nfloat   RandomFloat(float max)\r\n{\r\n    return max * ((float)RandomInt(65535) / 65535.0f);\r\n}\r\n\r\n// FIXME: shit\r\nfloat   RandomFloat(float min, float max)\r\n{\r\n    return min + (max - min) * ((float)RandomInt(65535) / 65535.0f);\r\n}\r\n\r\nvoid    Profile_Step(const char* name)\r\n{\r\n    static double last_time = 0.0;\r\n    double current_time = al_get_time();\r\n\r\n    float delta_ms = (float)(current_time-last_time) * 1000.0f;\r\n\r\n    Msg(MSGT_DEBUG, \"PROF %6.2f - %s\", delta_ms, name);\r\n\r\n    last_time = current_time;\r\n}\r\n\r\n// Show the ending ASCII message\r\nvoid    Show_End_Message()\r\n{\r\n    ConsolePrintf (\" %s (c) %s\\n\", MEKA_NAME_VERSION, MEKA_AUTHORS);\r\n    ConsolePrintf (\" Built on %s at %s\\n\", MEKA_BUILD_DATE, MEKA_BUILD_TIME);\r\n    ConsolePrintf (\" \" MEKA_HOMEPAGE \"\\n\");\r\n}\r\n\r\n// Quit the application immediately\r\nvoid    Quit()\r\n{\r\n    // Set text mode if we're not already in\r\n    if (g_env.state != MEKA_STATE_INIT && g_env.state != MEKA_STATE_SHUTDOWN)\r\n    {\r\n        Video_DestroyVideoBuffers();\r\n        al_destroy_display(g_display);\r\n        g_display = NULL;\r\n    }\r\n\r\n    // Return back to starting directory\r\n    chdir (g_env.Paths.StartingDirectory);\r\n\r\n#ifdef ARCH_WIN32\r\n    if (g_env.state == MEKA_STATE_INIT)\r\n    {\r\n        ConsoleEnablePause();\r\n        ConsoleWaitForAnswer(FALSE);\r\n    }\r\n#endif\r\n\r\n    // Exit application\r\n    exit (1);\r\n}\r\n\r\n// Display an error message then quit the application\r\nvoid    Quit_Msg(const char *format, ...)\r\n{\r\n    // Set text mode if we're not already in\r\n    if (g_env.state != MEKA_STATE_INIT && g_env.state != MEKA_STATE_SHUTDOWN)\r\n    {\r\n        Video_DestroyVideoBuffers();\r\n        al_destroy_display(g_display);\r\n        g_display = NULL;\r\n    }\r\n\r\n    // Return back to starting directory\r\n    chdir (g_env.Paths.StartingDirectory);\r\n\r\n#ifdef ARCH_WIN32\r\n    {\r\n        // FIXME: should redirect on console\r\n        char buffer[512];\r\n        va_list params;\r\n        va_start (params, format);\r\n        vsprintf (buffer, format, params);\r\n        va_end   (params);\r\n\r\n        ConsolePrint(buffer);\r\n        ConsoleEnablePause();\r\n\r\n        if (g_env.state == MEKA_STATE_INIT)\r\n            ConsoleWaitForAnswer(FALSE);\r\n        else\r\n        {\r\n            // Note: we don't use allegro_message() because Allegro might be unitialized here\r\n            MessageBox (NULL, buffer, Msg_Get(MSG_Window_Title), MB_OK | MB_ICONINFORMATION);\r\n        }\r\n    }\r\n#else\r\n    {\r\n        va_list params;\r\n        va_start (params, format);\r\n        vprintf  (format, params); // FIXME: use Console*\r\n        va_end   (params);\r\n        ConsolePrint(\"\\n\");\r\n    }\r\n#endif\r\n\r\n    // Force Allegro closing\r\n    // Trying to fix the crash on quit.\r\n    // Note that this call works even if Allegro has not been initialized yet\r\n    // (which may happens considering Quit_Msg() gets called during initialization)\r\n    // allegro_exit();\r\n    // remove_joystick();\r\n\r\n    // Exit application\r\n    exit (1);\r\n\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/misc.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - misc.h\r\n// Miscellaneous - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//#define PROFILE_ENABLE\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Change_System_Misc();\r\nvoid    Show_End_Message();\r\n\r\nbool    OSD_ClipboardSetText(const char* text, const char* text_end = NULL);\r\nchar *  OSD_ClipboardGetText();                 // User takes memory ownership\r\n\r\nvoid    Quit();\r\nvoid    Quit_Msg(const char *format, ...)      FORMAT_PRINTF (1);\r\n\r\nvoid    Random_Init();\r\nint     RandomInt(int max);\r\nfloat   RandomFloat(float max = 1.0f);\r\nfloat   RandomFloat(float min, float max);\r\n\r\nvoid *  Memory_Alloc(size_t size);\r\n\r\n#ifdef PROFILE_ENABLE\r\n#define PROFILE_STEP(__NAME)        Profile_Step(__NAME)\r\n#else\r\n#define PROFILE_STEP(__NAME)        do {} while(0)\r\n#endif\r\n\r\nvoid    Profile_Step(const char* name);\r\n\r\ntemplate<typename T>\r\nstatic inline T Clamp(T v, T mn, T mx)\r\n{\r\n    if (v < mn) return mn;\r\n    if (v > mx) return mx;\r\n    return v;\r\n}\r\n\r\nstatic inline int LinearRemap(int src, int src_min, int src_max, int dst_min, int dst_max)\r\n{\r\n    const float t = (float)(src - src_min) / (float)(src_max - src_min);\r\n    return dst_min + (dst_max - dst_min) * t;\r\n}\r\n\r\nstatic inline int LinearRemapClamp(int src, int src_min, int src_max, int dst_min, int dst_max)\r\n{\r\n    src = Clamp<int>(src, src_min, src_max);\r\n\r\n    const float t = (float)(src - src_min) / (float)(src_max - src_min);\r\n    return dst_min + (dst_max - dst_min) * t;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/palette.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - palette.c\r\n// Palette management - Code\r\n//-----------------------------------------------------------------------------\r\n// (This used to be a quite fancy dynamic palette management system to attempt\r\n// to minimize hardware palette change, but its mostly meaningless today)\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"blit.h\"\r\n#include \"blitintf.h\"\r\n#include \"palette.h\"\r\n#include \"video.h\"\r\n#include \"video_m2.h\"\r\n\r\n// #define DEBUG_PALETTE\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nALLEGRO_COLOR   Palette_Emulation[PALETTE_EMU_GAME_SIZE];\r\nu32             Palette_EmulationToHostGui[PALETTE_EMU_GAME_SIZE];\r\nu16             Palette_EmulationToHostGame[PALETTE_EMU_GAME_SIZE];\r\nint             Palette_EmulationFlags[PALETTE_EMU_GAME_SIZE];\r\nbool            Palette_EmulationDirtyAny;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Initialize palette engine\r\nvoid    Palette_Init()\r\n{\r\n    Palette_Emulation_Reset();\r\n}\r\n\r\n// Close palette engine\r\nvoid    Palette_Close()\r\n{\r\n}\r\n\r\nvoid    Palette_UpdateAfterRedraw()\r\n{\r\n    // Clear dirty flags\r\n    for (int i = 0; i != PALETTE_EMU_GAME_SIZE; i++)\r\n        Palette_EmulationFlags[i] &= ~PALETTE_EMULATION_FLAGS_DIRTY;\r\n    Palette_EmulationDirtyAny = FALSE;\r\n}\r\n\r\nvoid    Palette_Emulation_Reset()\r\n{\r\n    for (int i = 0; i != PALETTE_EMU_GAME_SIZE; i++)\r\n    {\r\n        Palette_Emulation[i] = COLOR_BLACK;\r\n        Palette_EmulationToHostGui[i] = 0;\r\n        Palette_EmulationToHostGame[i] = 0;\r\n        Palette_EmulationFlags[i] = PALETTE_EMULATION_FLAGS_DIRTY;\r\n    }\r\n    Palette_EmulationDirtyAny = TRUE;\r\n    Palette_Emulation_Reload();\r\n}\r\n\r\n// Reload palette data (fixed or from PRAM)\r\n// Called when changing video mode on the fly\r\nvoid    Palette_Emulation_Reload()\r\n{\r\n    switch (g_driver->vdp)\r\n    {\r\n    case VDP_TMS9918:\r\n        TMS9918_Palette_Setup();\r\n        return;\r\n    }\r\n\r\n    // g_driver->vdp == VDP_SMSGG\r\n    // SMS/GG Palette will be reloaded\r\n#ifdef DEBUG_PALETTE\r\n    Msg(MSGT_DEBUG, \"Palette_Emulation_Reload() SMS/GG\");\r\n#endif\r\n\r\n    switch (g_driver->id)\r\n    {\r\n    case DRV_SMS:\r\n        for (int i = 0; i != 32; i++)\r\n        {\r\n            ALLEGRO_COLOR color;\r\n            Palette_Compute_RGB_SMS(&color, i);\r\n            Palette_Emulation_SetColor(i, color);\r\n        }\r\n        break;\r\n    case DRV_GG:\r\n        for (int i = 0; i != 32; i++)\r\n        {\r\n            ALLEGRO_COLOR color;\r\n            Palette_Compute_RGB_GG(&color, i * 2);\r\n            Palette_Emulation_SetColor(i, color);\r\n        }\r\n        break;\r\n    }\r\n}\r\n\r\nu32     Palette_MakeHostColor(int color_format, int r, int g, int b)\r\n{\r\n    assert( (r&~0xFF)==0 && (g&~0xFF)==0 && (b&~0xFF)==0 );\r\n\r\n    switch (color_format)\r\n    {\r\n    case ALLEGRO_PIXEL_FORMAT_RGB_565:\r\n        r >>= 3;\r\n        g >>= 2;\r\n        b >>= 3;\r\n        return (r << 11) | (g << 5) | (b);\r\n    case ALLEGRO_PIXEL_FORMAT_RGB_555:\r\n        r >>= 3;\r\n        g >>= 3;\r\n        b >>= 3;\r\n        return (r << 10) | (g << 5) | (b);\r\n    case ALLEGRO_PIXEL_FORMAT_BGR_565:\r\n        r >>= 3;\r\n        g >>= 2;\r\n        b >>= 3;\r\n        return (b << 11) | (g << 5) | (r);\r\n    case ALLEGRO_PIXEL_FORMAT_BGR_555:\r\n        r >>= 3;\r\n        g >>= 3;\r\n        b >>= 3;\r\n        return (b << 10) | (g << 5) | (b);\r\n    case ALLEGRO_PIXEL_FORMAT_ARGB_8888:\r\n    case ALLEGRO_PIXEL_FORMAT_XRGB_8888:\r\n        return (0xFF << 24) | (r << 16) | (g << 8) | (b);\r\n    case ALLEGRO_PIXEL_FORMAT_RGBA_8888:\r\n    case ALLEGRO_PIXEL_FORMAT_RGBX_8888:\r\n        return    (r << 24) | (g << 16) | (b << 8) | (0xFF);\r\n    case ALLEGRO_PIXEL_FORMAT_ABGR_8888:\r\n    case ALLEGRO_PIXEL_FORMAT_XBGR_8888:\r\n        return (0xFF << 24) | (b << 16) | (g << 8) | (r);\r\n    }\r\n\r\n    if (color_format != 0)  // During init\r\n        Msg(MSGT_DEBUG, \"Palette_MakeHostColor() failed, unknown format: %d\", color_format);\r\n    return 0;\r\n}\r\n\r\nu32     Palette_MakeHostColor(int format, ALLEGRO_COLOR color)\r\n{\r\n    return Palette_MakeHostColor(format, color.r*255, color.g*255, color.b*255);\r\n}\r\n\r\nvoid    Palette_Emulation_SetColor(int idx, ALLEGRO_COLOR color)\r\n{\r\n    assert(idx >= 0 && idx < 32);\r\n    Palette_Emulation[idx] = color;\r\n    Palette_EmulationToHostGui[idx] = Palette_MakeHostColor(g_gui_buffer_format, color);\r\n    Palette_EmulationToHostGame[idx] = Palette_MakeHostColor(g_screenbuffer_format, color);\r\n    Palette_EmulationFlags[idx] |= PALETTE_EMULATION_FLAGS_DIRTY;\r\n    Palette_EmulationDirtyAny = TRUE;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Palette_Compute_RGB_SMS(ALLEGRO_COLOR *out_color, int i)\r\n{\r\n    int v;\r\n    int r, g, b;\r\n\r\n    v = PRAM[i] & 0x03;\r\n    r = (v) | (v << 2) | (v << 4) | (v << 6);\r\n\r\n    v = (PRAM[i] >> 2) & 0x03;\r\n    g = (v) | (v << 2) | (v << 4) | (v << 6);\r\n\r\n    v = (PRAM[i] >> 4) & 0x03;\r\n    b = (v) | (v << 2) | (v << 4) | (v << 6);\r\n\r\n    // Save output\r\n    *out_color = al_map_rgb(r, g, b);\r\n}\r\n\r\n// Note: if changing the meaning of 'i', please update datadump.c which uses it\r\nvoid    Palette_Compute_RGB_GG(ALLEGRO_COLOR *out_color, int i)\r\n{\r\n    int v;\r\n    int r, g, b;\r\n\r\n    // ----bbbb ggggrrrr (GG) -> --rrrrrr --gggggg --bbbbbb (RGB)\r\n    v = PRAM[i] & 0x0F;\r\n    r = (v) | (v << 4);\r\n\r\n    v = PRAM[i] & 0xF0;\r\n    g = (v >> 4) | (v);\r\n\r\n    v = PRAM[i + 1] & 0x0F;\r\n    b = (v) | (v << 4);\r\n\r\n    // Save output\r\n    *out_color = al_map_rgb(r, g, b);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/palette.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - palette.h\n// Palette management - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define PALETTE_EMU_GAME_SIZE   (32)    // Max of all emulated system palette size\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nextern ALLEGRO_COLOR Palette_Emulation[PALETTE_EMU_GAME_SIZE];\nextern u32           Palette_EmulationToHostGui[PALETTE_EMU_GAME_SIZE];\nextern u16           Palette_EmulationToHostGame[PALETTE_EMU_GAME_SIZE];\nextern int           Palette_EmulationFlags[PALETTE_EMU_GAME_SIZE];\nextern bool          Palette_EmulationDirtyAny;\n\ntypedef enum\n{\n    PALETTE_EMULATION_FLAGS_DIRTY   = 0x0001,\n} t_palette_emulation_flags;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Palette_Init();\nvoid    Palette_Close();\nvoid    Palette_UpdateAfterRedraw();\n\nvoid    Palette_Emulation_Reset();\nvoid    Palette_Emulation_Reload();\nvoid    Palette_Emulation_SetColor(int idx, ALLEGRO_COLOR color);\n\nvoid    Palette_Compute_RGB_SMS (ALLEGRO_COLOR *color, int i);\nvoid    Palette_Compute_RGB_GG  (ALLEGRO_COLOR *color, int i);\n\nu32     Palette_MakeHostColor(int format, int r, int g, int b);\nu32     Palette_MakeHostColor(int format, ALLEGRO_COLOR color);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/patch.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - patch.c\n// Patching System - Code\n//-----------------------------------------------------------------------------\n\n// #define DEBUG_PATCHES\n#include \"shared.h\"\n#include \"patch.h\"\n#include \"debugger.h\"\n#include \"libparse.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_patches Patches;\n\n// Create a new patch\nt_patch *       Patch_New()\n{\n    // Allocate new patch\n    t_patch* patch = (t_patch*)malloc(sizeof (t_patch));\n    if (patch == NULL)\n        return (NULL); // FIXME: abort?\n\n    // Clear with default values\n    patch->rom_patches      = NULL;\n    patch->mem_patches      = NULL;\n    patch->crc_type         = PATCH_CRC_TYPE_MEKACRC;\n    patch->crc_mekacrc.v[0] = 0x00000000;\n    patch->crc_mekacrc.v[1] = 0x00000000;\n    patch->crc_crc32        = 0x00000000;\n\n    // Add to global patch list\n    list_add (&Patches.patches, patch);\n\n    return (patch);\n}\n\n// Create a new patch action\nt_patch_action *        Patch_Action_New()\n{\n    t_patch_action* action = (t_patch_action*)malloc (sizeof (t_patch_action));\n    if (action == NULL)\n        return (NULL); // FIXME: abort\n\n    // Clear with default values\n    action->address     = 0x0000;\n    action->data        = NULL;\n    action->data_length = 0;\n\n    return (action);\n}\n\n// Parse and handle content of a line from MEKA.PAT\nint Patches_List_Parse_Line(const char *line)\n{\n    char s[256];\n\n    // ConsolePrintf(\"line = %s\\n\", line);\n\n    // Check if we're on a new patch entry\n    if (line[0] == '[') // && (line[17] == ']')\n    {\n        // Create the new patch\n        t_patch *patch = Patch_New();\n        if (patch == NULL)\n            return (1); // Not enough memory\n        Patches.patch_current = patch;\n\n        // Find checksum type and value\n        const char* p = strchr (line+1, ']');\n        if (p == NULL)\n            return (2); // Unrecognized instruction\n        strncpy (s, line+1, p-(line+1));\n        s[p-(line+1)] = 0;\n\n        // - Match all ROM\n        if (strcmp(s, \"*\") == 0)\n        {\n            patch->crc_type = PATCH_CRC_TYPE_NONE;\n            return (0);\n        }\n\n        // Specify CRC type\n        p = strchr (s, ':');\n        if (p == NULL)\n        {\n            // Default to MekaCRC type\n            patch->crc_type = PATCH_CRC_TYPE_MEKACRC;\n            sscanf (s, \"%08X%08X\", &patch->crc_mekacrc.v[0], &patch->crc_mekacrc.v[1]);\n            return (0);\n        }\n\n        // - CRC32\n        if (strncmp(s, \"crc32:\", 6) == 0)\n        {\n            patch->crc_type = PATCH_CRC_TYPE_CRC32;\n            sscanf  (s+6, \"%08X\", &patch->crc_crc32);\n            return (0);\n        }\n\n        // - MekaCRC\n        if (strncmp(s, \"mekacrc:\", 8) == 0)\n        {\n            patch->crc_type = PATCH_CRC_TYPE_MEKACRC;\n            sscanf (s+8, \"%08X%08X\", &patch->crc_mekacrc.v[0], &patch->crc_mekacrc.v[1]);\n            return (0);\n        }\n\n        return (2); // Unrecognized instruction ... FIXME: should return a better error!\n    }\n\n    // Ensure that a patch was already created\n    if (Patches.patch_current == NULL)\n        return (3);\n\n    {\n        // Create new action\n        t_patch_action *action = Patch_Action_New();\n        if (action == NULL)\n            return (1); // Not enough memory\n\n        // Add to ROM action list in patch\n        // FIXME: this is ugly parsing...\n        if (strnicmp (line, \"ROM[\", 4) == 0)\n            list_add_to_end (&Patches.patch_current->rom_patches, action);\n        else if (strnicmp (line, \"MEM[\", 4) == 0)\n            list_add_to_end (&Patches.patch_current->mem_patches, action);\n        else\n            return (2);\n\n        // Get address\n        // NB: don't test return value of ParseConstant because it currently return false because of the trailing ']'\n        t_debugger_value v;\n        v.data = 0;\n        Debugger_Eval_ParseConstant(line+4, &v, DEBUGGER_EVAL_VALUE_FORMAT_INT_HEX);\n        action->address = v.data;\n        // ConsolePrintf(\"Address = %x\\n\", action->address);\n\n        const char* p = strchr(line, '=');\n        if (p == NULL)\n            return (2);\n\n        // Get values\n        p++;\n        do\n        {\n            int value;\n            if (sscanf (p, \"%X\", &value) == 0)\n                break;\n            while (isxdigit (*p))\n                p++;\n            if ((action->data_length % 32) == 0)\n            {\n                action->data = (u8*)realloc(action->data, action->data_length + 32);\n                if (action->data == NULL)\n                    return (1); // Not enough memory\n            }\n            // ConsolePrintf(\"data[%i] = %04x\\n\", action->data_length, value);\n            action->data[action->data_length++] = value;\n        }\n        while (*p++ == ',');\n    }\n    return (0);\n}\n\n// Load MEKA.PAT\nvoid            Patches_List_Init()\n{\n    t_tfile *   tf;\n    t_list *    lines;\n\n    ConsolePrint(Msg_Get(MSG_Patch_Loading));\n\n    // Initializing system\n    Patches.patches = NULL;\n    Patches.patch_current = NULL;\n\n    // Open and read MEKA.PAT file\n    if ((tf = tfile_read (Patches.filename)) == NULL)\n    {\n        ConsolePrintf (\"%s\\n\", meka_strerror());\n        return;\n    }\n\n    // Ok\n    ConsolePrint(\"\\n\");\n\n    // Parse each line\n    int line_cnt = 0;\n    for (lines = tf->data_lines; lines; lines = lines->next)\n    {\n        char* line = (char*)lines->elem;\n        line_cnt += 1;\n\n        StrLower(line);\n\n        // Remove comments and space\n        char* p;\n        if ((p = strchr (line, ';')) != NULL)\n            *p = EOSTR;\n        StrRemoveBlanks (line);\n        if (line[0] == EOSTR)\n            continue;\n\n        switch (Patches_List_Parse_Line (line))\n        {\n        case 1: tfile_free(tf); Quit_Msg(\"%s\", Msg_Get(MSG_Error_Memory));                   break;\n        case 2: tfile_free(tf); Quit_Msg(Msg_Get(MSG_Patch_Unrecognized), line_cnt);   break;\n        case 3: tfile_free(tf); Quit_Msg(Msg_Get(MSG_Patch_Missing), line_cnt);        break;\n        }\n    }\n\n    Patches.patch_current = NULL;\n\n    // Free file data\n    tfile_free(tf);\n}\n\n//-----------------------------------------------------------------------------\n// Patch_Find ()\n// Find patch for given media image\n// Note: return the first patch only\n//-----------------------------------------------------------------------------\nt_patch *   Patch_Find (t_media_image *media_image)\n{\n    t_list *patches;\n\n    #ifdef DEBUG_PATCHES\n        Msg(MSGT_DEBUG, \"Patch_Find()\");\n    #endif\n\n    // Linear find\n    for (patches = Patches.patches; patches != NULL; patches = patches->next)\n    {\n        t_patch* patch = (t_patch*)patches->elem;\n\n        #ifdef DEBUG_PATCHES\n            Msg(MSGT_DEBUG, \"- Comparing mekacrc:%08X.%08X, crc32:%08X\", patch->crc_mekacrc.v[0], patch->crc_mekacrc.v[1], patch->crc_crc32);\n        #endif\n\n        if (patch->crc_type == PATCH_CRC_TYPE_NONE)\n            return (patch);\n        if (patch->crc_type == PATCH_CRC_TYPE_MEKACRC)\n            if (media_image->mekacrc.v[0] == patch->crc_mekacrc.v[0] && media_image->mekacrc.v[1] == patch->crc_mekacrc.v[1])\n                return (patch);\n        if (patch->crc_type == PATCH_CRC_TYPE_CRC32)\n            if (media_image->crc32 == patch->crc_crc32)\n                return (patch);\n    }\n\n    // No patch found\n    #ifdef DEBUG_PATCHES\n        Msg(MSGT_DEBUG, \"-> not found\");\n    #endif\n    return (NULL);\n}\n\n// Find patch for current ROM\nvoid        Patches_ROM_Initialize()\n{\n    // Find patch for current ROM\n    Patches.patch_current = Patch_Find (&g_media_rom);\n}\n\n// Apply patches to current ROM\nvoid        Patches_ROM_Apply()\n{\n    t_patch *patch = Patches.patch_current;\n    if (patch == NULL)\n        return;\n\n    // Apply ROM patches\n    for (t_list* actions = patch->rom_patches; actions != NULL; actions = actions->next)\n    {\n        t_patch_action* action = (t_patch_action*)actions->elem;\n\n        // Apply all bytes\n        for (int i = 0; i < action->data_length; i++)\n        {\n            const int addr = action->address + i;\n            if (addr < 0 || addr >= tsms.Size_ROM)\n            {\n                Msg(MSGT_USER, Msg_Get(MSG_Patch_Out_of_Bound), \"ROM\", addr);\n                return;\n            }\n            #ifdef DEBUG_PATCHES\n                Msg(MSGT_DEBUG, \"Patch ROM[%04X] = %02X\", addr, action->data[i]);\n            #endif\n            ROM[addr] = action->data[i];\n        }\n    }\n}\n\n// Apply real-time patches to memory map\nvoid        Patches_MEM_Apply()\n{\n    t_patch *patch = Patches.patch_current;\n    t_list *actions;\n    if (patch == NULL)\n        return;\n\n    // Apply MEM patches\n    for (actions = patch->mem_patches; actions != NULL; actions = actions->next)\n    {\n        t_patch_action* action = (t_patch_action*)actions->elem;\n\n        // Apply all bytes\n        int i;\n        int address = action->address;\n        int length = action->data_length;\n        if (address < 0x0000 || address > 0xFFFF || (address + length - 1) < 0x0000 || (address + length - 1) > 0xFFFF)\n        {\n            Msg(MSGT_USER, Msg_Get(MSG_Patch_Out_of_Bound), \"MEM\", address);\n            return;\n        }\n        for (i = 0; i < length; i++)\n        {\n            #ifdef DEBUG_PATCHES\n                Msg(MSGT_DEBUG, \"Patch MEM[%04X] = %02X\", address, action->data[i]);\n            #endif\n            Mem_Pages [address >> 13] [address] = action->data[i];\n            address++;\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/patch.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - patch.h\n// Patching System - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define PATCH_ACTION_SEEK               (1)\n#define PATCH_ACTION_WRITE              (2)\n\n#define PATCH_ACTION_SEEK_STR           \"seek\"\n#define PATCH_ACTION_WRITE_STR          \"write\"\n\n#define PATCH_CRC_TYPE_NONE             (0) // Apply to all ROM!\n#define PATCH_CRC_TYPE_MEKACRC          (1)\n#define PATCH_CRC_TYPE_CRC32            (2)\n\n#define PATCH_CRC_MATCH_ALL             \"*\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_patch_action\n{\n    int         address;\n    int         data_length;\n    u8 *        data;\n};\n\nstruct t_patch\n{\n    int         crc_type;\n    t_meka_crc  crc_mekacrc;\n    u32         crc_crc32;\n    t_list *    rom_patches;\n    t_list *    mem_patches;\n};\n\nstruct t_patches\n{\n    char        filename[FILENAME_LEN];\n    t_list *    patches;\n    t_patch *   patch_current;\n};\n\nextern t_patches Patches;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n// Load MEKA.PAT\nvoid    Patches_List_Init ();\n\n// Apply patches\nvoid    Patches_ROM_Initialize();\nvoid    Patches_ROM_Apply();\nvoid    Patches_MEM_Apply();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/periph.cpp",
    "content": "#include \"shared.h\"\r\n#include \"periph.h\"\r\n#include \"inputs_t.h\"\r\n#include \"lightgun.h\"\r\n#include \"rapidfir.h\"\r\n\r\n// FIXME: Clean/write and merge lightgun.* here\r\n// FIXME: Clean/write and merge sportpad.* here\r\n// FIXME: Clean/write and merge paddle control stuff here\r\n\r\nvoid Peripherals_Init()\r\n{\r\n    Peripherals_MachineReset();\r\n}\r\n\r\nvoid Peripherals_MachineReset()\r\n{\r\n    LightPhaser_Init();\r\n    RapidFire_Init();\r\n\r\n    for (int i = 0; i < 2; i++)\r\n    {\r\n        // Paddle Control\r\n        // FIXME\r\n        {\r\n            t_peripheral_paddle* p = &Inputs.Paddle[i];\r\n            p->x = 0;\r\n        }\r\n\r\n        // Sports Pad\r\n        // FIXME\r\n        {\r\n            t_peripheral_sportspad* p = &Inputs.SportsPad[i];\r\n            p->x = p->y = 0;\r\n            p->latch = 0;\r\n        }\r\n\r\n        // Graphic Board v2\r\n        {\r\n            t_peripheral_graphic_board_v2* p = &Inputs.GraphicBoardV2[i];\r\n            p->unknown = 0xFE;\r\n            p->buttons = 0;\r\n            p->x = p->y = 0;\r\n            p->read_index = 0;\r\n        }\r\n    }\r\n}\r\n\r\n// FIXME: Rewrite properly\r\nvoid Peripherals_WritePort3F(u8 old_value, u8 new_value)\r\n{\r\n    // Graphic Board v2.0\r\n    if (Inputs.Peripheral[0] == INPUT_GRAPHICBOARD_V2)\r\n    {\r\n        if ((old_value ^ new_value) & 0x20)\r\n            Inputs.GraphicBoardV2[0].read_index++;\r\n        if (new_value & 0x10)\r\n            Inputs.GraphicBoardV2[0].read_index = 0;\r\n    }\r\n    if (Inputs.Peripheral[1] == INPUT_GRAPHICBOARD_V2)\r\n    {\r\n        if ((old_value ^ new_value) & 0x80)\r\n            Inputs.GraphicBoardV2[1].read_index++;\r\n        if (new_value & 0x40)\r\n            Inputs.GraphicBoardV2[1].read_index = 0;\r\n    }\r\n\r\n    // SportsPad\r\n    // FIXME: This works-ish for known software but it's nonsense, need to rewrite\r\n    if ((old_value & 0xF) != (new_value & 0xF))\r\n        Inputs.SportsPad[0].latch = Inputs.SportsPad[1].latch = 1;\r\n    if (new_value == 0x0D) \r\n        Inputs.SportsPad[0].latch ^= 1;\r\n    if (new_value == 0x07) \r\n        Inputs.SportsPad[1].latch ^= 1;\r\n}\r\n\r\n// FIXME: This is terrible. Write something a little less 1998 please.\r\n// 1. Rewrite Sports Pad emulation correctly (now that we know how latch workes)\r\n// 2. Tune the function below so that it is playable with a mouse\r\nstatic void    SportsPad_Update_Axis(s8 *v, int move)\r\n{\r\n    int   vel;\r\n    int   limit = 50; // Technically 63, but in practice it is much less\r\n\r\n    vel = *v + (move / 2);\r\n\r\n    if (vel > limit) vel = limit;\r\n    else if (vel < -limit) vel = -limit;\r\n\r\n    if (vel > 0) vel -= 1;\r\n    if (vel < 0) vel += 1;\r\n\r\n    if (vel >= 10) vel -= 10;\r\n    else\r\n        if (vel <= -10) vel += 10;\r\n\r\n    *v = vel;\r\n}\r\n\r\nvoid    Peripherals_SportsPad_Update(int player, int device_x_rel, int device_y_rel)\r\n{\r\n    SportsPad_Update_Axis((s8*)&Inputs.SportsPad[player].x, -device_x_rel);\r\n    SportsPad_Update_Axis((s8*)&Inputs.SportsPad[player].y, -device_y_rel);\r\n}\r\n\r\nvoid    Peripherals_GraphicBoardV2_Update(int player, int x, int y, int buttons)\r\n{\r\n    t_peripheral_graphic_board_v2* p = &Inputs.GraphicBoardV2[player];\r\n\r\n    y += 32;\r\n    y += 4;\r\n    x -= 4;\r\n\r\n    if (x < 0) x = 0;\r\n    if (x > 255) x = 255;\r\n    p->x = (u8)x;\r\n\r\n    if (y < 0) y = 0;\r\n    if (y > 255) y = 255;\r\n    p->y = (u8)y;\r\n\r\n    p->buttons = buttons;\r\n    if (player == 0)\r\n    {\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_1)) p->buttons ^= (1 << 0);\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_2)) p->buttons ^= (1 << 1);\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_3)) p->buttons ^= (1 << 2);\r\n    }\r\n    else if (player == 1)\r\n    {\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_4)) p->buttons ^= (1 << 0);\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_5)) p->buttons ^= (1 << 1);\r\n        if (Inputs_KeyDown(ALLEGRO_KEY_6)) p->buttons ^= (1 << 2);\r\n    }\r\n    \r\n    //Msg(MSGT_DEBUG, \"x=%d y=%d, %x\\n\", p->x, p->y, p->buttons);\r\n}\r\n\r\n"
  },
  {
    "path": "meka/srcs/periph.h",
    "content": "\r\nvoid Peripherals_Init();\r\nvoid Peripherals_MachineReset();\r\nvoid Peripherals_WritePort3F(u8 old_v, u8 new_v);\r\n\r\nvoid Peripherals_SportsPad_Update(int player, int device_x_rel, int device_y_rel);\r\nvoid Peripherals_GraphicBoardV2_Update(int player, int x, int y, int buttons);\r\n\r\n\r\n"
  },
  {
    "path": "meka/srcs/platform/macosx/osxhelpers.h",
    "content": "#ifndef OSXHELPERS_H_\n#define OSXHELPERS_H_\n\nvoid GetResourcePath( char* outBuffer, int bufferSize );\nvoid GetWritableInternalResourcePath( char *outBuffer, int bufferSize );\nvoid GetWritableExternalResourcePath( char *outBuffer, int bufferSize );\nvoid PopulateWritableInternalResourcesPath( const char *path , const char **files );\n\n\n#endif\n"
  },
  {
    "path": "meka/srcs/platform/macosx/osxhelpers.mm",
    "content": "// Mac OS \n#include <CoreFoundation/CoreFoundation.h>\n#import <Foundation/Foundation.h>\n#include \"osxhelpers.h\"\n\nstatic void NSStringToCString(NSString *s, char *out, size_t outSize);\nstatic BOOL MakeDirectoryIfAbsent(NSURL *url, NSError **error);\nstatic void CopyPathToBuffer(NSSearchPathDirectory searchPath, NSString *subDirectory, char *outBuffer, size_t bufferSize);\nstatic NSURL* strToNSURL(const char *str);\nstatic NSString *strToNSString(const char *str);\n\nstatic void NSStringToCString(NSString *s, char *out, size_t outSize)\n{\n    [s getCString:out\n        maxLength:outSize\n         encoding:NSUTF8StringEncoding];\n}\n\nstatic NSString *strToNSString(const char *str)\n{\n    return [NSString stringWithCString:str\n                              encoding:NSUTF8StringEncoding];\n}\n\nstatic NSURL* strToNSURL(const char *str)\n{\n    return [NSURL URLWithString:strToNSString(str)];\n\n}\n\nvoid GetResourcePath( char* outBuffer, int bufferSize )\n{\n    @autoreleasepool {\n        NSStringToCString([[NSBundle mainBundle] resourcePath], \n                          outBuffer, \n                          bufferSize);\n    }\n}\n\nstatic BOOL MakeDirectoryIfAbsent(NSURL *url, NSError **error)\n{\n    BOOL isDirectory;\n    NSFileManager *fileManager  = [NSFileManager defaultManager];\n    if (![fileManager fileExistsAtPath:[url path]\n                           isDirectory:&isDirectory]) {\n        return [fileManager createDirectoryAtURL:url\n                     withIntermediateDirectories:YES\n                                      attributes:[NSDictionary dictionary]\n                                           error:error];\n    }\n    return YES;\n}\n\nstatic void CopyPathToBuffer(NSSearchPathDirectory searchPath, NSString *subDirectory, char *outBuffer, size_t bufferSize)\n{\n\tNSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:searchPath\n\t\t\t\t\t                                     inDomains:NSUserDomainMask] firstObject];\n    url = [url URLByAppendingPathComponent:subDirectory];\n    if (url != nil) {\n        NSError *error;\n        if (!MakeDirectoryIfAbsent(url, &error)) {\n            NSLog(@\"Error while creating: %@: %@\", url, error);\n            GetResourcePath( outBuffer, bufferSize );\n        }\n        else {\n            NSStringToCString([url path], outBuffer, bufferSize);\n        }\n    }\n    else {\n        GetResourcePath( outBuffer, bufferSize );\n    }\n}\n\nvoid PopulateWritableInternalResourcesPath( const char *path , const char **files)\n{\n    @autoreleasepool {\n        NSError *error = nil; // used to store errors during copying\n        NSString *destPath = strToNSString(path);\n        NSString *resourcePath = [[NSBundle mainBundle] resourcePath];\n        const char **itr = files;\n        NSFileManager *fm = [NSFileManager defaultManager];\n        while (*itr) {\n            NSString *filename = strToNSString(*itr);\n            NSString *srcFile = [resourcePath stringByAppendingPathComponent:filename];\n            NSString *destFile = [destPath stringByAppendingPathComponent:filename];\n            if (![fm fileExistsAtPath:destFile]) {\n                BOOL copyOK = [fm copyItemAtPath:srcFile\n                                          toPath:destFile\n                                           error:&error];\n                if (!copyOK) {\n                    NSLog(@\"Error while copying %@ to %@ (%@)\",\n                          srcFile,\n                          destPath,\n                          error);\n                }\n\n            }\n            ++itr;\n        }\n    }\n}\n\n\nvoid GetWritableInternalResourcePath( char *outBuffer, int bufferSize )\n{\n    @autoreleasepool {\n        CopyPathToBuffer(NSApplicationSupportDirectory,\n                         [[NSBundle mainBundle] bundleIdentifier],\n                         outBuffer,\n                         bufferSize);\n    }\n}\n\nvoid GetWritableExternalResourcePath( char *outBuffer, int bufferSize )\n{\n    @autoreleasepool {\n        CopyPathToBuffer(NSDocumentDirectory,\n                         @\"Meka\",\n                         outBuffer,\n                         bufferSize);\n    }\n}\n"
  },
  {
    "path": "meka/srcs/projects/msvc/Meka.plg",
    "content": "<html>\r\n<body>\r\n<pre>\r\n<h1>Build Log</h1>\r\n<h3>\r\n--------------------Configuration: Meka - Win32 Debug--------------------\r\n</h3>\r\n<h3>Command Lines</h3>\r\nCreating temporary file \"C:\\DOCUME~1\\omar\\LOCALS~1\\Temp\\RSP24B.tmp\" with contents\r\n[\r\n/nologo /MLd /W3 /Gm /GX /ZI /Od /I \"..\" /I \"..\\tools\" /I \"..\\sound\" /I \"d:\\djgpp\\seal\\src\" /I \"d:\\djgpp\\zlib113\" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"X86_ASM\" /D \"MEKA_SOUND\" /D \"MEKA_EAGLE\" /D \"MEKA_ZIP\" /D \"MEKA_JOY\" /D \"MEKA_Z80_DEBUGGER\" /D \"MARAT_Z80\" /Fp\"Debug/Meka.pch\" /YX /Fo\"Debug/\" /Fd\"Debug/\" /FD /GZ /c \r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\ym2413hd.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\fmeditor.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\fmunit.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\s_init.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\s_log.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\s_misc.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\s_opl.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\sasound.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\sound.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\vgm.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sound\\wav.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\zip\\unzip.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tools\\liblist.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tools\\libmy.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tools\\libparse.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tools\\tfile.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\m6502\\m6502.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\z80marat\\Debug.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\z80marat\\Z80.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\z80marat\\Z80Call.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\about.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\desktop.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_action.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_apps.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_box.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_colors.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_emu.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_file.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_init.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_menu.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_menu_i.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_menu_t.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_mouse.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_tools.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_update.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\g_widget.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\gui.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\options.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\themes.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\themes_b.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\beam.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\blit.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\blitintf.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\palette.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tileview.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tms_vdp.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\video.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\video_c.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\video_m2.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\video_m5.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\video_t.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\glasses.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\keyboard.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\keysname.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\lightgun.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\rapidfir.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sportpad.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tvoekaki.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\nes.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\nes_maps.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\nes_ppu.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\bios.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\coleco.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\drivers.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\ioports.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\machine.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sf7000.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sg1ksc3k.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\areplay.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\bmemory.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\capture.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\checksum.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\clock.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\commport.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\config.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\config_j.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\config_v.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\country.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\cpu.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\data.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\datadump.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\debugger.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\eeprom.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\effects.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\errors.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\fdc765.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\file.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\fonts.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\fskipper.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\games.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\inputs.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\inputs_c.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\inputs_f.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\inputs_i.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\inputs_t.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\inputs_u.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\mainloop.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\mappers.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\meka.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\memory.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\message.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\misc.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\patch.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\register.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\saves.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\sdsc.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\techinfo.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\textbox.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\textview.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tools.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tools_t.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\tvtype.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\vlfn.c\"\r\n\"Z:\\work\\omar\\Meka\\Srcs\\vmachine.c\"\r\n]\r\nCreating command line \"cl.exe @C:\\DOCUME~1\\omar\\LOCALS~1\\Temp\\RSP24B.tmp\" \r\nCreating temporary file \"C:\\DOCUME~1\\omar\\LOCALS~1\\Temp\\RSP24C.tmp\" with contents\r\n[\r\n/nologo /MLd /W3 /Gm /GX /ZI /Od /I \"..\" /I \"..\\tools\" /I \"..\\sound\" /I \"d:\\djgpp\\seal\\src\" /I \"d:\\djgpp\\zlib113\" /I \"d:\\djgpp\\zlib\\\\\" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"X86_ASM\" /D \"MEKA_SOUND\" /D \"MEKA_EAGLE\" /D \"MEKA_ZIP\" /D \"MEKA_JOY\" /D \"MEKA_Z80_DEBUGGER\" /D \"MARAT_Z80\" /Fp\"Debug/Meka.pch\" /YX /Fo\"Debug/\" /Fd\"Debug/\" /FD /GZ /c \r\n\"Z:\\work\\omar\\Meka\\Srcs\\specials.c\"\r\n]\r\nCreating command line \"cl.exe @C:\\DOCUME~1\\omar\\LOCALS~1\\Temp\\RSP24C.tmp\" \r\nCreating temporary file \"C:\\DOCUME~1\\omar\\LOCALS~1\\Temp\\RSP24D.tmp\" with contents\r\n[\r\nkernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib alleg.lib audw32vc.lib zlib.lib /nologo /subsystem:windows /incremental:yes /pdb:\"Debug/mekaw.pdb\" /debug /machine:I386 /out:\"debug/mekaw.exe\" /pdbtype:sept /libpath:\"d:/djgpp/seal/lib/win32/\" /libpath:\"d:/djgpp/zlib113\" /section:.text,erw /section:.data,erw /section:.bss,erw \r\n.\\Debug\\psg.obj\r\n.\\Debug\\emu2413.obj\r\n.\\Debug\\mekaintf.obj\r\n.\\Debug\\ym2413hd.obj\r\n.\\Debug\\fmeditor.obj\r\n.\\Debug\\fmunit.obj\r\n.\\Debug\\s_init.obj\r\n.\\Debug\\s_log.obj\r\n.\\Debug\\s_misc.obj\r\n.\\Debug\\s_opl.obj\r\n.\\Debug\\sasound.obj\r\n.\\Debug\\sound.obj\r\n.\\Debug\\vgm.obj\r\n.\\Debug\\wav.obj\r\n.\\Debug\\unzip.obj\r\n.\\Debug\\liblist.obj\r\n.\\Debug\\libmy.obj\r\n.\\Debug\\libparse.obj\r\n.\\Debug\\tfile.obj\r\n.\\Debug\\m6502.obj\r\n.\\Debug\\Debug.obj\r\n.\\Debug\\Z80.obj\r\n.\\Debug\\Z80Call.obj\r\n.\\Debug\\about.obj\r\n.\\Debug\\desktop.obj\r\n.\\Debug\\g_action.obj\r\n.\\Debug\\g_apps.obj\r\n.\\Debug\\g_box.obj\r\n.\\Debug\\g_colors.obj\r\n.\\Debug\\g_emu.obj\r\n.\\Debug\\g_file.obj\r\n.\\Debug\\g_init.obj\r\n.\\Debug\\g_menu.obj\r\n.\\Debug\\g_menu_i.obj\r\n.\\Debug\\g_menu_t.obj\r\n.\\Debug\\g_mouse.obj\r\n.\\Debug\\g_tools.obj\r\n.\\Debug\\g_update.obj\r\n.\\Debug\\g_widget.obj\r\n.\\Debug\\gui.obj\r\n.\\Debug\\options.obj\r\n.\\Debug\\specials.obj\r\n.\\Debug\\themes.obj\r\n.\\Debug\\themes_b.obj\r\n.\\Debug\\beam.obj\r\n.\\Debug\\blit.obj\r\n.\\Debug\\blitintf.obj\r\n.\\Debug\\palette.obj\r\n.\\Debug\\tileview.obj\r\n.\\Debug\\tms_vdp.obj\r\n.\\Debug\\video.obj\r\n.\\Debug\\video_c.obj\r\n.\\Debug\\video_m2.obj\r\n.\\Debug\\video_m5.obj\r\n.\\Debug\\video_t.obj\r\n.\\Debug\\glasses.obj\r\n.\\Debug\\keyboard.obj\r\n.\\Debug\\keysname.obj\r\n.\\Debug\\lightgun.obj\r\n.\\Debug\\rapidfir.obj\r\n.\\Debug\\sportpad.obj\r\n.\\Debug\\tvoekaki.obj\r\n.\\Debug\\nes.obj\r\n.\\Debug\\nes_maps.obj\r\n.\\Debug\\nes_ppu.obj\r\n.\\Debug\\bios.obj\r\n.\\Debug\\coleco.obj\r\n.\\Debug\\drivers.obj\r\n.\\Debug\\ioports.obj\r\n.\\Debug\\machine.obj\r\n.\\Debug\\sf7000.obj\r\n.\\Debug\\sg1ksc3k.obj\r\n.\\Debug\\areplay.obj\r\n.\\Debug\\bmemory.obj\r\n.\\Debug\\capture.obj\r\n.\\Debug\\checksum.obj\r\n.\\Debug\\clock.obj\r\n.\\Debug\\commport.obj\r\n.\\Debug\\config.obj\r\n.\\Debug\\config_j.obj\r\n.\\Debug\\config_v.obj\r\n.\\Debug\\country.obj\r\n.\\Debug\\cpu.obj\r\n.\\Debug\\data.obj\r\n.\\Debug\\datadump.obj\r\n.\\Debug\\debugger.obj\r\n.\\Debug\\eeprom.obj\r\n.\\Debug\\effects.obj\r\n.\\Debug\\errors.obj\r\n.\\Debug\\fdc765.obj\r\n.\\Debug\\file.obj\r\n.\\Debug\\fonts.obj\r\n.\\Debug\\fskipper.obj\r\n.\\Debug\\games.obj\r\n.\\Debug\\inputs.obj\r\n.\\Debug\\inputs_c.obj\r\n.\\Debug\\inputs_f.obj\r\n.\\Debug\\inputs_i.obj\r\n.\\Debug\\inputs_t.obj\r\n.\\Debug\\inputs_u.obj\r\n.\\Debug\\mainloop.obj\r\n.\\Debug\\mappers.obj\r\n.\\Debug\\meka.obj\r\n.\\Debug\\memory.obj\r\n.\\Debug\\message.obj\r\n.\\Debug\\misc.obj\r\n.\\Debug\\patch.obj\r\n.\\Debug\\register.obj\r\n.\\Debug\\saves.obj\r\n.\\Debug\\sdsc.obj\r\n.\\Debug\\techinfo.obj\r\n.\\Debug\\textbox.obj\r\n.\\Debug\\textview.obj\r\n.\\Debug\\tools.obj\r\n.\\Debug\\tools_t.obj\r\n.\\Debug\\tvtype.obj\r\n.\\Debug\\vlfn.obj\r\n.\\Debug\\vmachine.obj\r\n.\\videoasm.obj\r\n.\\eagle.obj\r\n.\\mappersa.obj\r\n]\r\nCreating command line \"link.exe @C:\\DOCUME~1\\omar\\LOCALS~1\\Temp\\RSP24D.tmp\"\r\n<h3>Output Window</h3>\r\nCompiling...\r\nym2413hd.c\r\nfmeditor.c\r\nfmunit.c\r\ns_init.c\r\ns_log.c\r\ns_misc.c\r\ns_opl.c\r\nZ:\\work\\omar\\Meka\\Srcs\\sound\\s_opl.c(92) : warning C4013: '_inp' undefined; assuming extern returning int\r\nZ:\\work\\omar\\Meka\\Srcs\\sound\\s_opl.c(111) : warning C4013: '_outp' undefined; assuming extern returning int\r\nsasound.c\r\nZ:\\work\\omar\\Meka\\Srcs\\sound\\sasound.c(589) : warning C4018: '<' : signed/unsigned mismatch\r\nZ:\\work\\omar\\Meka\\Srcs\\sound\\sasound.c(589) : warning C4018: '>=' : signed/unsigned mismatch\r\nsound.c\r\nvgm.c\r\nwav.c\r\nunzip.c\r\nliblist.c\r\nlibmy.c\r\nlibparse.c\r\ntfile.c\r\nm6502.c\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(26) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(26) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(26) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(31) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(31) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(37) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(38) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(54) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(54) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(55) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(55) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(74) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(84) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(91) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(92) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(234) : warning C4761: integral size mismatch in argument; conversion supplied\r\nZ:\\work\\omar\\Meka\\Srcs\\m6502\\m6502.c(234) : warning C4761: integral size mismatch in argument; conversion supplied\r\nZ:\\work\\omar\\Meka\\Srcs\\m6502\\m6502.c(235) : warning C4761: integral size mismatch in argument; conversion supplied\r\nZ:\\work\\omar\\Meka\\Srcs\\m6502\\m6502.c(236) : warning C4761: integral size mismatch in argument; conversion supplied\r\nZ:\\work\\omar\\Meka\\Srcs\\m6502\\m6502.c(236) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(26) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(26) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(26) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(31) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(31) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(37) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(38) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(54) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(54) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(55) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(55) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(74) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(84) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(91) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(92) : warning C4761: integral size mismatch in argument; conversion supplied\r\nz:\\work\\omar\\meka\\srcs\\m6502\\codes.h(234) : warning C4761: integral size mismatch in argument; converDebug.c\r\nsion supplied\r\nZ80.c\r\nZ80Call.c\r\nabout.c\r\ndesktop.c\r\ng_action.c\r\ng_apps.c\r\ng_box.c\r\ng_colors.c\r\ng_emu.c\r\ng_file.c\r\ng_init.c\r\ng_menu.c\r\ng_menu_i.c\r\ng_menu_t.c\r\ng_mouse.c\r\ng_tools.c\r\ng_update.c\r\ng_widget.c\r\ngui.c\r\noptions.c\r\nthemes.c\r\nthemes_b.c\r\nbeam.c\r\nblit.c\r\nblitintf.c\r\npalette.c\r\ntileview.c\r\ntms_vdp.c\r\nvideo.c\r\nvideo_c.c\r\nvideo_m2.c\r\nvideo_m5.c\r\nvideo_t.c\r\nglasses.c\r\nkeyboard.c\r\nkeysname.c\r\nlightgun.c\r\nrapidfir.c\r\nsportpad.c\r\ntvoekaki.c\r\nnes.c\r\nnes_maps.c\r\nnes_ppu.c\r\nbios.c\r\ncoleco.c\r\ndrivers.c\r\nioports.c\r\nmachine.c\r\nsf7000.c\r\nsg1ksc3k.c\r\nareplay.c\r\nbmemory.c\r\ncapture.c\r\nchecksum.c\r\nclock.c\r\ncommport.c\r\nconfig.c\r\nconfig_j.c\r\nconfig_v.c\r\ncountry.c\r\ncpu.c\r\ndata.c\r\ndatadump.c\r\ndebugger.c\r\neeprom.c\r\neffects.c\r\nerrors.c\r\nfdc765.c\r\nfile.c\r\nfonts.c\r\nfskipper.c\r\ngames.c\r\ninputs.c\r\ninputs_c.c\r\ninputs_f.c\r\ninputs_i.c\r\ninputs_t.c\r\ninputs_u.c\r\nmainloop.c\r\nmappers.c\r\nmeka.c\r\nZ:\\work\\omar\\Meka\\Srcs\\meka.c(315) : warning C4028: formal parameter 1 different from declaration\r\nZ:\\work\\omar\\Meka\\Srcs\\meka.c(315) : warning C4028: formal parameter 2 different from declaration\r\nmemory.c\r\nmessage.c\r\nmisc.c\r\npatch.c\r\nregister.c\r\nsaves.c\r\nsdsc.c\r\ntechinfo.c\r\ntextbox.c\r\ntextview.c\r\ntools.c\r\ntools_t.c\r\ntvtype.c\r\nvlfn.c\r\nvmachine.c\r\nCompiling...\r\nspecials.c\r\nLinking...\r\n\r\n\r\n\r\n<h3>Results</h3>\r\nmekaw.exe - 0 error(s), 42 warning(s)\r\n</pre>\r\n</body>\r\n</html>\r\n"
  },
  {
    "path": "meka/srcs/projects/msvc/Meka.rc",
    "content": "// Microsoft Visual C++ generated resource script.\r\n//\r\n#include \"resource.h\"\r\n\r\n#define APSTUDIO_READONLY_SYMBOLS\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Generated from the TEXTINCLUDE 2 resource.\r\n//\r\n#include \"windows.h\"\r\n#ifndef IDC_STATIC\r\n#define IDC_STATIC\t\t\t\t-1\r\n#endif\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n#undef APSTUDIO_READONLY_SYMBOLS\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// English (U.S.) resources\r\n\r\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n#ifdef _WIN32\r\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r\n#pragma code_page(1252)\r\n#endif //_WIN32\r\n\r\n#ifdef APSTUDIO_INVOKED\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// TEXTINCLUDE\r\n//\r\n\r\n1 TEXTINCLUDE \r\nBEGIN\r\n    \"resource.h\\0\"\r\nEND\r\n\r\n2 TEXTINCLUDE \r\nBEGIN\r\n    \"#include \"\"windows.h\"\"\\r\\n\"\r\n    \"\\0\"\r\nEND\r\n\r\n3 TEXTINCLUDE \r\nBEGIN\r\n    \"\\r\\n\"\r\n    \"\\0\"\r\nEND\r\n\r\n#endif    // APSTUDIO_INVOKED\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Icon\r\n//\r\n\r\n// Icon with lowest ID value placed first to ensure application icon\r\n// remains consistent on all systems.\r\nALLEGRO_ICON            ICON                    \"mekaw.ico\"\r\n#endif    // English (U.S.) resources\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// English (U.K.) resources\r\n\r\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\r\n#ifdef _WIN32\r\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\r\n#pragma code_page(1252)\r\n#endif //_WIN32\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Dialog\r\n//\r\n\r\nIDD_CONSOLE DIALOGEX 0, 0, 242, 244\r\nSTYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r\nCAPTION \"MEKA - Console\"\r\nFONT 8, \"Arial\", 400, 0, 0x0\r\nBEGIN\r\n    EDITTEXT        IDC_CONSOLE_TEXT,4,3,235,221,ES_MULTILINE | ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP\r\n    PUSHBUTTON      \"&Copy\",IDC_CONSOLE_COPY,4,227,37,14\r\n    PUSHBUTTON      \"&Quit\",IDC_CONSOLE_QUIT,135,227,50,14,WS_DISABLED\r\n    DEFPUSHBUTTON   \"&RUN\",IDC_CONSOLE_RUN,189,227,50,14,WS_DISABLED\r\n    CTEXT           \"Startup in progress...\",IDC_CONSOLE_INFO,45,227,86,14,SS_CENTERIMAGE | SS_SUNKEN\r\nEND\r\n\r\nIDD_SETUP DIALOGEX 0, 0, 242, 185\r\nSTYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r\nCAPTION \"xxx MEKA - Setup\"\r\nFONT 8, \"MS Shell Dlg\", 0, 0, 0x0\r\nBEGIN\r\n    DEFPUSHBUTTON   \"OK\",IDOK,134,167,50,14\r\n    PUSHBUTTON      \"Quit\",IDCLOSE,188,167,50,14\r\n    COMBOBOX        IDC_SETUP_VIDEO_DISPLAY_MODE,7,49,131,164,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r\n    LTEXT           \"xxx Resolution:\",IDC_SETUP_VIDEO_RESOLUTION_TEXT,7,38,219,11\r\n    COMBOBOX        IDC_SETUP_SOUND_SAMPLERATE,7,110,131,38,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r\n    LTEXT           \"xxx Sample rate:\",IDC_SETUP_SOUND_SAMPLERATE_TEXT,7,99,220,11\r\n    COMBOBOX        IDC_SETUP_LANGUAGE,7,144,131,107,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP\r\n    GROUPBOX        \"Language\",IDC_STATIC,2,132,237,32\r\n    GROUPBOX        \"Video\",IDC_STATIC,2,2,237,86\r\n    GROUPBOX        \"Audio\",IDC_STATIC,2,89,237,41\r\n    LTEXT           \"xxx Driver:\",IDC_SETUP_VIDEO_DRIVER_TEXT,7,12,220,11\r\n    COMBOBOX        IDC_SETUP_VIDEO_DRIVER,7,23,131,43,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r\n    LTEXT           \"Press ESCAPE during gameplay to hide user interface.\\nPress ALT-ENTER to toggle fullscreen mode.\",IDC_SETUP_VIDEO_NOTES,7,67,219,16\r\nEND\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// DESIGNINFO\r\n//\r\n\r\n#ifdef APSTUDIO_INVOKED\r\nGUIDELINES DESIGNINFO \r\nBEGIN\r\n    IDD_CONSOLE, DIALOG\r\n    BEGIN\r\n        LEFTMARGIN, 4\r\n        RIGHTMARGIN, 239\r\n        TOPMARGIN, 3\r\n        BOTTOMMARGIN, 241\r\n        HORZGUIDE, 216\r\n    END\r\n\r\n    IDD_SETUP, DIALOG\r\n    BEGIN\r\n        LEFTMARGIN, 2\r\n        RIGHTMARGIN, 239\r\n        VERTGUIDE, 7\r\n        VERTGUIDE, 138\r\n        TOPMARGIN, 2\r\n        BOTTOMMARGIN, 181\r\n    END\r\nEND\r\n#endif    // APSTUDIO_INVOKED\r\n\r\n#endif    // English (U.K.) resources\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n\r\n#ifndef APSTUDIO_INVOKED\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Generated from the TEXTINCLUDE 3 resource.\r\n//\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n#endif    // not APSTUDIO_INVOKED\r\n\r\n"
  },
  {
    "path": "meka/srcs/projects/msvc/Meka.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.26730.16\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Meka\", \"Meka.vcxproj\", \"{E4B91824-CCCF-4BA5-9CC1-52E75CDA8EE3}\"\r\nEndProject\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"smsid\", \"..\\..\\smsid\\smsid.vcxproj\", \"{3391017C-51A4-477A-9C31-BB5D68A07928}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Win32 = Debug|Win32\r\n\t\tRelease|Win32 = Release|Win32\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{E4B91824-CCCF-4BA5-9CC1-52E75CDA8EE3}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{E4B91824-CCCF-4BA5-9CC1-52E75CDA8EE3}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{E4B91824-CCCF-4BA5-9CC1-52E75CDA8EE3}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{E4B91824-CCCF-4BA5-9CC1-52E75CDA8EE3}.Release|Win32.Build.0 = Release|Win32\r\n\t\t{3391017C-51A4-477A-9C31-BB5D68A07928}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{3391017C-51A4-477A-9C31-BB5D68A07928}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{3391017C-51A4-477A-9C31-BB5D68A07928}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{3391017C-51A4-477A-9C31-BB5D68A07928}.Release|Win32.Build.0 = Release|Win32\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "meka/srcs/projects/msvc/Meka.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"packages\\nasm2.2.13.3.1\\build\\native\\nasm.props\" Condition=\"Exists('packages\\nasm2.2.13.3.1\\build\\native\\nasm.props')\" />\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{E4B91824-CCCF-4BA5-9CC1-52E75CDA8EE3}</ProjectGuid>\r\n    <RootNamespace>Meka</RootNamespace>\r\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <UseOfMfc>false</UseOfMfc>\r\n    <UseOfAtl>false</UseOfAtl>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <UseOfMfc>false</UseOfMfc>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n    <Import Project=\"$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n    <Import Project=\"$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup>\r\n    <_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <OutDir>..\\..\\..\\objs\\meka\\$(Configuration)\\</OutDir>\r\n    <IntDir>..\\..\\..\\objs\\meka\\$(Configuration)\\</IntDir>\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <TargetName>mekaw</TargetName>\r\n    <CustomBuildAfterTargets>Link</CustomBuildAfterTargets>\r\n    <Allegro_LibraryType>StaticMonolithRelease</Allegro_LibraryType>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <OutDir>..\\..\\..\\objs\\meka\\$(Configuration)\\</OutDir>\r\n    <IntDir>..\\..\\..\\objs\\meka\\$(Configuration)\\</IntDir>\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <TargetName>mekaw</TargetName>\r\n    <CustomBuildAfterTargets>Link</CustomBuildAfterTargets>\r\n    <Allegro_LibraryType>StaticMonolithRelease</Allegro_LibraryType>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <Midl>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MkTypLibCompatible>true</MkTypLibCompatible>\r\n      <SuppressStartupBanner>true</SuppressStartupBanner>\r\n      <TargetEnvironment>Win32</TargetEnvironment>\r\n      <TypeLibraryName>.\\Debug/Meka.tlb</TypeLibraryName>\r\n    </Midl>\r\n    <ClCompile>\r\n      <Optimization>Disabled</Optimization>\r\n      <AdditionalIncludeDirectories>../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>_DEBUG;DEBUGMODE;_WINDOWS;X86_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <StringPooling>false</StringPooling>\r\n      <MinimalRebuild>false</MinimalRebuild>\r\n      <ExceptionHandling />\r\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <PrecompiledHeaderFile>shared.h</PrecompiledHeaderFile>\r\n      <PrecompiledHeaderOutputFile>$(IntDir)shared.pch</PrecompiledHeaderOutputFile>\r\n      <AssemblerListingLocation>./$(IntDir)</AssemblerListingLocation>\r\n      <ObjectFileName>./$(IntDir)</ObjectFileName>\r\n      <ProgramDataBaseFileName>./$(IntDir)</ProgramDataBaseFileName>\r\n      <BrowseInformation>true</BrowseInformation>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <SuppressStartupBanner>true</SuppressStartupBanner>\r\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r\n      <CompileAs>CompileAsCpp</CompileAs>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <ResourceCompile>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <Culture>0x0000</Culture>\r\n    </ResourceCompile>\r\n    <Link>\r\n      <AdditionalOptions>/MACHINE:I386 /IGNORE:4204,4099 </AdditionalOptions>\r\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\r\n      <Version />\r\n      <AdditionalLibraryDirectories>$(DXSDK_DIR)/lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <IgnoreSpecificDefaultLibraries>libcmt; msvcrt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <ProgramDatabaseFile>$(IntDir)mekaw.pdb</ProgramDatabaseFile>\r\n      <GenerateMapFile>false</GenerateMapFile>\r\n      <MapFileName />\r\n      <MapExports>false</MapExports>\r\n      <SubSystem>Windows</SubSystem>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention />\r\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\r\n    </Link>\r\n    <CustomBuildStep>\r\n      <Command>copy /Y $(OutDir)$(TargetName)$(TargetExt) ..\\..\\..</Command>\r\n      <Outputs>..\\.\\..\\mekaw.exe</Outputs>\r\n    </CustomBuildStep>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <Midl>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MkTypLibCompatible>true</MkTypLibCompatible>\r\n      <SuppressStartupBanner>true</SuppressStartupBanner>\r\n      <TargetEnvironment>Win32</TargetEnvironment>\r\n      <TypeLibraryName>.\\Release/Meka.tlb</TypeLibraryName>\r\n    </Midl>\r\n    <ClCompile>\r\n      <Optimization>Full</Optimization>\r\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r\n      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r\n      <OmitFramePointers>true</OmitFramePointers>\r\n      <AdditionalIncludeDirectories>../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>NDEBUG;_WINDOWS;X86_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <StringPooling>true</StringPooling>\r\n      <MinimalRebuild>false</MinimalRebuild>\r\n      <ExceptionHandling />\r\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <PrecompiledHeaderFile>shared.h</PrecompiledHeaderFile>\r\n      <PrecompiledHeaderOutputFile>$(IntDir)shared.pch</PrecompiledHeaderOutputFile>\r\n      <AssemblerListingLocation>./$(IntDir)</AssemblerListingLocation>\r\n      <ObjectFileName>./$(IntDir)</ObjectFileName>\r\n      <ProgramDataBaseFileName>./$(IntDir)</ProgramDataBaseFileName>\r\n      <BrowseInformation>true</BrowseInformation>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <SuppressStartupBanner>true</SuppressStartupBanner>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <CompileAs>CompileAsCpp</CompileAs>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <ResourceCompile>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <Culture>0x0000</Culture>\r\n    </ResourceCompile>\r\n    <Link>\r\n      <AdditionalOptions>/MACHINE:I386 /IGNORE:4204,4099 </AdditionalOptions>\r\n      <ShowProgress>NotSet</ShowProgress>\r\n      <Version />\r\n      <AdditionalLibraryDirectories>$(DXSDK_DIR)/lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <ModuleDefinitionFile />\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <ProgramDatabaseFile>$(IntDir)mekaw.pdb</ProgramDatabaseFile>\r\n      <GenerateMapFile>false</GenerateMapFile>\r\n      <MapFileName />\r\n      <MapExports>false</MapExports>\r\n      <SubSystem>Windows</SubSystem>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <DataExecutionPrevention />\r\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\r\n    </Link>\r\n    <CustomBuildStep>\r\n      <Command>copy /Y $(OutDir)$(TargetName)$(TargetExt) ..\\..\\..</Command>\r\n      <Outputs>..\\.\\..\\mekaw.exe</Outputs>\r\n    </CustomBuildStep>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <Text Include=\"..\\..\\..\\changes.txt\" />\r\n    <Text Include=\"..\\..\\..\\compat.txt\" />\r\n    <Text Include=\"..\\..\\..\\debugger.txt\" />\r\n    <Text Include=\"..\\..\\..\\history.txt\" />\r\n    <Text Include=\"..\\..\\..\\meka.txt\" />\r\n    <Text Include=\"..\\..\\..\\multi.txt\" />\r\n    <Text Include=\"..\\..\\..\\sources.txt\" />\r\n    <Text Include=\"..\\..\\..\\tech.txt\" />\r\n    <Text Include=\"..\\..\\..\\todo.txt\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"..\\..\\..\\meka.blt\" />\r\n    <None Include=\"..\\..\\..\\meka.dsk\" />\r\n    <None Include=\"..\\..\\..\\meka.fdb\" />\r\n    <None Include=\"..\\..\\..\\meka.inp\" />\r\n    <None Include=\"..\\..\\..\\meka.msg\" />\r\n    <None Include=\"..\\..\\..\\meka.nam\" />\r\n    <None Include=\"..\\..\\..\\meka.pat\" />\r\n    <None Include=\"..\\..\\..\\meka.thm\" />\r\n    <None Include=\"..\\..\\..\\mekaw.cfg\" />\r\n    <NASM Include=\"..\\..\\hq2x16.asm\">\r\n      <GenerateDebugInformation Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</GenerateDebugInformation>\r\n      <GenerateDebugInformation Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</GenerateDebugInformation>\r\n      <AdditionalOptions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">-w-orphan-labels %(AdditionalOptions)</AdditionalOptions>\r\n      <AdditionalOptions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">-w-orphan-labels %(AdditionalOptions)</AdditionalOptions>\r\n    </NASM>\r\n    <NASM Include=\"..\\..\\hq2x32.asm\">\r\n      <GenerateDebugInformation Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</GenerateDebugInformation>\r\n      <GenerateDebugInformation Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</GenerateDebugInformation>\r\n      <AdditionalOptions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">-w-orphan-labels %(AdditionalOptions)</AdditionalOptions>\r\n      <AdditionalOptions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">-w-orphan-labels %(AdditionalOptions)</AdditionalOptions>\r\n    </NASM>\r\n    <None Include=\"..\\..\\Makefile\" />\r\n    <None Include=\"packages.config\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"..\\..\\allegro4to5.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_about.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_cheatfinder.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_filebrowser.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_game.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_mapview.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_memview.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_options.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_palview.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_techinfo.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_textview.cpp\" />\r\n    <ClCompile Include=\"..\\..\\app_tileview.cpp\" />\r\n    <ClCompile Include=\"..\\..\\areplay.cpp\" />\r\n    <ClCompile Include=\"..\\..\\beam.cpp\" />\r\n    <ClCompile Include=\"..\\..\\bios.cpp\" />\r\n    <ClCompile Include=\"..\\..\\blit.cpp\" />\r\n    <ClCompile Include=\"..\\..\\blitintf.cpp\" />\r\n    <ClCompile Include=\"..\\..\\blit_c.cpp\" />\r\n    <ClCompile Include=\"..\\..\\bmemory.cpp\" />\r\n    <ClCompile Include=\"..\\..\\build.cpp\" />\r\n    <ClCompile Include=\"..\\..\\capture.cpp\" />\r\n    <ClCompile Include=\"..\\..\\checksum.cpp\" />\r\n    <ClCompile Include=\"..\\..\\coleco.cpp\" />\r\n    <ClCompile Include=\"..\\..\\commport.cpp\" />\r\n    <ClCompile Include=\"..\\..\\config.cpp\" />\r\n    <ClCompile Include=\"..\\..\\country.cpp\" />\r\n    <ClCompile Include=\"..\\..\\cpu.cpp\" />\r\n    <ClCompile Include=\"..\\..\\data.cpp\" />\r\n    <ClCompile Include=\"..\\..\\datadump.cpp\" />\r\n    <ClCompile Include=\"..\\..\\db.cpp\" />\r\n    <ClCompile Include=\"..\\..\\debugger.cpp\" />\r\n    <ClCompile Include=\"..\\..\\desktop.cpp\" />\r\n    <ClCompile Include=\"..\\..\\drivers.cpp\" />\r\n    <ClCompile Include=\"..\\..\\eeprom.cpp\" />\r\n    <ClCompile Include=\"..\\..\\effects.cpp\" />\r\n    <ClCompile Include=\"..\\..\\errors.cpp\" />\r\n    <ClCompile Include=\"..\\..\\fdc765.cpp\" />\r\n    <ClCompile Include=\"..\\..\\file.cpp\" />\r\n    <ClCompile Include=\"..\\..\\fonts.cpp\" />\r\n    <ClCompile Include=\"..\\..\\fskipper.cpp\" />\r\n    <ClCompile Include=\"..\\..\\glasses.cpp\" />\r\n    <ClCompile Include=\"..\\..\\gui.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_action.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_box.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_init.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_menu.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_menu_i.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_menu_t.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_mouse.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_tools.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_update.cpp\" />\r\n    <ClCompile Include=\"..\\..\\g_widget.cpp\" />\r\n    <ClCompile Include=\"..\\..\\hq2x.cpp\" />\r\n    <ClCompile Include=\"..\\..\\inputs.cpp\" />\r\n    <ClCompile Include=\"..\\..\\inputs_c.cpp\" />\r\n    <ClCompile Include=\"..\\..\\inputs_f.cpp\" />\r\n    <ClCompile Include=\"..\\..\\inputs_i.cpp\" />\r\n    <ClCompile Include=\"..\\..\\inputs_t.cpp\" />\r\n    <ClCompile Include=\"..\\..\\inputs_u.cpp\" />\r\n    <ClCompile Include=\"..\\..\\ioports.cpp\" />\r\n    <ClCompile Include=\"..\\..\\keyinfo.cpp\" />\r\n    <ClCompile Include=\"..\\..\\libmisc.cpp\" />\r\n    <ClCompile Include=\"..\\..\\libparse.cpp\" />\r\n    <ClCompile Include=\"..\\..\\lightgun.cpp\" />\r\n    <ClCompile Include=\"..\\..\\machine.cpp\" />\r\n    <ClCompile Include=\"..\\..\\mainloop.cpp\" />\r\n    <ClCompile Include=\"..\\..\\mappers.cpp\" />\r\n    <ClCompile Include=\"..\\..\\meka.cpp\" />\r\n    <ClCompile Include=\"..\\..\\message.cpp\" />\r\n    <ClCompile Include=\"..\\..\\misc.cpp\" />\r\n    <ClCompile Include=\"..\\..\\palette.cpp\" />\r\n    <ClCompile Include=\"..\\..\\patch.cpp\" />\r\n    <ClCompile Include=\"..\\..\\periph.cpp\" />\r\n    <ClCompile Include=\"..\\..\\rapidfir.cpp\" />\r\n    <ClCompile Include=\"..\\..\\saves.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sdsc.cpp\" />\r\n    <ClCompile Include=\"..\\..\\setup.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sf7000.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sg1ksc3k.cpp\" />\r\n    <ClCompile Include=\"..\\..\\shared.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sk1100.cpp\" />\r\n    <ClCompile Include=\"..\\..\\skin.cpp\" />\r\n    <ClCompile Include=\"..\\..\\skin_bg.cpp\" />\r\n    <ClCompile Include=\"..\\..\\skin_fx.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\emu2413\\emu2413.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\emu2413\\mekaintf.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\fmeditor.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\fmunit.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\psg.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\sound.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\sound_logging.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\s_misc.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\vgm.cpp\" />\r\n    <ClCompile Include=\"..\\..\\sound\\wav.cpp\" />\r\n    <ClCompile Include=\"..\\..\\textbox.cpp\" />\r\n    <ClCompile Include=\"..\\..\\tools.cpp\" />\r\n    <ClCompile Include=\"..\\..\\tvoekaki.cpp\" />\r\n    <ClCompile Include=\"..\\..\\tvtype.cpp\" />\r\n    <ClCompile Include=\"..\\..\\unzip.cpp\" />\r\n    <ClCompile Include=\"..\\..\\vdp.cpp\" />\r\n    <ClCompile Include=\"..\\..\\video.cpp\" />\r\n    <ClCompile Include=\"..\\..\\video_c.cpp\" />\r\n    <ClCompile Include=\"..\\..\\video_m2.cpp\" />\r\n    <ClCompile Include=\"..\\..\\video_m5.cpp\" />\r\n    <ClCompile Include=\"..\\..\\vlfn.cpp\" />\r\n    <ClCompile Include=\"..\\..\\vmachine.cpp\" />\r\n    <ClCompile Include=\"..\\..\\z80marat\\Debug.cpp\" />\r\n    <ClCompile Include=\"..\\..\\z80marat\\Z80.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n      </PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n      </PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\z80marat\\Z80Call.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n      </PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n      </PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\z80marat\\Z80DebugHelpers.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\..\\allegro4to5.h\" />\r\n    <ClInclude Include=\"..\\..\\app_about.h\" />\r\n    <ClInclude Include=\"..\\..\\app_cheatfinder.h\" />\r\n    <ClInclude Include=\"..\\..\\app_filebrowser.h\" />\r\n    <ClInclude Include=\"..\\..\\app_game.h\" />\r\n    <ClInclude Include=\"..\\..\\app_mapview.h\" />\r\n    <ClInclude Include=\"..\\..\\app_memview.h\" />\r\n    <ClInclude Include=\"..\\..\\app_options.h\" />\r\n    <ClInclude Include=\"..\\..\\app_palview.h\" />\r\n    <ClInclude Include=\"..\\..\\app_techinfo.h\" />\r\n    <ClInclude Include=\"..\\..\\app_textview.h\" />\r\n    <ClInclude Include=\"..\\..\\app_tileview.h\" />\r\n    <ClInclude Include=\"..\\..\\areplay.h\" />\r\n    <ClInclude Include=\"..\\..\\beam.h\" />\r\n    <ClInclude Include=\"..\\..\\bios.h\" />\r\n    <ClInclude Include=\"..\\..\\blit.h\" />\r\n    <ClInclude Include=\"..\\..\\blitintf.h\" />\r\n    <ClInclude Include=\"..\\..\\blit_c.h\" />\r\n    <ClInclude Include=\"..\\..\\bmemory.h\" />\r\n    <ClInclude Include=\"..\\..\\capture.h\" />\r\n    <ClInclude Include=\"..\\..\\checksum.h\" />\r\n    <ClInclude Include=\"..\\..\\coleco.h\" />\r\n    <ClInclude Include=\"..\\..\\commport.h\" />\r\n    <ClInclude Include=\"..\\..\\config.h\" />\r\n    <ClInclude Include=\"..\\..\\country.h\" />\r\n    <ClInclude Include=\"..\\..\\cpu.h\" />\r\n    <ClInclude Include=\"..\\..\\data.h\" />\r\n    <ClInclude Include=\"..\\..\\datadump.h\" />\r\n    <ClInclude Include=\"..\\..\\db.h\" />\r\n    <ClInclude Include=\"..\\..\\debugger.h\" />\r\n    <ClInclude Include=\"..\\..\\desktop.h\" />\r\n    <ClInclude Include=\"..\\..\\drivers.h\" />\r\n    <ClInclude Include=\"..\\..\\eeprom.h\" />\r\n    <ClInclude Include=\"..\\..\\effects.h\" />\r\n    <ClInclude Include=\"..\\..\\errors.h\" />\r\n    <ClInclude Include=\"..\\..\\fdc765.h\" />\r\n    <ClInclude Include=\"..\\..\\file.h\" />\r\n    <ClInclude Include=\"..\\..\\fonts.h\" />\r\n    <ClInclude Include=\"..\\..\\fskipper.h\" />\r\n    <ClInclude Include=\"..\\..\\glasses.h\" />\r\n    <ClInclude Include=\"..\\..\\grab.h\" />\r\n    <ClInclude Include=\"..\\..\\gui.h\" />\r\n    <ClInclude Include=\"..\\..\\g_action.h\" />\r\n    <ClInclude Include=\"..\\..\\g_box.h\" />\r\n    <ClInclude Include=\"..\\..\\g_init.h\" />\r\n    <ClInclude Include=\"..\\..\\g_menu.h\" />\r\n    <ClInclude Include=\"..\\..\\g_menu_i.h\" />\r\n    <ClInclude Include=\"..\\..\\g_menu_t.h\" />\r\n    <ClInclude Include=\"..\\..\\g_mouse.h\" />\r\n    <ClInclude Include=\"..\\..\\g_tools.h\" />\r\n    <ClInclude Include=\"..\\..\\g_update.h\" />\r\n    <ClInclude Include=\"..\\..\\g_widget.h\" />\r\n    <ClInclude Include=\"..\\..\\hq2x.h\" />\r\n    <ClInclude Include=\"..\\..\\inputs.h\" />\r\n    <ClInclude Include=\"..\\..\\inputs_c.h\" />\r\n    <ClInclude Include=\"..\\..\\inputs_f.h\" />\r\n    <ClInclude Include=\"..\\..\\inputs_i.h\" />\r\n    <ClInclude Include=\"..\\..\\inputs_t.h\" />\r\n    <ClInclude Include=\"..\\..\\inputs_u.h\" />\r\n    <ClInclude Include=\"..\\..\\ioports.h\" />\r\n    <ClInclude Include=\"..\\..\\keyinfo.h\" />\r\n    <ClInclude Include=\"..\\..\\libmisc.h\" />\r\n    <ClInclude Include=\"..\\..\\libparse.h\" />\r\n    <ClInclude Include=\"..\\..\\lightgun.h\" />\r\n    <ClInclude Include=\"..\\..\\machine.h\" />\r\n    <ClInclude Include=\"..\\..\\mainloop.h\" />\r\n    <ClInclude Include=\"..\\..\\mappers.h\" />\r\n    <ClInclude Include=\"..\\..\\meka.h\" />\r\n    <ClInclude Include=\"..\\..\\message.h\" />\r\n    <ClInclude Include=\"..\\..\\misc.h\" />\r\n    <ClInclude Include=\"..\\..\\palette.h\" />\r\n    <ClInclude Include=\"..\\..\\patch.h\" />\r\n    <ClInclude Include=\"..\\..\\periph.h\" />\r\n    <ClInclude Include=\"..\\..\\rapidfir.h\" />\r\n    <ClInclude Include=\"..\\..\\saves.h\" />\r\n    <ClInclude Include=\"..\\..\\sdsc.h\" />\r\n    <ClInclude Include=\"..\\..\\setup.h\" />\r\n    <ClInclude Include=\"..\\..\\sf7000.h\" />\r\n    <ClInclude Include=\"..\\..\\sg1ksc3k.h\" />\r\n    <ClInclude Include=\"..\\..\\shared.h\" />\r\n    <ClInclude Include=\"..\\..\\sk1100.h\" />\r\n    <ClInclude Include=\"..\\..\\skin.h\" />\r\n    <ClInclude Include=\"..\\..\\skin_bg.h\" />\r\n    <ClInclude Include=\"..\\..\\skin_fx.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\emu2413\\emu2413.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\emu2413\\mekaintf.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\fmeditor.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\fmunit.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\psg.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\sound.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\sound_logging.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\s_misc.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\vgm.h\" />\r\n    <ClInclude Include=\"..\\..\\sound\\wav.h\" />\r\n    <ClInclude Include=\"..\\..\\system.h\" />\r\n    <ClInclude Include=\"..\\..\\textbox.h\" />\r\n    <ClInclude Include=\"..\\..\\tools.h\" />\r\n    <ClInclude Include=\"..\\..\\tvoekaki.h\" />\r\n    <ClInclude Include=\"..\\..\\tvtype.h\" />\r\n    <ClInclude Include=\"..\\..\\unzip.h\" />\r\n    <ClInclude Include=\"..\\..\\vdp.h\" />\r\n    <ClInclude Include=\"..\\..\\video.h\" />\r\n    <ClInclude Include=\"..\\..\\video_c.h\" />\r\n    <ClInclude Include=\"..\\..\\video_m2.h\" />\r\n    <ClInclude Include=\"..\\..\\video_m5.h\" />\r\n    <ClInclude Include=\"..\\..\\vlfn.h\" />\r\n    <ClInclude Include=\"..\\..\\vmachine.h\" />\r\n    <ClInclude Include=\"..\\..\\vmachpal.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\Codes.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesCB.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesED.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesXCB.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesXX.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\Tables.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\Z80.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\Z80DebugHelpers.h\" />\r\n    <ClInclude Include=\"..\\..\\z80marat\\Z80OpcodeEnums.h\" />\r\n    <ClInclude Include=\"resource.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"Meka.rc\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"mekaw.ico\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Manifest Include=\"meka.manifest\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n    <Import Project=\"packages\\nasm2.2.13.3.1\\build\\native\\nasm.targets\" Condition=\"Exists('packages\\nasm2.2.13.3.1\\build\\native\\nasm.targets')\" />\r\n    <Import Project=\"packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets\" Condition=\"Exists('packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets')\" />\r\n    <Import Project=\"packages\\Allegro.5.2.10\\build\\native\\Allegro.targets\" Condition=\"Exists('packages\\Allegro.5.2.10\\build\\native\\Allegro.targets')\" />\r\n  </ImportGroup>\r\n  <Target Name=\"EnsureNuGetPackageBuildImports\" BeforeTargets=\"PrepareForBuild\">\r\n    <PropertyGroup>\r\n      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>\r\n    </PropertyGroup>\r\n    <Error Condition=\"!Exists('packages\\nasm2.2.13.3.1\\build\\native\\nasm.props')\" Text=\"$([System.String]::Format('$(ErrorText)', 'packages\\nasm2.2.13.3.1\\build\\native\\nasm.props'))\" />\r\n    <Error Condition=\"!Exists('packages\\nasm2.2.13.3.1\\build\\native\\nasm.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', 'packages\\nasm2.2.13.3.1\\build\\native\\nasm.targets'))\" />\r\n    <Error Condition=\"!Exists('packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', 'packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets'))\" />\r\n    <Error Condition=\"!Exists('packages\\Allegro.5.2.10\\build\\native\\Allegro.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', 'packages\\Allegro.5.2.10\\build\\native\\Allegro.targets'))\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "meka/srcs/projects/msvc/Meka.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Docs\">\r\n      <UniqueIdentifier>{4f66665f-f566-4046-a869-cf42d62c5f0d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Data\">\r\n      <UniqueIdentifier>{1add6800-429b-4faa-8637-6842e2a5ca82}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\">\r\n      <UniqueIdentifier>{77da84d4-7adb-42ce-94e3-752f4797ee2d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Sound\">\r\n      <UniqueIdentifier>{73ce6f69-b4b2-4eb3-ae6f-6b3486b253ad}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Sound\\PSG\">\r\n      <UniqueIdentifier>{85fd0f3b-e518-4f0b-a178-df43d15a8c25}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Sound\\Emu2413\">\r\n      <UniqueIdentifier>{87edded6-23c2-452a-9ca2-0f6e8558d8f3}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\CPU\">\r\n      <UniqueIdentifier>{c3bbca8b-9b5b-47b4-87e5-e9dfca36a374}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\CPU\\Z80marat\">\r\n      <UniqueIdentifier>{6c6d1c5d-9dcb-4df8-b498-68c9957be26b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\GUI\">\r\n      <UniqueIdentifier>{c9c85590-abd2-4b12-8309-a43323d56f60}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Video\">\r\n      <UniqueIdentifier>{a1be508c-b7b3-4c6c-863e-934a317d32f9}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Video\\HQ2X\">\r\n      <UniqueIdentifier>{6bb1ab42-f8c0-4955-bba1-57d9bd33dad2}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Peripherals\">\r\n      <UniqueIdentifier>{74ead6c4-d1d6-48d6-b0d6-8faddff689fc}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Machines\">\r\n      <UniqueIdentifier>{0c026409-962a-4e36-8d33-bb9961ac3127}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Applets\">\r\n      <UniqueIdentifier>{0d08e4c3-9e73-46e3-9fd8-5424635e9a29}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Srcs\\Debugger\">\r\n      <UniqueIdentifier>{e86793e4-c4d1-42b4-98c9-74948df96535}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Resources\">\r\n      <UniqueIdentifier>{a733b7ed-c60b-481a-b5d2-841729f0bd9f}</UniqueIdentifier>\r\n      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Text Include=\"..\\..\\..\\changes.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\compat.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\debugger.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\history.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\meka.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\multi.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\sources.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\tech.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n    <Text Include=\"..\\..\\..\\todo.txt\">\r\n      <Filter>Docs</Filter>\r\n    </Text>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"..\\..\\..\\meka.blt\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.dsk\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.fdb\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.inp\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.msg\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.nam\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.pat\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\meka.thm\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\..\\mekaw.cfg\">\r\n      <Filter>Data</Filter>\r\n    </None>\r\n    <None Include=\"..\\..\\Makefile\">\r\n      <Filter>Srcs</Filter>\r\n    </None>\r\n    <None Include=\"packages.config\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"..\\..\\allegro4to5.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\bmemory.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\build.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\capture.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\checksum.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\commport.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\config.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\country.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\cpu.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\data.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\db.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\eeprom.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\effects.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\errors.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\fdc765.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\file.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\fonts.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\fskipper.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\inputs.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\inputs_c.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\inputs_f.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\inputs_i.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\inputs_t.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\inputs_u.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\libmisc.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\libparse.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\mainloop.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\mappers.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\meka.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\message.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\misc.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\patch.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\saves.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sdsc.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\setup.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\shared.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\tools.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\tvtype.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\unzip.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\vlfn.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\vmachine.cpp\">\r\n      <Filter>Srcs</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\fmeditor.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\fmunit.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\s_misc.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\sound.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\sound_logging.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\vgm.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\wav.cpp\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\psg.cpp\">\r\n      <Filter>Srcs\\Sound\\PSG</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\emu2413\\emu2413.cpp\">\r\n      <Filter>Srcs\\Sound\\Emu2413</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sound\\emu2413\\mekaintf.cpp\">\r\n      <Filter>Srcs\\Sound\\Emu2413</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\z80marat\\Debug.cpp\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\z80marat\\Z80.cpp\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\z80marat\\Z80Call.cpp\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\z80marat\\Z80DebugHelpers.cpp\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\desktop.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_action.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_box.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_init.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_menu.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_menu_i.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_menu_t.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_mouse.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_tools.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_update.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\g_widget.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\gui.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\skin.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\skin_bg.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\skin_fx.cpp\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\beam.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\blit.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\blit_c.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\blitintf.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\palette.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\vdp.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\video.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\video_c.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\video_m2.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\video_m5.cpp\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\hq2x.cpp\">\r\n      <Filter>Srcs\\Video\\HQ2X</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\areplay.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\glasses.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\keyinfo.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\lightgun.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\periph.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\rapidfir.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sk1100.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\tvoekaki.cpp\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\bios.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\coleco.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\drivers.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\ioports.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\machine.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sf7000.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\sg1ksc3k.cpp\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_about.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_cheatfinder.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_filebrowser.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_game.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_mapview.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_memview.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_options.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_palview.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_techinfo.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_textview.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\app_tileview.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\textbox.cpp\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\datadump.cpp\">\r\n      <Filter>Srcs\\Debugger</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\..\\debugger.cpp\">\r\n      <Filter>Srcs\\Debugger</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\..\\allegro4to5.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\bmemory.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\capture.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\checksum.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\commport.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\config.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\country.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\cpu.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\data.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\db.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\eeprom.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\effects.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\errors.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\fdc765.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\file.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\fonts.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\fskipper.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\grab.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\inputs.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\inputs_c.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\inputs_f.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\inputs_i.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\inputs_t.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\inputs_u.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\libmisc.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\libparse.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\mainloop.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\mappers.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\meka.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\message.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\misc.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\patch.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"resource.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\saves.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sdsc.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\setup.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\shared.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\system.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\tools.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\tvtype.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\unzip.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\vlfn.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\vmachine.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\vmachpal.h\">\r\n      <Filter>Srcs</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\fmeditor.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\fmunit.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\s_misc.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\sound.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\sound_logging.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\vgm.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\wav.h\">\r\n      <Filter>Srcs\\Sound</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\psg.h\">\r\n      <Filter>Srcs\\Sound\\PSG</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\emu2413\\emu2413.h\">\r\n      <Filter>Srcs\\Sound\\Emu2413</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sound\\emu2413\\mekaintf.h\">\r\n      <Filter>Srcs\\Sound\\Emu2413</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\Codes.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesCB.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesED.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesXCB.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\CodesXX.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\Tables.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\Z80.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\Z80DebugHelpers.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\z80marat\\Z80OpcodeEnums.h\">\r\n      <Filter>Srcs\\CPU\\Z80marat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\desktop.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_action.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_box.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_init.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_menu.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_menu_i.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_menu_t.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_mouse.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_tools.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_update.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\g_widget.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\gui.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\skin.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\skin_bg.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\skin_fx.h\">\r\n      <Filter>Srcs\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\beam.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\blit.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\blit_c.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\blitintf.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\palette.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\vdp.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\video.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\video_c.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\video_m2.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\video_m5.h\">\r\n      <Filter>Srcs\\Video</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\hq2x.h\">\r\n      <Filter>Srcs\\Video\\HQ2X</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\areplay.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\glasses.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\keyinfo.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\lightgun.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\periph.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\rapidfir.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sk1100.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\tvoekaki.h\">\r\n      <Filter>Srcs\\Peripherals</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\bios.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\coleco.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\drivers.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\ioports.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\machine.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sf7000.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\sg1ksc3k.h\">\r\n      <Filter>Srcs\\Machines</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_about.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_cheatfinder.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_filebrowser.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_game.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_mapview.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_memview.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_options.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_palview.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_techinfo.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_textview.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\app_tileview.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\textbox.h\">\r\n      <Filter>Srcs\\Applets</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\datadump.h\">\r\n      <Filter>Srcs\\Debugger</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\..\\debugger.h\">\r\n      <Filter>Srcs\\Debugger</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"Meka.rc\">\r\n      <Filter>Resources</Filter>\r\n    </ResourceCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"mekaw.ico\">\r\n      <Filter>Resources</Filter>\r\n    </Image>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <NASM Include=\"..\\..\\hq2x32.asm\">\r\n      <Filter>Srcs\\Video\\HQ2X</Filter>\r\n    </NASM>\r\n    <NASM Include=\"..\\..\\hq2x16.asm\">\r\n      <Filter>Srcs\\Video\\HQ2X</Filter>\r\n    </NASM>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Manifest Include=\"meka.manifest\">\r\n      <Filter>Resources</Filter>\r\n    </Manifest>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "meka/srcs/projects/msvc/meka.manifest",
    "content": "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\" >\n <asmv3:application>\n <asmv3:windowsSettings xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">\n <dpiAware>false</dpiAware>\n </asmv3:windowsSettings>\n </asmv3:application>\n </assembly>"
  },
  {
    "path": "meka/srcs/projects/msvc/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<packages>\r\n  <package id=\"Allegro\" version=\"5.2.10\" targetFramework=\"native\" />\r\n  <package id=\"AllegroDeps\" version=\"1.15.0\" targetFramework=\"native\" />\r\n  <package id=\"nasm2\" version=\"2.13.3.1\" targetFramework=\"native\" />\r\n</packages>"
  },
  {
    "path": "meka/srcs/projects/msvc/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\r\n// Microsoft Visual C++ generated include file.\r\n// Used by Meka.rc\r\n//\r\n#define IDD_SETUP                       9\r\n#define IDD_CONSOLE                     101\r\n#define IDC_CONSOLE_TEXT                1001\r\n#define IDC_CONSOLE_CLEAR               1002\r\n#define IDC_CONSOLE_COPY                1003\r\n#define IDC_CONSOLE_QUIT                1004\r\n#define IDC_SETUP_SOUNDCARDS            1005\r\n#define IDC_CONSOLE_RUN                 1006\r\n#define IDC_CONSOLE_MEKA_VERSION        1007\r\n#define IDC_CONSOLE_INFO                1007\r\n#define IDC_SETUP_SOUND_SAMPLERATE_TEXT 1008\r\n#define IDC_SETUP_SOUND_SAMPLERATE      1009\r\n#define IDC_CHECK1                      1010\r\n#define IDC_SETUP_LANGUAGE              1011\r\n#define IDC_SETUP_VIDEO_DISPLAY_MODE    1012\r\n#define IDC_SETUP_RESOLUTION_TEXT       1013\r\n#define IDC_SETUP_VIDEO_RESOLUTION_TEXT 1013\r\n#define IDC_SETUP_VIDEO_DRIVER_TEXT     1014\r\n#define IDC_SETUP_RESOLUTION2           1015\r\n#define IDC_SETUP_VIDEO_DRIVER          1015\r\n#define IDC_SETUP_VIDEO_NOTES           1016\r\n\r\n// Next default values for new objects\r\n// \r\n#ifdef APSTUDIO_INVOKED\r\n#ifndef APSTUDIO_READONLY_SYMBOLS\r\n#define _APS_NEXT_RESOURCE_VALUE        103\r\n#define _APS_NEXT_COMMAND_VALUE         40001\r\n#define _APS_NEXT_CONTROL_VALUE         1011\r\n#define _APS_NEXT_SYMED_VALUE           101\r\n#endif\r\n#endif\r\n"
  },
  {
    "path": "meka/srcs/projects/xcode/meka/meka.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXFileReference section */\n\t\t075097E215EB793400B04454 /* app_cheatfinder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_cheatfinder.cpp; sourceTree = \"<group>\"; };\n\t\t075097E315EB793400B04454 /* app_cheatfinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_cheatfinder.h; sourceTree = \"<group>\"; };\n\t\t07D7B3B9141D59EC00B5EB2A /* allegro4to5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = allegro4to5.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3BA141D59EC00B5EB2A /* allegro4to5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = allegro4to5.h; sourceTree = \"<group>\"; };\n\t\t07D7B3BB141D59EC00B5EB2A /* app_about.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_about.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3BC141D59EC00B5EB2A /* app_about.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_about.h; sourceTree = \"<group>\"; };\n\t\t07D7B3BD141D59EC00B5EB2A /* app_filebrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_filebrowser.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3BE141D59EC00B5EB2A /* app_filebrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_filebrowser.h; sourceTree = \"<group>\"; };\n\t\t07D7B3BF141D59EC00B5EB2A /* app_game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_game.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3C0141D59EC00B5EB2A /* app_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_game.h; sourceTree = \"<group>\"; };\n\t\t07D7B3C1141D59EC00B5EB2A /* app_mapview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_mapview.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3C2141D59EC00B5EB2A /* app_mapview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_mapview.h; sourceTree = \"<group>\"; };\n\t\t07D7B3C3141D59EC00B5EB2A /* app_memview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_memview.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3C4141D59EC00B5EB2A /* app_memview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_memview.h; sourceTree = \"<group>\"; };\n\t\t07D7B3C5141D59EC00B5EB2A /* app_options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_options.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3C6141D59EC00B5EB2A /* app_options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_options.h; sourceTree = \"<group>\"; };\n\t\t07D7B3C7141D59EC00B5EB2A /* app_palview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_palview.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3C8141D59EC00B5EB2A /* app_palview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_palview.h; sourceTree = \"<group>\"; };\n\t\t07D7B3C9141D59EC00B5EB2A /* app_techinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_techinfo.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3CA141D59EC00B5EB2A /* app_techinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_techinfo.h; sourceTree = \"<group>\"; };\n\t\t07D7B3CB141D59EC00B5EB2A /* app_textview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_textview.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3CC141D59EC00B5EB2A /* app_textview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_textview.h; sourceTree = \"<group>\"; };\n\t\t07D7B3CD141D59EC00B5EB2A /* app_tileview.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_tileview.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3CE141D59EC00B5EB2A /* app_tileview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = app_tileview.h; sourceTree = \"<group>\"; };\n\t\t07D7B3CF141D59EC00B5EB2A /* areplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = areplay.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3D0141D59EC00B5EB2A /* areplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = areplay.h; sourceTree = \"<group>\"; };\n\t\t07D7B3D1141D59EC00B5EB2A /* beam.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = beam.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3D2141D59EC00B5EB2A /* beam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = beam.h; sourceTree = \"<group>\"; };\n\t\t07D7B3D3141D59EC00B5EB2A /* bios.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bios.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3D4141D59EC00B5EB2A /* bios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = bios.h; sourceTree = \"<group>\"; };\n\t\t07D7B3D5141D59EC00B5EB2A /* blit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blit.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3D6141D59EC00B5EB2A /* blit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = blit.h; sourceTree = \"<group>\"; };\n\t\t07D7B3D7141D59EC00B5EB2A /* blit_c.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blit_c.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3D8141D59EC00B5EB2A /* blit_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = blit_c.h; sourceTree = \"<group>\"; };\n\t\t07D7B3D9141D59EC00B5EB2A /* blitintf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blitintf.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3DA141D59EC00B5EB2A /* blitintf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = blitintf.h; sourceTree = \"<group>\"; };\n\t\t07D7B3DB141D59EC00B5EB2A /* bmemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bmemory.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3DC141D59EC00B5EB2A /* bmemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = bmemory.h; sourceTree = \"<group>\"; };\n\t\t07D7B3DD141D59EC00B5EB2A /* build.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = build.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3DE141D59EC00B5EB2A /* build.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = build.h; sourceTree = \"<group>\"; };\n\t\t07D7B3E0141D59EC00B5EB2A /* capture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = capture.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3E1141D59EC00B5EB2A /* capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = capture.h; sourceTree = \"<group>\"; };\n\t\t07D7B3E2141D59EC00B5EB2A /* checksum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = checksum.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3E3141D59EC00B5EB2A /* checksum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = checksum.h; sourceTree = \"<group>\"; };\n\t\t07D7B3E4141D59EC00B5EB2A /* coleco.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coleco.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3E5141D59EC00B5EB2A /* coleco.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = coleco.h; sourceTree = \"<group>\"; };\n\t\t07D7B3E6141D59EC00B5EB2A /* commport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commport.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3E7141D59EC00B5EB2A /* commport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = commport.h; sourceTree = \"<group>\"; };\n\t\t07D7B3E8141D59EC00B5EB2A /* config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3E9141D59EC00B5EB2A /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = config.h; sourceTree = \"<group>\"; };\n\t\t07D7B3EA141D59EC00B5EB2A /* country.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = country.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3EB141D59EC00B5EB2A /* country.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = country.h; sourceTree = \"<group>\"; };\n\t\t07D7B3EC141D59EC00B5EB2A /* cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpu.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3ED141D59EC00B5EB2A /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cpu.h; sourceTree = \"<group>\"; };\n\t\t07D7B3EE141D59EC00B5EB2A /* data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = data.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3EF141D59EC00B5EB2A /* data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = data.h; sourceTree = \"<group>\"; };\n\t\t07D7B3F0141D59EC00B5EB2A /* datadump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = datadump.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3F1141D59EC00B5EB2A /* datadump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = datadump.h; sourceTree = \"<group>\"; };\n\t\t07D7B3F2141D59EC00B5EB2A /* db.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = db.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3F3141D59EC00B5EB2A /* db.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = db.h; sourceTree = \"<group>\"; };\n\t\t07D7B3F4141D59EC00B5EB2A /* debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debugger.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3F5141D59EC00B5EB2A /* debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = debugger.h; sourceTree = \"<group>\"; };\n\t\t07D7B3F6141D59EC00B5EB2A /* desktop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = desktop.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3F7141D59EC00B5EB2A /* desktop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = desktop.h; sourceTree = \"<group>\"; };\n\t\t07D7B3F9141D59EC00B5EB2A /* blitter-notes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = \"blitter-notes.txt\"; sourceTree = \"<group>\"; };\n\t\t07D7B3FA141D59EC00B5EB2A /* db-notes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = \"db-notes.txt\"; sourceTree = \"<group>\"; };\n\t\t07D7B3FB141D59EC00B5EB2A /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = \"<group>\"; };\n\t\t07D7B3FD141D59EC00B5EB2A /* meka_save_state_007.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = meka_save_state_007.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3FE141D59EC00B5EB2A /* meka_save_state_00C.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = meka_save_state_00C.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B3FF141D59EC00B5EB2A /* sound-engine-2003-12.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = \"sound-engine-2003-12.txt\"; sourceTree = \"<group>\"; };\n\t\t07D7B400141D59EC00B5EB2A /* sound-engine-notes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = \"sound-engine-notes.txt\"; sourceTree = \"<group>\"; };\n\t\t07D7B401141D59EC00B5EB2A /* drivers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drivers.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B402141D59EC00B5EB2A /* drivers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drivers.h; sourceTree = \"<group>\"; };\n\t\t07D7B403141D59EC00B5EB2A /* eagle.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = eagle.asm; sourceTree = \"<group>\"; };\n\t\t07D7B404141D59EC00B5EB2A /* eagle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = eagle.h; sourceTree = \"<group>\"; };\n\t\t07D7B405141D59EC00B5EB2A /* eeprom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = eeprom.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B406141D59EC00B5EB2A /* eeprom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = eeprom.h; sourceTree = \"<group>\"; };\n\t\t07D7B407141D59EC00B5EB2A /* effects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = effects.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B408141D59EC00B5EB2A /* effects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = effects.h; sourceTree = \"<group>\"; };\n\t\t07D7B409141D59EC00B5EB2A /* errors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = errors.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B40A141D59EC00B5EB2A /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = errors.h; sourceTree = \"<group>\"; };\n\t\t07D7B40B141D59EC00B5EB2A /* fdc765.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fdc765.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B40C141D59EC00B5EB2A /* fdc765.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = fdc765.h; sourceTree = \"<group>\"; };\n\t\t07D7B40D141D59EC00B5EB2A /* file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B40E141D59EC00B5EB2A /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = file.h; sourceTree = \"<group>\"; };\n\t\t07D7B40F141D59EC00B5EB2A /* fonts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fonts.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B410141D59EC00B5EB2A /* fonts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = fonts.h; sourceTree = \"<group>\"; };\n\t\t07D7B411141D59EC00B5EB2A /* fskipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fskipper.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B412141D59EC00B5EB2A /* fskipper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = fskipper.h; sourceTree = \"<group>\"; };\n\t\t07D7B413141D59EC00B5EB2A /* g_action.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_action.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B414141D59EC00B5EB2A /* g_action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_action.h; sourceTree = \"<group>\"; };\n\t\t07D7B415141D59EC00B5EB2A /* g_box.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_box.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B416141D59EC00B5EB2A /* g_box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_box.h; sourceTree = \"<group>\"; };\n\t\t07D7B417141D59EC00B5EB2A /* g_colors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_colors.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B418141D59EC00B5EB2A /* g_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_init.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B419141D59EC00B5EB2A /* g_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_init.h; sourceTree = \"<group>\"; };\n\t\t07D7B41A141D59EC00B5EB2A /* g_menu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_menu.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B41B141D59EC00B5EB2A /* g_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_menu.h; sourceTree = \"<group>\"; };\n\t\t07D7B41C141D59EC00B5EB2A /* g_menu_i.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_menu_i.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B41D141D59EC00B5EB2A /* g_menu_i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_menu_i.h; sourceTree = \"<group>\"; };\n\t\t07D7B41E141D59EC00B5EB2A /* g_menu_t.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_menu_t.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B41F141D59EC00B5EB2A /* g_menu_t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_menu_t.h; sourceTree = \"<group>\"; };\n\t\t07D7B420141D59EC00B5EB2A /* g_mouse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_mouse.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B421141D59EC00B5EB2A /* g_mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_mouse.h; sourceTree = \"<group>\"; };\n\t\t07D7B422141D59EC00B5EB2A /* g_tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_tools.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B423141D59EC00B5EB2A /* g_tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_tools.h; sourceTree = \"<group>\"; };\n\t\t07D7B424141D59EC00B5EB2A /* g_update.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_update.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B425141D59EC00B5EB2A /* g_update.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_update.h; sourceTree = \"<group>\"; };\n\t\t07D7B426141D59EC00B5EB2A /* g_widget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_widget.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B427141D59EC00B5EB2A /* g_widget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = g_widget.h; sourceTree = \"<group>\"; };\n\t\t07D7B428141D59EC00B5EB2A /* glasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glasses.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B429141D59EC00B5EB2A /* glasses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = glasses.h; sourceTree = \"<group>\"; };\n\t\t07D7B42A141D59EC00B5EB2A /* gui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gui.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B42B141D59EC00B5EB2A /* gui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gui.h; sourceTree = \"<group>\"; };\n\t\t07D7B42C141D59EC00B5EB2A /* hq2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hq2x.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B42D141D59EC00B5EB2A /* hq2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = hq2x.h; sourceTree = \"<group>\"; };\n\t\t07D7B42E141D59EC00B5EB2A /* hq2x16.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = hq2x16.asm; sourceTree = \"<group>\"; };\n\t\t07D7B42F141D59EC00B5EB2A /* hq2x32.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = hq2x32.asm; sourceTree = \"<group>\"; };\n\t\t07D7B430141D59EC00B5EB2A /* inputs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputs.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B431141D59EC00B5EB2A /* inputs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inputs.h; sourceTree = \"<group>\"; };\n\t\t07D7B432141D59EC00B5EB2A /* inputs_c.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputs_c.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B433141D59EC00B5EB2A /* inputs_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inputs_c.h; sourceTree = \"<group>\"; };\n\t\t07D7B434141D59EC00B5EB2A /* inputs_f.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputs_f.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B435141D59EC00B5EB2A /* inputs_f.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inputs_f.h; sourceTree = \"<group>\"; };\n\t\t07D7B436141D59EC00B5EB2A /* inputs_i.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputs_i.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B437141D59EC00B5EB2A /* inputs_i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inputs_i.h; sourceTree = \"<group>\"; };\n\t\t07D7B438141D59EC00B5EB2A /* inputs_t.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputs_t.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B439141D59EC00B5EB2A /* inputs_t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inputs_t.h; sourceTree = \"<group>\"; };\n\t\t07D7B43A141D59EC00B5EB2A /* inputs_u.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputs_u.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B43B141D59EC00B5EB2A /* inputs_u.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inputs_u.h; sourceTree = \"<group>\"; };\n\t\t07D7B43C141D59EC00B5EB2A /* ioports.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ioports.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B43D141D59EC00B5EB2A /* ioports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ioports.h; sourceTree = \"<group>\"; };\n\t\t07D7B43E141D59EC00B5EB2A /* keyinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyinfo.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B43F141D59EC00B5EB2A /* keyinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = keyinfo.h; sourceTree = \"<group>\"; };\n\t\t07D7B441141D59EC00B5EB2A /* EMPTY.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EMPTY.txt; sourceTree = \"<group>\"; };\n\t\t07D7B443141D59EC00B5EB2A /* unzip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unzip.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B444141D59EC00B5EB2A /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unzip.h; sourceTree = \"<group>\"; };\n\t\t07D7B445141D59EC00B5EB2A /* lightgun.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lightgun.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B446141D59EC00B5EB2A /* lightgun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = lightgun.h; sourceTree = \"<group>\"; };\n\t\t07D7B447141D59EC00B5EB2A /* machine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = machine.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B448141D59EC00B5EB2A /* machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = machine.h; sourceTree = \"<group>\"; };\n\t\t07D7B449141D59EC00B5EB2A /* mainloop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mainloop.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B44A141D59EC00B5EB2A /* mainloop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mainloop.h; sourceTree = \"<group>\"; };\n\t\t07D7B44B141D59EC00B5EB2A /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = \"<group>\"; };\n\t\t07D7B44C141D59EC00B5EB2A /* mappers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mappers.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B44D141D59EC00B5EB2A /* mappers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mappers.h; sourceTree = \"<group>\"; };\n\t\t07D7B44E141D59EC00B5EB2A /* meka.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = meka.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B44F141D59EC00B5EB2A /* meka.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = meka.h; sourceTree = \"<group>\"; };\n\t\t07D7B450141D59EC00B5EB2A /* meka.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = meka.ico; sourceTree = \"<group>\"; };\n\t\t07D7B451141D59EC00B5EB2A /* mekaw.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = mekaw.ico; sourceTree = \"<group>\"; };\n\t\t07D7B452141D59EC00B5EB2A /* mekaw.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mekaw.rc; sourceTree = \"<group>\"; };\n\t\t07D7B453141D59EC00B5EB2A /* mekaw.res */ = {isa = PBXFileReference; lastKnownFileType = file; path = mekaw.res; sourceTree = \"<group>\"; };\n\t\t07D7B454141D59EC00B5EB2A /* memory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B455141D59EC00B5EB2A /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = memory.h; sourceTree = \"<group>\"; };\n\t\t07D7B456141D59EC00B5EB2A /* message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B457141D59EC00B5EB2A /* message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = message.h; sourceTree = \"<group>\"; };\n\t\t07D7B458141D59EC00B5EB2A /* misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = misc.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B459141D59EC00B5EB2A /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = misc.h; sourceTree = \"<group>\"; };\n\t\t07D7B45B141D59EC00B5EB2A /* manifest.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = manifest.xml; sourceTree = \"<group>\"; };\n\t\t07D7B45C141D59EC00B5EB2A /* Meka.opt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Meka.opt; sourceTree = \"<group>\"; };\n\t\t07D7B45D141D59EC00B5EB2A /* Meka.plg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Meka.plg; sourceTree = \"<group>\"; };\n\t\t07D7B45E141D59EC00B5EB2A /* Meka.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Meka.rc; sourceTree = \"<group>\"; };\n\t\t07D7B45F141D59EC00B5EB2A /* meka.RES */ = {isa = PBXFileReference; lastKnownFileType = file; path = meka.RES; sourceTree = \"<group>\"; };\n\t\t07D7B460141D59EC00B5EB2A /* Meka.sln */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Meka.sln; sourceTree = \"<group>\"; };\n\t\t07D7B461141D59EC00B5EB2A /* Meka.vcproj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Meka.vcproj; sourceTree = \"<group>\"; };\n\t\t07D7B462141D59EC00B5EB2A /* mekaw.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = mekaw.ico; sourceTree = \"<group>\"; };\n\t\t07D7B463141D59EC00B5EB2A /* README.TXT */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.TXT; sourceTree = \"<group>\"; };\n\t\t07D7B464141D59EC00B5EB2A /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = resource.h; sourceTree = \"<group>\"; };\n\t\t07D7B466141D59EC00B5EB2A /* cpu.o */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.objfile\"; path = cpu.o; sourceTree = \"<group>\"; };\n\t\t07D7B467141D59EC00B5EB2A /* debug.o */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.objfile\"; path = debug.o; sourceTree = \"<group>\"; };\n\t\t07D7B46B141D59EC00B5EB2A /* machine.o */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.objfile\"; path = machine.o; sourceTree = \"<group>\"; };\n\t\t07D7B46C141D59EC00B5EB2A /* meka.o */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.objfile\"; path = meka.o; sourceTree = \"<group>\"; };\n\t\t07D7B472141D59EC00B5EB2A /* misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = misc.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B473141D59EC00B5EB2A /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = misc.h; sourceTree = \"<group>\"; };\n\t\t07D7B474141D59EC00B5EB2A /* timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timer.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B475141D59EC00B5EB2A /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = timer.h; sourceTree = \"<group>\"; };\n\t\t07D7B476141D59EC00B5EB2A /* palette.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = palette.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B477141D59EC00B5EB2A /* palette.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = palette.h; sourceTree = \"<group>\"; };\n\t\t07D7B478141D59EC00B5EB2A /* patch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = patch.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B479141D59EC00B5EB2A /* patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = patch.h; sourceTree = \"<group>\"; };\n\t\t07D7B47D141D59EC00B5EB2A /* meka.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; path = meka.xcodeproj; sourceTree = \"<group>\"; };\n\t\t07D7B480141D59EC00B5EB2A /* rapidfir.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rapidfir.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B481141D59EC00B5EB2A /* rapidfir.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rapidfir.h; sourceTree = \"<group>\"; };\n\t\t07D7B482141D59EC00B5EB2A /* saves.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saves.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B483141D59EC00B5EB2A /* saves.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = saves.h; sourceTree = \"<group>\"; };\n\t\t07D7B484141D59EC00B5EB2A /* sdsc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sdsc.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B485141D59EC00B5EB2A /* sdsc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sdsc.h; sourceTree = \"<group>\"; };\n\t\t07D7B486141D59EC00B5EB2A /* setup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = setup.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B487141D59EC00B5EB2A /* setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = setup.h; sourceTree = \"<group>\"; };\n\t\t07D7B488141D59EC00B5EB2A /* sf7000.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sf7000.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B489141D59EC00B5EB2A /* sf7000.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sf7000.h; sourceTree = \"<group>\"; };\n\t\t07D7B48A141D59EC00B5EB2A /* sg1ksc3k.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sg1ksc3k.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B48B141D59EC00B5EB2A /* sg1ksc3k.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sg1ksc3k.h; sourceTree = \"<group>\"; };\n\t\t07D7B48C141D59EC00B5EB2A /* shared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B48D141D59EC00B5EB2A /* shared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = shared.h; sourceTree = \"<group>\"; };\n\t\t07D7B48E141D59EC00B5EB2A /* sk1100.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sk1100.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B48F141D59EC00B5EB2A /* sk1100.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sk1100.h; sourceTree = \"<group>\"; };\n\t\t07D7B490141D59EC00B5EB2A /* skin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skin.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B491141D59EC00B5EB2A /* skin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = skin.h; sourceTree = \"<group>\"; };\n\t\t07D7B492141D59EC00B5EB2A /* skin_bg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skin_bg.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B493141D59EC00B5EB2A /* skin_bg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = skin_bg.h; sourceTree = \"<group>\"; };\n\t\t07D7B494141D59EC00B5EB2A /* skin_fx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skin_fx.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B495141D59EC00B5EB2A /* skin_fx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = skin_fx.h; sourceTree = \"<group>\"; };\n\t\t07D7B497141D59EC00B5EB2A /* replacement_code.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = replacement_code.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B498141D59EC00B5EB2A /* smsid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = smsid.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B499141D59EC00B5EB2A /* smsid.vcproj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = smsid.vcproj; sourceTree = \"<group>\"; };\n\t\t07D7B49C141D59EC00B5EB2A /* 2413tone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 2413tone.h; sourceTree = \"<group>\"; };\n\t\t07D7B49D141D59EC00B5EB2A /* emu2413.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emu2413.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B49E141D59EC00B5EB2A /* emu2413.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = emu2413.h; sourceTree = \"<group>\"; };\n\t\t07D7B49F141D59EC00B5EB2A /* emutypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = emutypes.h; sourceTree = \"<group>\"; };\n\t\t07D7B4A0141D59EC00B5EB2A /* mekaintf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mekaintf.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4A1141D59EC00B5EB2A /* mekaintf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mekaintf.h; sourceTree = \"<group>\"; };\n\t\t07D7B4A2141D59EC00B5EB2A /* sample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sample.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4A3141D59EC00B5EB2A /* fmeditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fmeditor.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4A4141D59EC00B5EB2A /* fmeditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = fmeditor.h; sourceTree = \"<group>\"; };\n\t\t07D7B4A5141D59EC00B5EB2A /* fmunit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fmunit.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4A6141D59EC00B5EB2A /* fmunit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = fmunit.h; sourceTree = \"<group>\"; };\n\t\t07D7B4A7141D59EC00B5EB2A /* psg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = psg.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4A8141D59EC00B5EB2A /* psg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = psg.h; sourceTree = \"<group>\"; };\n\t\t07D7B4AB141D59EC00B5EB2A /* s_misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = s_misc.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4AC141D59EC00B5EB2A /* s_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = s_misc.h; sourceTree = \"<group>\"; };\n\t\t07D7B4AD141D59EC00B5EB2A /* sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4AE141D59EC00B5EB2A /* sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sound.h; sourceTree = \"<group>\"; };\n\t\t07D7B4AF141D59EC00B5EB2A /* sound_logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_logging.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4B0141D59EC00B5EB2A /* sound_logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sound_logging.h; sourceTree = \"<group>\"; };\n\t\t07D7B4B1141D59EC00B5EB2A /* vgm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vgm.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4B2141D59EC00B5EB2A /* vgm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = vgm.h; sourceTree = \"<group>\"; };\n\t\t07D7B4B3141D59EC00B5EB2A /* wav.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wav.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4B4141D59EC00B5EB2A /* wav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = wav.h; sourceTree = \"<group>\"; };\n\t\t07D7B4B5141D59EC00B5EB2A /* sportpad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sportpad.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4B6141D59EC00B5EB2A /* sportpad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sportpad.h; sourceTree = \"<group>\"; };\n\t\t07D7B4B7141D59EC00B5EB2A /* system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = system.h; sourceTree = \"<group>\"; };\n\t\t07D7B4B8141D59EC00B5EB2A /* textbox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = textbox.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4B9141D59EC00B5EB2A /* textbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = textbox.h; sourceTree = \"<group>\"; };\n\t\t07D7B4BB141D59EC00B5EB2A /* liblist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = liblist.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4BC141D59EC00B5EB2A /* liblist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = liblist.h; sourceTree = \"<group>\"; };\n\t\t07D7B4BD141D59EC00B5EB2A /* libmy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libmy.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4BE141D59EC00B5EB2A /* libmy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = libmy.h; sourceTree = \"<group>\"; };\n\t\t07D7B4BF141D59EC00B5EB2A /* libparse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libparse.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4C0141D59EC00B5EB2A /* libparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = libparse.h; sourceTree = \"<group>\"; };\n\t\t07D7B4C1141D59EC00B5EB2A /* tfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tfile.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4C2141D59EC00B5EB2A /* tfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tfile.h; sourceTree = \"<group>\"; };\n\t\t07D7B4C3141D59EC00B5EB2A /* tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tools.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4C4141D59EC00B5EB2A /* tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tools.h; sourceTree = \"<group>\"; };\n\t\t07D7B4C5141D59EC00B5EB2A /* tvoekaki.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tvoekaki.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4C6141D59EC00B5EB2A /* tvoekaki.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tvoekaki.h; sourceTree = \"<group>\"; };\n\t\t07D7B4C7141D59EC00B5EB2A /* tvtype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tvtype.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4C8141D59EC00B5EB2A /* tvtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tvtype.h; sourceTree = \"<group>\"; };\n\t\t07D7B4C9141D59EC00B5EB2A /* vdp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdp.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4CA141D59EC00B5EB2A /* vdp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = vdp.h; sourceTree = \"<group>\"; };\n\t\t07D7B4CB141D59EC00B5EB2A /* video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4CC141D59EC00B5EB2A /* video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = video.h; sourceTree = \"<group>\"; };\n\t\t07D7B4CD141D59EC00B5EB2A /* video_c.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_c.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4CE141D59EC00B5EB2A /* video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = video_c.h; sourceTree = \"<group>\"; };\n\t\t07D7B4CF141D59EC00B5EB2A /* video_m2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_m2.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4D0141D59EC00B5EB2A /* video_m2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = video_m2.h; sourceTree = \"<group>\"; };\n\t\t07D7B4D1141D59EC00B5EB2A /* video_m5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_m5.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4D2141D59EC00B5EB2A /* video_m5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = video_m5.h; sourceTree = \"<group>\"; };\n\t\t07D7B4D3141D59EC00B5EB2A /* video_sp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_sp.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4D4141D59EC00B5EB2A /* video_t.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_t.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4D5141D59EC00B5EB2A /* videoasm.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = videoasm.asm; sourceTree = \"<group>\"; };\n\t\t07D7B4D6141D59EC00B5EB2A /* vlfn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vlfn.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4D7141D59EC00B5EB2A /* vlfn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = vlfn.h; sourceTree = \"<group>\"; };\n\t\t07D7B4D8141D59EC00B5EB2A /* vmachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vmachine.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4D9141D59EC00B5EB2A /* vmachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = vmachine.h; sourceTree = \"<group>\"; };\n\t\t07D7B4DB141D59EC00B5EB2A /* Codes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Codes.h; sourceTree = \"<group>\"; };\n\t\t07D7B4DC141D59EC00B5EB2A /* CodesCB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CodesCB.h; sourceTree = \"<group>\"; };\n\t\t07D7B4DD141D59EC00B5EB2A /* CodesED.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CodesED.h; sourceTree = \"<group>\"; };\n\t\t07D7B4DE141D59EC00B5EB2A /* CodesXCB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CodesXCB.h; sourceTree = \"<group>\"; };\n\t\t07D7B4DF141D59EC00B5EB2A /* CodesXX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CodesXX.h; sourceTree = \"<group>\"; };\n\t\t07D7B4E0141D59EC00B5EB2A /* dasm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dasm.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4E1141D59EC00B5EB2A /* Debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Debug.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4E2141D59EC00B5EB2A /* Tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Tables.h; sourceTree = \"<group>\"; };\n\t\t07D7B4E3141D59EC00B5EB2A /* todo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = todo; sourceTree = \"<group>\"; };\n\t\t07D7B4E4141D59EC00B5EB2A /* UNDOC.TXT */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = UNDOC.TXT; sourceTree = \"<group>\"; };\n\t\t07D7B4E5141D59EC00B5EB2A /* Z80.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Z80.cpp; sourceTree = \"<group>\"; };\n\t\t07D7B4E6141D59EC00B5EB2A /* Z80.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Z80.h; sourceTree = \"<group>\"; };\n\t\t07D7B4E7141D59EC00B5EB2A /* Z80Call.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Z80Call.cpp; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXGroup section */\n\t\t07D7B3AB141D591600B5EB2A = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B3B8141D59EC00B5EB2A /* srcs */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B3B8141D59EC00B5EB2A /* srcs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t075097E215EB793400B04454 /* app_cheatfinder.cpp */,\n\t\t\t\t075097E315EB793400B04454 /* app_cheatfinder.h */,\n\t\t\t\t07D7B3B9141D59EC00B5EB2A /* allegro4to5.cpp */,\n\t\t\t\t07D7B3BA141D59EC00B5EB2A /* allegro4to5.h */,\n\t\t\t\t07D7B3BB141D59EC00B5EB2A /* app_about.cpp */,\n\t\t\t\t07D7B3BC141D59EC00B5EB2A /* app_about.h */,\n\t\t\t\t07D7B3BD141D59EC00B5EB2A /* app_filebrowser.cpp */,\n\t\t\t\t07D7B3BE141D59EC00B5EB2A /* app_filebrowser.h */,\n\t\t\t\t07D7B3BF141D59EC00B5EB2A /* app_game.cpp */,\n\t\t\t\t07D7B3C0141D59EC00B5EB2A /* app_game.h */,\n\t\t\t\t07D7B3C1141D59EC00B5EB2A /* app_mapview.cpp */,\n\t\t\t\t07D7B3C2141D59EC00B5EB2A /* app_mapview.h */,\n\t\t\t\t07D7B3C3141D59EC00B5EB2A /* app_memview.cpp */,\n\t\t\t\t07D7B3C4141D59EC00B5EB2A /* app_memview.h */,\n\t\t\t\t07D7B3C5141D59EC00B5EB2A /* app_options.cpp */,\n\t\t\t\t07D7B3C6141D59EC00B5EB2A /* app_options.h */,\n\t\t\t\t07D7B3C7141D59EC00B5EB2A /* app_palview.cpp */,\n\t\t\t\t07D7B3C8141D59EC00B5EB2A /* app_palview.h */,\n\t\t\t\t07D7B3C9141D59EC00B5EB2A /* app_techinfo.cpp */,\n\t\t\t\t07D7B3CA141D59EC00B5EB2A /* app_techinfo.h */,\n\t\t\t\t07D7B3CB141D59EC00B5EB2A /* app_textview.cpp */,\n\t\t\t\t07D7B3CC141D59EC00B5EB2A /* app_textview.h */,\n\t\t\t\t07D7B3CD141D59EC00B5EB2A /* app_tileview.cpp */,\n\t\t\t\t07D7B3CE141D59EC00B5EB2A /* app_tileview.h */,\n\t\t\t\t07D7B3CF141D59EC00B5EB2A /* areplay.cpp */,\n\t\t\t\t07D7B3D0141D59EC00B5EB2A /* areplay.h */,\n\t\t\t\t07D7B3D1141D59EC00B5EB2A /* beam.cpp */,\n\t\t\t\t07D7B3D2141D59EC00B5EB2A /* beam.h */,\n\t\t\t\t07D7B3D3141D59EC00B5EB2A /* bios.cpp */,\n\t\t\t\t07D7B3D4141D59EC00B5EB2A /* bios.h */,\n\t\t\t\t07D7B3D5141D59EC00B5EB2A /* blit.cpp */,\n\t\t\t\t07D7B3D6141D59EC00B5EB2A /* blit.h */,\n\t\t\t\t07D7B3D7141D59EC00B5EB2A /* blit_c.cpp */,\n\t\t\t\t07D7B3D8141D59EC00B5EB2A /* blit_c.h */,\n\t\t\t\t07D7B3D9141D59EC00B5EB2A /* blitintf.cpp */,\n\t\t\t\t07D7B3DA141D59EC00B5EB2A /* blitintf.h */,\n\t\t\t\t07D7B3DB141D59EC00B5EB2A /* bmemory.cpp */,\n\t\t\t\t07D7B3DC141D59EC00B5EB2A /* bmemory.h */,\n\t\t\t\t07D7B3DD141D59EC00B5EB2A /* build.cpp */,\n\t\t\t\t07D7B3DE141D59EC00B5EB2A /* build.h */,\n\t\t\t\t07D7B3E0141D59EC00B5EB2A /* capture.cpp */,\n\t\t\t\t07D7B3E1141D59EC00B5EB2A /* capture.h */,\n\t\t\t\t07D7B3E2141D59EC00B5EB2A /* checksum.cpp */,\n\t\t\t\t07D7B3E3141D59EC00B5EB2A /* checksum.h */,\n\t\t\t\t07D7B3E4141D59EC00B5EB2A /* coleco.cpp */,\n\t\t\t\t07D7B3E5141D59EC00B5EB2A /* coleco.h */,\n\t\t\t\t07D7B3E6141D59EC00B5EB2A /* commport.cpp */,\n\t\t\t\t07D7B3E7141D59EC00B5EB2A /* commport.h */,\n\t\t\t\t07D7B3E8141D59EC00B5EB2A /* config.cpp */,\n\t\t\t\t07D7B3E9141D59EC00B5EB2A /* config.h */,\n\t\t\t\t07D7B3EA141D59EC00B5EB2A /* country.cpp */,\n\t\t\t\t07D7B3EB141D59EC00B5EB2A /* country.h */,\n\t\t\t\t07D7B3EC141D59EC00B5EB2A /* cpu.cpp */,\n\t\t\t\t07D7B3ED141D59EC00B5EB2A /* cpu.h */,\n\t\t\t\t07D7B3EE141D59EC00B5EB2A /* data.cpp */,\n\t\t\t\t07D7B3EF141D59EC00B5EB2A /* data.h */,\n\t\t\t\t07D7B3F0141D59EC00B5EB2A /* datadump.cpp */,\n\t\t\t\t07D7B3F1141D59EC00B5EB2A /* datadump.h */,\n\t\t\t\t07D7B3F2141D59EC00B5EB2A /* db.cpp */,\n\t\t\t\t07D7B3F3141D59EC00B5EB2A /* db.h */,\n\t\t\t\t07D7B3F4141D59EC00B5EB2A /* debugger.cpp */,\n\t\t\t\t07D7B3F5141D59EC00B5EB2A /* debugger.h */,\n\t\t\t\t07D7B3F6141D59EC00B5EB2A /* desktop.cpp */,\n\t\t\t\t07D7B3F7141D59EC00B5EB2A /* desktop.h */,\n\t\t\t\t07D7B3F8141D59EC00B5EB2A /* docs */,\n\t\t\t\t07D7B401141D59EC00B5EB2A /* drivers.cpp */,\n\t\t\t\t07D7B402141D59EC00B5EB2A /* drivers.h */,\n\t\t\t\t07D7B403141D59EC00B5EB2A /* eagle.asm */,\n\t\t\t\t07D7B404141D59EC00B5EB2A /* eagle.h */,\n\t\t\t\t07D7B405141D59EC00B5EB2A /* eeprom.cpp */,\n\t\t\t\t07D7B406141D59EC00B5EB2A /* eeprom.h */,\n\t\t\t\t07D7B407141D59EC00B5EB2A /* effects.cpp */,\n\t\t\t\t07D7B408141D59EC00B5EB2A /* effects.h */,\n\t\t\t\t07D7B409141D59EC00B5EB2A /* errors.cpp */,\n\t\t\t\t07D7B40A141D59EC00B5EB2A /* errors.h */,\n\t\t\t\t07D7B40B141D59EC00B5EB2A /* fdc765.cpp */,\n\t\t\t\t07D7B40C141D59EC00B5EB2A /* fdc765.h */,\n\t\t\t\t07D7B40D141D59EC00B5EB2A /* file.cpp */,\n\t\t\t\t07D7B40E141D59EC00B5EB2A /* file.h */,\n\t\t\t\t07D7B40F141D59EC00B5EB2A /* fonts.cpp */,\n\t\t\t\t07D7B410141D59EC00B5EB2A /* fonts.h */,\n\t\t\t\t07D7B411141D59EC00B5EB2A /* fskipper.cpp */,\n\t\t\t\t07D7B412141D59EC00B5EB2A /* fskipper.h */,\n\t\t\t\t07D7B413141D59EC00B5EB2A /* g_action.cpp */,\n\t\t\t\t07D7B414141D59EC00B5EB2A /* g_action.h */,\n\t\t\t\t07D7B415141D59EC00B5EB2A /* g_box.cpp */,\n\t\t\t\t07D7B416141D59EC00B5EB2A /* g_box.h */,\n\t\t\t\t07D7B417141D59EC00B5EB2A /* g_colors.cpp */,\n\t\t\t\t07D7B418141D59EC00B5EB2A /* g_init.cpp */,\n\t\t\t\t07D7B419141D59EC00B5EB2A /* g_init.h */,\n\t\t\t\t07D7B41A141D59EC00B5EB2A /* g_menu.cpp */,\n\t\t\t\t07D7B41B141D59EC00B5EB2A /* g_menu.h */,\n\t\t\t\t07D7B41C141D59EC00B5EB2A /* g_menu_i.cpp */,\n\t\t\t\t07D7B41D141D59EC00B5EB2A /* g_menu_i.h */,\n\t\t\t\t07D7B41E141D59EC00B5EB2A /* g_menu_t.cpp */,\n\t\t\t\t07D7B41F141D59EC00B5EB2A /* g_menu_t.h */,\n\t\t\t\t07D7B420141D59EC00B5EB2A /* g_mouse.cpp */,\n\t\t\t\t07D7B421141D59EC00B5EB2A /* g_mouse.h */,\n\t\t\t\t07D7B422141D59EC00B5EB2A /* g_tools.cpp */,\n\t\t\t\t07D7B423141D59EC00B5EB2A /* g_tools.h */,\n\t\t\t\t07D7B424141D59EC00B5EB2A /* g_update.cpp */,\n\t\t\t\t07D7B425141D59EC00B5EB2A /* g_update.h */,\n\t\t\t\t07D7B426141D59EC00B5EB2A /* g_widget.cpp */,\n\t\t\t\t07D7B427141D59EC00B5EB2A /* g_widget.h */,\n\t\t\t\t07D7B428141D59EC00B5EB2A /* glasses.cpp */,\n\t\t\t\t07D7B429141D59EC00B5EB2A /* glasses.h */,\n\t\t\t\t07D7B42A141D59EC00B5EB2A /* gui.cpp */,\n\t\t\t\t07D7B42B141D59EC00B5EB2A /* gui.h */,\n\t\t\t\t07D7B42C141D59EC00B5EB2A /* hq2x.cpp */,\n\t\t\t\t07D7B42D141D59EC00B5EB2A /* hq2x.h */,\n\t\t\t\t07D7B42E141D59EC00B5EB2A /* hq2x16.asm */,\n\t\t\t\t07D7B42F141D59EC00B5EB2A /* hq2x32.asm */,\n\t\t\t\t07D7B430141D59EC00B5EB2A /* inputs.cpp */,\n\t\t\t\t07D7B431141D59EC00B5EB2A /* inputs.h */,\n\t\t\t\t07D7B432141D59EC00B5EB2A /* inputs_c.cpp */,\n\t\t\t\t07D7B433141D59EC00B5EB2A /* inputs_c.h */,\n\t\t\t\t07D7B434141D59EC00B5EB2A /* inputs_f.cpp */,\n\t\t\t\t07D7B435141D59EC00B5EB2A /* inputs_f.h */,\n\t\t\t\t07D7B436141D59EC00B5EB2A /* inputs_i.cpp */,\n\t\t\t\t07D7B437141D59EC00B5EB2A /* inputs_i.h */,\n\t\t\t\t07D7B438141D59EC00B5EB2A /* inputs_t.cpp */,\n\t\t\t\t07D7B439141D59EC00B5EB2A /* inputs_t.h */,\n\t\t\t\t07D7B43A141D59EC00B5EB2A /* inputs_u.cpp */,\n\t\t\t\t07D7B43B141D59EC00B5EB2A /* inputs_u.h */,\n\t\t\t\t07D7B43C141D59EC00B5EB2A /* ioports.cpp */,\n\t\t\t\t07D7B43D141D59EC00B5EB2A /* ioports.h */,\n\t\t\t\t07D7B43E141D59EC00B5EB2A /* keyinfo.cpp */,\n\t\t\t\t07D7B43F141D59EC00B5EB2A /* keyinfo.h */,\n\t\t\t\t07D7B440141D59EC00B5EB2A /* libaddon */,\n\t\t\t\t07D7B445141D59EC00B5EB2A /* lightgun.cpp */,\n\t\t\t\t07D7B446141D59EC00B5EB2A /* lightgun.h */,\n\t\t\t\t07D7B447141D59EC00B5EB2A /* machine.cpp */,\n\t\t\t\t07D7B448141D59EC00B5EB2A /* machine.h */,\n\t\t\t\t07D7B449141D59EC00B5EB2A /* mainloop.cpp */,\n\t\t\t\t07D7B44A141D59EC00B5EB2A /* mainloop.h */,\n\t\t\t\t07D7B44B141D59EC00B5EB2A /* Makefile */,\n\t\t\t\t07D7B44C141D59EC00B5EB2A /* mappers.cpp */,\n\t\t\t\t07D7B44D141D59EC00B5EB2A /* mappers.h */,\n\t\t\t\t07D7B44E141D59EC00B5EB2A /* meka.cpp */,\n\t\t\t\t07D7B44F141D59EC00B5EB2A /* meka.h */,\n\t\t\t\t07D7B450141D59EC00B5EB2A /* meka.ico */,\n\t\t\t\t07D7B451141D59EC00B5EB2A /* mekaw.ico */,\n\t\t\t\t07D7B452141D59EC00B5EB2A /* mekaw.rc */,\n\t\t\t\t07D7B453141D59EC00B5EB2A /* mekaw.res */,\n\t\t\t\t07D7B454141D59EC00B5EB2A /* memory.cpp */,\n\t\t\t\t07D7B455141D59EC00B5EB2A /* memory.h */,\n\t\t\t\t07D7B456141D59EC00B5EB2A /* message.cpp */,\n\t\t\t\t07D7B457141D59EC00B5EB2A /* message.h */,\n\t\t\t\t07D7B458141D59EC00B5EB2A /* misc.cpp */,\n\t\t\t\t07D7B459141D59EC00B5EB2A /* misc.h */,\n\t\t\t\t07D7B45A141D59EC00B5EB2A /* MsVc */,\n\t\t\t\t07D7B465141D59EC00B5EB2A /* obj */,\n\t\t\t\t07D7B471141D59EC00B5EB2A /* osd */,\n\t\t\t\t07D7B476141D59EC00B5EB2A /* palette.cpp */,\n\t\t\t\t07D7B477141D59EC00B5EB2A /* palette.h */,\n\t\t\t\t07D7B478141D59EC00B5EB2A /* patch.cpp */,\n\t\t\t\t07D7B479141D59EC00B5EB2A /* patch.h */,\n\t\t\t\t07D7B47A141D59EC00B5EB2A /* projects */,\n\t\t\t\t07D7B480141D59EC00B5EB2A /* rapidfir.cpp */,\n\t\t\t\t07D7B481141D59EC00B5EB2A /* rapidfir.h */,\n\t\t\t\t07D7B482141D59EC00B5EB2A /* saves.cpp */,\n\t\t\t\t07D7B483141D59EC00B5EB2A /* saves.h */,\n\t\t\t\t07D7B484141D59EC00B5EB2A /* sdsc.cpp */,\n\t\t\t\t07D7B485141D59EC00B5EB2A /* sdsc.h */,\n\t\t\t\t07D7B486141D59EC00B5EB2A /* setup.cpp */,\n\t\t\t\t07D7B487141D59EC00B5EB2A /* setup.h */,\n\t\t\t\t07D7B488141D59EC00B5EB2A /* sf7000.cpp */,\n\t\t\t\t07D7B489141D59EC00B5EB2A /* sf7000.h */,\n\t\t\t\t07D7B48A141D59EC00B5EB2A /* sg1ksc3k.cpp */,\n\t\t\t\t07D7B48B141D59EC00B5EB2A /* sg1ksc3k.h */,\n\t\t\t\t07D7B48C141D59EC00B5EB2A /* shared.cpp */,\n\t\t\t\t07D7B48D141D59EC00B5EB2A /* shared.h */,\n\t\t\t\t07D7B48E141D59EC00B5EB2A /* sk1100.cpp */,\n\t\t\t\t07D7B48F141D59EC00B5EB2A /* sk1100.h */,\n\t\t\t\t07D7B490141D59EC00B5EB2A /* skin.cpp */,\n\t\t\t\t07D7B491141D59EC00B5EB2A /* skin.h */,\n\t\t\t\t07D7B492141D59EC00B5EB2A /* skin_bg.cpp */,\n\t\t\t\t07D7B493141D59EC00B5EB2A /* skin_bg.h */,\n\t\t\t\t07D7B494141D59EC00B5EB2A /* skin_fx.cpp */,\n\t\t\t\t07D7B495141D59EC00B5EB2A /* skin_fx.h */,\n\t\t\t\t07D7B496141D59EC00B5EB2A /* smsid */,\n\t\t\t\t07D7B49A141D59EC00B5EB2A /* sound */,\n\t\t\t\t07D7B4B5141D59EC00B5EB2A /* sportpad.cpp */,\n\t\t\t\t07D7B4B6141D59EC00B5EB2A /* sportpad.h */,\n\t\t\t\t07D7B4B7141D59EC00B5EB2A /* system.h */,\n\t\t\t\t07D7B4B8141D59EC00B5EB2A /* textbox.cpp */,\n\t\t\t\t07D7B4B9141D59EC00B5EB2A /* textbox.h */,\n\t\t\t\t07D7B4BA141D59EC00B5EB2A /* tools */,\n\t\t\t\t07D7B4C3141D59EC00B5EB2A /* tools.cpp */,\n\t\t\t\t07D7B4C4141D59EC00B5EB2A /* tools.h */,\n\t\t\t\t07D7B4C5141D59EC00B5EB2A /* tvoekaki.cpp */,\n\t\t\t\t07D7B4C6141D59EC00B5EB2A /* tvoekaki.h */,\n\t\t\t\t07D7B4C7141D59EC00B5EB2A /* tvtype.cpp */,\n\t\t\t\t07D7B4C8141D59EC00B5EB2A /* tvtype.h */,\n\t\t\t\t07D7B4C9141D59EC00B5EB2A /* vdp.cpp */,\n\t\t\t\t07D7B4CA141D59EC00B5EB2A /* vdp.h */,\n\t\t\t\t07D7B4CB141D59EC00B5EB2A /* video.cpp */,\n\t\t\t\t07D7B4CC141D59EC00B5EB2A /* video.h */,\n\t\t\t\t07D7B4CD141D59EC00B5EB2A /* video_c.cpp */,\n\t\t\t\t07D7B4CE141D59EC00B5EB2A /* video_c.h */,\n\t\t\t\t07D7B4CF141D59EC00B5EB2A /* video_m2.cpp */,\n\t\t\t\t07D7B4D0141D59EC00B5EB2A /* video_m2.h */,\n\t\t\t\t07D7B4D1141D59EC00B5EB2A /* video_m5.cpp */,\n\t\t\t\t07D7B4D2141D59EC00B5EB2A /* video_m5.h */,\n\t\t\t\t07D7B4D3141D59EC00B5EB2A /* video_sp.cpp */,\n\t\t\t\t07D7B4D4141D59EC00B5EB2A /* video_t.cpp */,\n\t\t\t\t07D7B4D5141D59EC00B5EB2A /* videoasm.asm */,\n\t\t\t\t07D7B4D6141D59EC00B5EB2A /* vlfn.cpp */,\n\t\t\t\t07D7B4D7141D59EC00B5EB2A /* vlfn.h */,\n\t\t\t\t07D7B4D8141D59EC00B5EB2A /* vmachine.cpp */,\n\t\t\t\t07D7B4D9141D59EC00B5EB2A /* vmachine.h */,\n\t\t\t\t07D7B4DA141D59EC00B5EB2A /* z80marat */,\n\t\t\t);\n\t\t\tname = srcs;\n\t\t\tpath = ../../..;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B3F8141D59EC00B5EB2A /* docs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B3F9141D59EC00B5EB2A /* blitter-notes.txt */,\n\t\t\t\t07D7B3FA141D59EC00B5EB2A /* db-notes.txt */,\n\t\t\t\t07D7B3FB141D59EC00B5EB2A /* README.txt */,\n\t\t\t\t07D7B3FC141D59EC00B5EB2A /* savestate */,\n\t\t\t\t07D7B3FF141D59EC00B5EB2A /* sound-engine-2003-12.txt */,\n\t\t\t\t07D7B400141D59EC00B5EB2A /* sound-engine-notes.txt */,\n\t\t\t);\n\t\t\tpath = docs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B3FC141D59EC00B5EB2A /* savestate */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B3FD141D59EC00B5EB2A /* meka_save_state_007.cpp */,\n\t\t\t\t07D7B3FE141D59EC00B5EB2A /* meka_save_state_00C.cpp */,\n\t\t\t);\n\t\t\tpath = savestate;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B440141D59EC00B5EB2A /* libaddon */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B441141D59EC00B5EB2A /* EMPTY.txt */,\n\t\t\t\t07D7B442141D59EC00B5EB2A /* zip */,\n\t\t\t);\n\t\t\tpath = libaddon;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B442141D59EC00B5EB2A /* zip */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B443141D59EC00B5EB2A /* unzip.cpp */,\n\t\t\t\t07D7B444141D59EC00B5EB2A /* unzip.h */,\n\t\t\t);\n\t\t\tpath = zip;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B45A141D59EC00B5EB2A /* MsVc */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B45B141D59EC00B5EB2A /* manifest.xml */,\n\t\t\t\t07D7B45C141D59EC00B5EB2A /* Meka.opt */,\n\t\t\t\t07D7B45D141D59EC00B5EB2A /* Meka.plg */,\n\t\t\t\t07D7B45E141D59EC00B5EB2A /* Meka.rc */,\n\t\t\t\t07D7B45F141D59EC00B5EB2A /* meka.RES */,\n\t\t\t\t07D7B460141D59EC00B5EB2A /* Meka.sln */,\n\t\t\t\t07D7B461141D59EC00B5EB2A /* Meka.vcproj */,\n\t\t\t\t07D7B462141D59EC00B5EB2A /* mekaw.ico */,\n\t\t\t\t07D7B463141D59EC00B5EB2A /* README.TXT */,\n\t\t\t\t07D7B464141D59EC00B5EB2A /* resource.h */,\n\t\t\t);\n\t\t\tpath = MsVc;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B465141D59EC00B5EB2A /* obj */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B466141D59EC00B5EB2A /* cpu.o */,\n\t\t\t\t07D7B467141D59EC00B5EB2A /* debug.o */,\n\t\t\t\t07D7B468141D59EC00B5EB2A /* libaddon */,\n\t\t\t\t07D7B46B141D59EC00B5EB2A /* machine.o */,\n\t\t\t\t07D7B46C141D59EC00B5EB2A /* meka.o */,\n\t\t\t\t07D7B46D141D59EC00B5EB2A /* osd */,\n\t\t\t\t07D7B46E141D59EC00B5EB2A /* sound */,\n\t\t\t\t07D7B470141D59EC00B5EB2A /* tools */,\n\t\t\t);\n\t\t\tpath = obj;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B468141D59EC00B5EB2A /* libaddon */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B469141D59EC00B5EB2A /* png */,\n\t\t\t\t07D7B46A141D59EC00B5EB2A /* zip */,\n\t\t\t);\n\t\t\tpath = libaddon;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B469141D59EC00B5EB2A /* png */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tpath = png;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B46A141D59EC00B5EB2A /* zip */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tpath = zip;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B46D141D59EC00B5EB2A /* osd */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tpath = osd;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B46E141D59EC00B5EB2A /* sound */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B46F141D59EC00B5EB2A /* emu2413 */,\n\t\t\t);\n\t\t\tpath = sound;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B46F141D59EC00B5EB2A /* emu2413 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tpath = emu2413;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B470141D59EC00B5EB2A /* tools */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tpath = tools;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B471141D59EC00B5EB2A /* osd */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B472141D59EC00B5EB2A /* misc.cpp */,\n\t\t\t\t07D7B473141D59EC00B5EB2A /* misc.h */,\n\t\t\t\t07D7B474141D59EC00B5EB2A /* timer.cpp */,\n\t\t\t\t07D7B475141D59EC00B5EB2A /* timer.h */,\n\t\t\t);\n\t\t\tpath = osd;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B47A141D59EC00B5EB2A /* projects */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B47B141D59EC00B5EB2A /* xcode */,\n\t\t\t);\n\t\t\tpath = projects;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B47B141D59EC00B5EB2A /* xcode */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B47C141D59EC00B5EB2A /* meka */,\n\t\t\t);\n\t\t\tpath = xcode;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B47C141D59EC00B5EB2A /* meka */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B47D141D59EC00B5EB2A /* meka.xcodeproj */,\n\t\t\t);\n\t\t\tpath = meka;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B47E141D59EC00B5EB2A /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B496141D59EC00B5EB2A /* smsid */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B497141D59EC00B5EB2A /* replacement_code.cpp */,\n\t\t\t\t07D7B498141D59EC00B5EB2A /* smsid.cpp */,\n\t\t\t\t07D7B499141D59EC00B5EB2A /* smsid.vcproj */,\n\t\t\t);\n\t\t\tpath = smsid;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B49A141D59EC00B5EB2A /* sound */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B49B141D59EC00B5EB2A /* emu2413 */,\n\t\t\t\t07D7B4A3141D59EC00B5EB2A /* fmeditor.cpp */,\n\t\t\t\t07D7B4A4141D59EC00B5EB2A /* fmeditor.h */,\n\t\t\t\t07D7B4A5141D59EC00B5EB2A /* fmunit.cpp */,\n\t\t\t\t07D7B4A6141D59EC00B5EB2A /* fmunit.h */,\n\t\t\t\t07D7B4A7141D59EC00B5EB2A /* psg.cpp */,\n\t\t\t\t07D7B4A8141D59EC00B5EB2A /* psg.h */,\n\t\t\t\t07D7B4AB141D59EC00B5EB2A /* s_misc.cpp */,\n\t\t\t\t07D7B4AC141D59EC00B5EB2A /* s_misc.h */,\n\t\t\t\t07D7B4AD141D59EC00B5EB2A /* sound.cpp */,\n\t\t\t\t07D7B4AE141D59EC00B5EB2A /* sound.h */,\n\t\t\t\t07D7B4AF141D59EC00B5EB2A /* sound_logging.cpp */,\n\t\t\t\t07D7B4B0141D59EC00B5EB2A /* sound_logging.h */,\n\t\t\t\t07D7B4B1141D59EC00B5EB2A /* vgm.cpp */,\n\t\t\t\t07D7B4B2141D59EC00B5EB2A /* vgm.h */,\n\t\t\t\t07D7B4B3141D59EC00B5EB2A /* wav.cpp */,\n\t\t\t\t07D7B4B4141D59EC00B5EB2A /* wav.h */,\n\t\t\t);\n\t\t\tpath = sound;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B49B141D59EC00B5EB2A /* emu2413 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B49C141D59EC00B5EB2A /* 2413tone.h */,\n\t\t\t\t07D7B49D141D59EC00B5EB2A /* emu2413.cpp */,\n\t\t\t\t07D7B49E141D59EC00B5EB2A /* emu2413.h */,\n\t\t\t\t07D7B49F141D59EC00B5EB2A /* emutypes.h */,\n\t\t\t\t07D7B4A0141D59EC00B5EB2A /* mekaintf.cpp */,\n\t\t\t\t07D7B4A1141D59EC00B5EB2A /* mekaintf.h */,\n\t\t\t\t07D7B4A2141D59EC00B5EB2A /* sample.cpp */,\n\t\t\t);\n\t\t\tpath = emu2413;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B4BA141D59EC00B5EB2A /* tools */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B4BB141D59EC00B5EB2A /* liblist.cpp */,\n\t\t\t\t07D7B4BC141D59EC00B5EB2A /* liblist.h */,\n\t\t\t\t07D7B4BD141D59EC00B5EB2A /* libmy.cpp */,\n\t\t\t\t07D7B4BE141D59EC00B5EB2A /* libmy.h */,\n\t\t\t\t07D7B4BF141D59EC00B5EB2A /* libparse.cpp */,\n\t\t\t\t07D7B4C0141D59EC00B5EB2A /* libparse.h */,\n\t\t\t\t07D7B4C1141D59EC00B5EB2A /* tfile.cpp */,\n\t\t\t\t07D7B4C2141D59EC00B5EB2A /* tfile.h */,\n\t\t\t);\n\t\t\tpath = tools;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t07D7B4DA141D59EC00B5EB2A /* z80marat */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t07D7B4DB141D59EC00B5EB2A /* Codes.h */,\n\t\t\t\t07D7B4DC141D59EC00B5EB2A /* CodesCB.h */,\n\t\t\t\t07D7B4DD141D59EC00B5EB2A /* CodesED.h */,\n\t\t\t\t07D7B4DE141D59EC00B5EB2A /* CodesXCB.h */,\n\t\t\t\t07D7B4DF141D59EC00B5EB2A /* CodesXX.h */,\n\t\t\t\t07D7B4E0141D59EC00B5EB2A /* dasm.cpp */,\n\t\t\t\t07D7B4E1141D59EC00B5EB2A /* Debug.cpp */,\n\t\t\t\t07D7B4E2141D59EC00B5EB2A /* Tables.h */,\n\t\t\t\t07D7B4E3141D59EC00B5EB2A /* todo */,\n\t\t\t\t07D7B4E4141D59EC00B5EB2A /* UNDOC.TXT */,\n\t\t\t\t07D7B4E5141D59EC00B5EB2A /* Z80.cpp */,\n\t\t\t\t07D7B4E6141D59EC00B5EB2A /* Z80.h */,\n\t\t\t\t07D7B4E7141D59EC00B5EB2A /* Z80Call.cpp */,\n\t\t\t);\n\t\t\tpath = z80marat;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXLegacyTarget section */\n\t\t07D7B3B2141D591600B5EB2A /* meka */ = {\n\t\t\tisa = PBXLegacyTarget;\n\t\t\tbuildArgumentsString = \"$(ACTION)\";\n\t\t\tbuildConfigurationList = 07D7B3B5141D591600B5EB2A /* Build configuration list for PBXLegacyTarget \"meka\" */;\n\t\t\tbuildPhases = (\n\t\t\t);\n\t\t\tbuildToolPath = /usr/bin/make;\n\t\t\tbuildWorkingDirectory = \"$(PROJECT_DIR)/../../../\";\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = meka;\n\t\t\tpassBuildSettingsInEnvironment = 1;\n\t\t\tproductName = meka;\n\t\t};\n/* End PBXLegacyTarget section */\n\n/* Begin PBXProject section */\n\t\t07D7B3AD141D591600B5EB2A /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t};\n\t\t\tbuildConfigurationList = 07D7B3B0141D591600B5EB2A /* Build configuration list for PBXProject \"meka\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\tEnglish,\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 07D7B3AB141D591600B5EB2A;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 07D7B47E141D59EC00B5EB2A /* Products */;\n\t\t\t\t\tProjectRef = 07D7B47D141D59EC00B5EB2A /* meka.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t07D7B3B2141D591600B5EB2A /* meka */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin XCBuildConfiguration section */\n\t\t07D7B3B3141D591600B5EB2A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_64_BIT)\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.7;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t07D7B3B4141D591600B5EB2A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_64_BIT)\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_ENABLE_OBJC_EXCEPTIONS = YES;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.7;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t07D7B3B6141D591600B5EB2A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tDEBUGGING_SYMBOLS = YES;\n\t\t\t\tGCC_GENERATE_DEBUGGING_SYMBOLS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tOTHER_CFLAGS = \"\";\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t07D7B3B7141D591600B5EB2A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tOTHER_CFLAGS = \"\";\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t07D7B3B0141D591600B5EB2A /* Build configuration list for PBXProject \"meka\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t07D7B3B3141D591600B5EB2A /* Debug */,\n\t\t\t\t07D7B3B4141D591600B5EB2A /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t07D7B3B5141D591600B5EB2A /* Build configuration list for PBXLegacyTarget \"meka\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t07D7B3B6141D591600B5EB2A /* Debug */,\n\t\t\t\t07D7B3B7141D591600B5EB2A /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 07D7B3AD141D591600B5EB2A /* Project object */;\n}\n"
  },
  {
    "path": "meka/srcs/projects/xcode/meka/meka.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:meka.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "meka/srcs/rapidfir.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - rapidfir.c\r\n// Simple rapid fire emulation/simulation - Code\r\n//-----------------------------------------------------------------------------\r\n// Note: a program could be written to analyze the speed of an official \r\n// Sega Master System Rapid Fire, and simulate that as well.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"rapidfir.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nint RapidFire;\r\nint RapidFire_Count;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    RapidFire_Init()\r\n{\r\n    RapidFire = 0;\r\n}\r\n\r\nvoid    RapidFire_Update()\r\n{\r\n    RapidFire_Count = (RapidFire_Count + 1) & 7;\r\n    if (RapidFire_Count & 4)\r\n    {\r\n        if (RapidFire & RAPIDFIRE_J1B1) tsms.Control[7] |= 0x0010;\r\n        if (RapidFire & RAPIDFIRE_J1B2) tsms.Control[7] |= 0x0020;\r\n        if (RapidFire & RAPIDFIRE_J2B1) tsms.Control[7] |= 0x0400;\r\n        if (RapidFire & RAPIDFIRE_J2B2) tsms.Control[7] |= 0x0800;\r\n    }\r\n}\r\n\r\nvoid    RapidFire_Switch_J1B1()\r\n{\r\n    RapidFire ^= RAPIDFIRE_J1B1;\r\n    gui_menu_toggle_check (menus_ID.rapidfire, 0);\r\n    if (RapidFire & RAPIDFIRE_J1B1)\r\n        Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_On), 1, 1);\r\n    else Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_Off), 1, 1);\r\n}\r\n\r\nvoid    RapidFire_Switch_J1B2()\r\n{\r\n    RapidFire ^= RAPIDFIRE_J1B2;\r\n    gui_menu_toggle_check (menus_ID.rapidfire, 1);\r\n    if (RapidFire & RAPIDFIRE_J1B2)\r\n        Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_On), 1, 2);\r\n    else Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_Off), 1, 2);\r\n}\r\n\r\nvoid    RapidFire_Switch_J2B1()\r\n{\r\n    RapidFire ^= RAPIDFIRE_J2B1;\r\n    gui_menu_toggle_check (menus_ID.rapidfire, 2);\r\n    if (RapidFire & RAPIDFIRE_J2B1)\r\n        Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_On), 2, 1);\r\n    else Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_Off), 2, 1);\r\n}\r\n\r\nvoid    RapidFire_Switch_J2B2()\r\n{\r\n    RapidFire ^= RAPIDFIRE_J2B2;\r\n    gui_menu_toggle_check (menus_ID.rapidfire, 3);\r\n    if (RapidFire & RAPIDFIRE_J2B2)\r\n        Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_On), 2, 2);\r\n    else Msg(MSGT_USER, Msg_Get(MSG_RapidFire_JxBx_Off), 2, 2);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/rapidfir.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - rapidfir.h\n// Rapid Fire Emulation/Simulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define RAPIDFIRE_J1B1          (1)\n#define RAPIDFIRE_J1B2          (2)\n#define RAPIDFIRE_J2B1          (4)\n#define RAPIDFIRE_J2B2          (8)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nextern int RapidFire;\nextern int RapidFire_Count;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    RapidFire_Init();\nvoid    RapidFire_Update();\n\nvoid    RapidFire_Switch_J1B1();\nvoid    RapidFire_Switch_J1B2();\nvoid    RapidFire_Switch_J2B1();\nvoid    RapidFire_Switch_J2B2();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/saves.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - saves.c\r\n// Save States - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"bios.h\"\r\n#include \"commport.h\"\r\n#include \"lightgun.h\"\r\n#include \"mappers.h\"\r\n#include \"palette.h\"\r\n#include \"saves.h\"\r\n#include \"sf7000.h\"\r\n#include \"tvoekaki.h\"\r\n#include \"vdp.h\"\r\n#include \"vmachine.h\"\r\n#include \"sound/fmunit.h\"\r\n#include \"sound/psg.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Fix up emulator data after loading a save state\r\nvoid        Load_Game_Fixup()\r\n{\r\n    int     i;\r\n    u8      b;\r\n\r\n    // CPU\r\n    #ifdef MARAT_Z80\r\n        sms.R.IPeriod = opt.Cur_IPeriod;\r\n        /*\r\n        #ifdef MEKA_Z80_DEBUGGER\r\n        if (Debugger.Enabled && Debugger.break_point_set)\r\n            sms.R.Trap = Debugger.break_point_address; // FIXME, argh\r\n        #endif\r\n        */\r\n    #endif\r\n\r\n    // Memory\r\n    // FIXME: need to clean all those stuff.. it's messy\r\n    //if (g_machine.driver_id != DRV_NES)\r\n    {\r\n        switch (g_machine.mapper)\r\n        {\r\n        case MAPPER_SMS_NoMapper:\r\n            break;\r\n        case MAPPER_Standard:\r\n        case MAPPER_93c46:\r\n            // We save previous RAM content, because:\r\n            // The code could do: LD (FFFF), xx then LD (DFFF), yy\r\n            // In this case, FCR[2]==xx but RAM[1FFF]==yy\r\n            b = RAM[0x1FFC]; WrZ80_NoHook (0xFFFC, sms.SRAM_Mapping_Register); RAM[0x1FFC] = b;\r\n            b = RAM[0x1FFD]; WrZ80_NoHook (0xFFFD, g_machine.mapper_regs[0]);  RAM[0x1FFD] = b;\r\n            b = RAM[0x1FFE]; WrZ80_NoHook (0xFFFE, g_machine.mapper_regs[1]);  RAM[0x1FFE] = b;\r\n            b = RAM[0x1FFF]; WrZ80_NoHook (0xFFFF, g_machine.mapper_regs[2]);  RAM[0x1FFF] = b;\r\n            break;\r\n        case MAPPER_SMS_Korean_MSX_8KB_0003:\r\n            WrZ80_NoHook (0x0000, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook (0x0001, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook (0x0002, g_machine.mapper_regs[2]);\r\n            WrZ80_NoHook (0x0003, g_machine.mapper_regs[3]);\r\n            break;\r\n        case MAPPER_SMS_Korean_MSX_8KB_0300:\r\n            WrZ80_NoHook(0x0000, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook(0x0100, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook(0x0200, g_machine.mapper_regs[2]);\r\n            WrZ80_NoHook(0x0300, g_machine.mapper_regs[3]);\r\n            break;\r\n        case MAPPER_SMS_Korean_Janggun:\r\n            WrZ80_NoHook (0xFFFE, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook (0x4000, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook (0x6000, g_machine.mapper_regs[2]);\r\n            WrZ80_NoHook (0xFFFF, g_machine.mapper_regs[3]);\r\n            WrZ80_NoHook (0x8000, g_machine.mapper_regs[4]);\r\n            WrZ80_NoHook (0xA000, g_machine.mapper_regs[5]);\r\n            break;\r\n        case MAPPER_CodeMasters:\r\n            WrZ80_NoHook (0x0000, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook (0x4000, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook (0x8000, g_machine.mapper_regs[2]);\r\n            break;\r\n        case MAPPER_SMS_4PakAllAction:\r\n            WrZ80_NoHook (0x3FFE, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook (0x7FFF, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook (0xBFFF, g_machine.mapper_regs[2]);\r\n            break;\r\n        case MAPPER_SMS_Korean_A000:\r\n            WrZ80_NoHook (0xA000, g_machine.mapper_regs[2]);\r\n            break;\r\n        case MAPPER_SMS_Korean_BFFC:\r\n            WrZ80_NoHook(0xBFFC, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_ColecoVision:\r\n            for (i = 0x0400; i < 0x2000; i += 0x400)\r\n                memcpy (RAM + i, RAM, 0x0400);\r\n            break;\r\n        case MAPPER_SG1000:\r\n            b = RAM[0x1FFD]; WrZ80_NoHook(0xFFFD, g_machine.mapper_regs[0]);     RAM[0x1FFD] = b;\r\n            b = RAM[0x1FFE]; WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[1]);     RAM[0x1FFE] = b;\r\n            b = RAM[0x1FFF]; WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[2]);     RAM[0x1FFF] = b;\r\n            memcpy (RAM + 0x1000, RAM, 0x1000);\r\n            break;\r\n        case MAPPER_SF7000:\r\n            SF7000_IPL_Mapping_Update();\r\n            break;\r\n        case MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA:\r\n            break;\r\n        case MAPPER_SMS_Korean_FFFF_HiCom:\r\n            WrZ80_NoHook (0xFFFF, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SC3000_Survivors_Multicart:\r\n            Out_SMS(0xE0, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SMS_Korean_2000_xor_1F:\r\n            WrZ80_NoHook(0x2000, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SMS_Korean_FFFE:\r\n            WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SMS_Korean_FFF3_FFFC:\r\n            WrZ80_NoHook(0xFFF3, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook(0xFFFC, g_machine.mapper_regs[1]);\r\n            break;\r\n        case MAPPER_SMS_Korean_0000_xor_FF:\r\n            WrZ80_NoHook(0x0000, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SMS_Korean_MD_FFF0:\r\n            WrZ80_NoHook(0xFFF0, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[2]);\r\n            break;\r\n        case MAPPER_SMS_Korean_MD_FFF5:\r\n            WrZ80_NoHook(0xFFF5, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[2]);\r\n            break;\r\n        case MAPPER_SMS_Korean_MD_FFFA:\r\n            WrZ80_NoHook(0xFFFA, g_machine.mapper_regs[0]);\r\n            WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[1]);\r\n            WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[2]);\r\n            break;\r\n        case MAPPER_SMS_Korean_MSX_32KB_2000:\r\n            WrZ80_NoHook(0x2000, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SMS_Korean_SMS_32KB_2000:\r\n            WrZ80_NoHook(0x2000, g_machine.mapper_regs[0]);\r\n            break;\r\n        case MAPPER_SMS_Korean_MSX_SMS_8000:\r\n            {\r\n                int mapper_page = g_machine.mapper_regs[0];\r\n                WrZ80_NoHook(0x8000, 0x00); // reset the mapper to avoid the 0xFF special case\r\n                WrZ80_NoHook(0x8000, mapper_page);\r\n            }\r\n            break;\r\n        }\r\n    }\r\n\r\n    // VDP/Graphic related\r\n    tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_ALL;\r\n    VDP_UpdateLineLimits();\r\n    // FALSE!!! // tsms.VDP_Line = 224;\r\n\r\n    // Rewrite all VDP registers (we can do that since it has zero side-effect)\r\n    for (i = 0; i < 16; i ++)\r\n        Tms_VDP_Out (i, sms.VDP[i]);\r\n\r\n    // Set all tiles as dirty\r\n    for (i = 0; i < MAX_TILES; i++)\r\n        tgfx.Tile_Dirty [i] = TILE_DIRTY_DECODE | TILE_DIRTY_REDRAW;\r\n\r\n    // Reload palette\r\n    Palette_Emulation_Reload();\r\n\r\n    // Msg(MSGT_DEBUG, \"ICount %d VDP Line %d\", CPU_GetICount(), tsms.VDP_Line);\r\n}\r\n\r\n// Save current state / dispatch to format saving code\r\nvoid        SaveState_Save()\r\n{\r\n    // Do not allow saving if machine is not running\r\n    if ((g_machine_flags & MACHINE_RUN) != MACHINE_RUN)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_No_ROM));\r\n        return;\r\n    }\r\n\r\n    // Do not allow saving in BIOS\r\n    // This would be messy with file handling currently\r\n    if ((g_machine_flags & MACHINE_NOT_IN_BIOS) == 0)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Save_Not_in_BIOS));\r\n        return;\r\n    }\r\n\r\n    char buf[FILENAME_LEN+1];\r\n    Save_Get_Filename(buf);\r\n    FILE* f;\r\n    int result;\r\n    if (!(f = fopen(buf, \"wb\")))\r\n        result = 2;\r\n    else\r\n    {\r\n        result = Save_Game_MSV(f);\r\n        fclose (f);\r\n    }\r\n\r\n    StrPath_RemoveDirectory (buf);\r\n    switch (result)\r\n    {\r\n    case 1: Msg(MSGT_USER, Msg_Get(MSG_Save_Success), buf);\r\n        break;\r\n    case 2: Msg(MSGT_USER, Msg_Get(MSG_Save_Error), buf);\r\n        break;\r\n    }\r\n}\r\n\r\n// Load state from current slot\r\nvoid        SaveState_Load()\r\n{\r\n    // Do not allow loading if machine is not running\r\n    if ((g_machine_flags & MACHINE_RUN) != MACHINE_RUN)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_No_ROM));\r\n        return;\r\n    }\r\n\r\n    // If loading while in BIOS, disable BIOS and switch to game\r\n    if ((g_machine_flags & MACHINE_NOT_IN_BIOS) == 0)\r\n    {\r\n        // Note: I'm not sure why I saved the current VDP line here...\r\n        const int line = tsms.VDP_Line;\r\n        BIOS_Switch_to_Game();\r\n        tsms.VDP_Line = line;\r\n    }\r\n\r\n    /*\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n        if (Debugger.Enabled)\r\n            Debugger.Break_Point = sms.R.Trap;\r\n    #endif\r\n    */\r\n\r\n    char buf[FILENAME_LEN+1];\r\n    Save_Get_Filename(buf);\r\n    \r\n    FILE* f;\r\n    int result;\r\n    if (!(f = fopen(buf, \"rb\")))\r\n        result = 2;\r\n    else\r\n    {\r\n        result = Load_Game_MSV (f);\r\n        fclose (f);\r\n    }\r\n\r\n    StrPath_RemoveDirectory (buf);\r\n    switch (result)\r\n    {\r\n    case 1: Msg(MSGT_USER, Msg_Get(MSG_Load_Success), buf);\r\n        Load_Game_Fixup();\r\n        break;\r\n    case 2: Msg(MSGT_USER, Msg_Get(MSG_Load_Error), buf);         break;\r\n    case 3: Msg(MSGT_USER, Msg_Get(MSG_Load_Not_Valid), buf);     break;\r\n    case 4: Msg(MSGT_USER, Msg_Get(MSG_Load_Version), buf);       break;\r\n    case 5: Msg(MSGT_USER, Msg_Get(MSG_Load_Wrong_System), buf);  break;\r\n    }\r\n\r\n    // Msg(MSGT_USER, \"Debugger.Break_Point = %04X\", Debugger.Break_Point);\r\n    // Msg(MSGT_USER, \"Loaded sms.R.Trap = %04X, %d\", sms.R.Trap, sms.R.Trace);\r\n}\r\n\r\n// Save current state to given file, in MEKA save state format\r\nint     Save_Game_MSV(FILE *f)\r\n{\r\n    u8  b;\r\n    u16 w;\r\n\r\n    BMemory_Verify_Usage();\r\n\r\n    // Write Header\r\n    fwrite (\"MEKA\", 4, 1, f);\r\n    b = 0x1A;\r\n    fwrite (&b, 1, 1, f);\r\n    b = MEKA_SAVESTATE_VERSION;\r\n    fwrite (&b, 1, 1, f);\r\n    b = g_machine.driver_id;  // Do NOT save g_driver->id, as it may change with legacy video mode in the current code\r\n    fwrite (&b, 1, 1, f);\r\n\r\n    // Write CRC32, introduced in version 0x0C\r\n    fwrite (&g_media_rom.crc32, sizeof (u32), 1, f);\r\n\r\n    // Write 'sms' structure (misc stuff)\r\n    sms.R.R = (sms.R.R & 0x7F) | (sms.R.R7);\r\n    sms.R.R7 = 0;\r\n    fwrite (&sms, sizeof (struct SMS_TYPE), 1, f);\r\n    sms.R.R7 = (sms.R.R & 0x80);\r\n\r\n    const int mappers_regs_to_save = (g_machine.mapper_regs_count <= 4) ? 4 : g_machine.mapper_regs_count;\r\n    fwrite (&g_machine.mapper_regs[0], sizeof(u8), mappers_regs_to_save, f);\r\n\r\n    // Write VDP scanline counter\r\n    w = tsms.VDP_Line;\r\n    fwrite (&w, sizeof (u16), 1, f);\r\n\r\n    // Write RAM & mapper specific data\r\n    // FIXME: RAM size should be based on value got from current driver\r\n    switch (g_machine.mapper)\r\n    {\r\n    case MAPPER_32kRAM:\r\n    case MAPPER_SC3000_Survivors_Multicart:\r\n        fwrite (RAM, 0x08000, 1, f);\r\n        break;\r\n    case MAPPER_ColecoVision:\r\n        fwrite (RAM, 0x00400, 1, f);\r\n        break;\r\n    case MAPPER_SG1000:\r\n        fwrite (RAM, 0x01000, 1, f);\r\n        break;\r\n    case MAPPER_TVOekaki:\r\n        fwrite (RAM, 0x01000, 1, f);\r\n        fwrite (&TVOekaki, sizeof (TVOekaki), 1, f);\r\n        break;\r\n    case MAPPER_SF7000:\r\n        fwrite (RAM, 0x10000, 1, f);\r\n        fwrite (&SF7000, sizeof (SF7000), 1, f);\r\n        break;\r\n    case MAPPER_CodeMasters:\r\n        if (sms.SRAM_Mapping_Register & ONBOARD_RAM_EXIST) // Ernie Els Golf Onboard RAM\r\n            fwrite (RAM, 0x2000 + 0x2000, 1, f);\r\n        else\r\n            fwrite (RAM, 0x2000, 1, f);\r\n        break;\r\n    case MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA:\r\n        fwrite (RAM, 0x02000, 1, f);\r\n        fwrite (RAM + 0x2000, 0x00800, 1, f);\r\n        break;\r\n    // All other mappers save 8KB of RAM (0x2000)\r\n    case MAPPER_Standard:\r\n    case MAPPER_SMS_NoMapper:\r\n    default:\r\n        fwrite (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change\r\n        break;\r\n    }\r\n    \r\n    // Write VRAM\r\n    fwrite (VRAM, 0x4000, 1, f);\r\n    \r\n    // Write Palette\r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_SMS:\r\n        fwrite (PRAM, 32, 1, f);\r\n        break;\r\n    case DRV_GG:\r\n        fwrite (PRAM, 64, 1, f);\r\n        fwrite (&Gear_to_Gear, sizeof (t_gear_to_gear), 1, f);\r\n        break;\r\n    }\r\n\r\n    // Write PSG & FM state\r\n    PSG_Save (f);\r\n    FM_Save (f);\r\n\r\n    // Write Port 3F value\r\n    fwrite (&tsms.Port3F, 1, 1, f);\r\n\r\n    // Write backed memory (SRAM, 93c46 EEPROM, etc.)\r\n    BMemory_Save_State (f);\r\n \r\n    // Write \"EOF\" characters\r\n    fwrite (\"EOF\", 3, 1, f);\r\n\r\n    return (1);\r\n}\r\n\r\n// Load state from given file, in MEKA save state format\r\nint         Load_Game_MSV(FILE *f)\r\n{\r\n    char    buf[5];\r\n    u8      b, version;\r\n\r\n    fread (&buf, 4, 1, f);\r\n    buf[4] = 0;\r\n    if (strcmp(buf, \"MEKA\") != 0)\r\n    {\r\n        if (strcmp(buf, \"S8B \") == 0)\r\n            return (Load_Game_MSD (f));\r\n        return (3); // not a savegame\r\n    }\r\n    fseek (f, 5, SEEK_SET);\r\n    fread (&version, 1, 1, f);\r\n    if (version > MEKA_SAVESTATE_VERSION)\r\n        return (4); // unsupported version\r\n\r\n    // Msg(MSGT_DEBUG, \"Loading, version = %02X\", version);\r\n\r\n    // Read driver id\r\n    fread (&b, 1, 1, f);\r\n    if (version >= 0x05)\r\n    {\r\n        // Check if we are running on the same machine\r\n        if (b != g_machine.driver_id)\r\n            return (5);\r\n    }\r\n    else\r\n    {\r\n        // Old kind of machine identification\r\n        if (b != drv_id_to_mode (g_machine.driver_id))\r\n            return (5); // not the same machine\r\n    }\r\n\r\n    // CRC32, introduced in version 0x0C. Currently skip this value.\r\n    if (version >= 0x0C)\r\n    {\r\n        u32 crc;\r\n        fread (&crc, sizeof (u32), 1, f);\r\n    }\r\n\r\n    // 'sms' structure (including CPU stuff)\r\n    {\r\n        // Backup then restore debugging purpose data\r\n        // So they're not lost when loading a state while debugging\r\n        u16 trap = sms.R.Trap;\r\n        u8  trace = sms.R.Trace;\r\n        fread (&sms, sizeof(struct SMS_TYPE), 1, f);\r\n        sms.R.R7 = (sms.R.R & 0x80);\r\n        sms.R.Trap = trap;\r\n        sms.R.Trace = trace;\r\n    }\r\n\r\n    if (version >= 0x0E)\r\n    {\r\n        // Always save at least 4 so that legacy software can readily bump up version and read data for most games (apart from those using mappers with >4 registers)\r\n        const int mappers_regs_to_save = (g_machine.mapper_regs_count <= 4) ? 4 : g_machine.mapper_regs_count;\r\n        fread(&g_machine.mapper_regs[0], sizeof(u8), mappers_regs_to_save, f);\r\n    }\r\n    else\r\n    {\r\n        // Old structure which was 3+1 (due to struct alignment)\r\n        fread(&g_machine.mapper_regs[0], sizeof(u8), 3+1, f);\r\n        for (int i = 3; i != MAPPER_REGS_MAX; i++)              // 4th value was padding so we also invalid it.\r\n            g_machine.mapper_regs[i] = 0;\r\n        if (g_machine.mapper == MAPPER_SMS_Korean_MSX_8KB_0003 || g_machine.mapper == MAPPER_SMS_Korean_MSX_8KB_0300)\r\n        {\r\n            u8 r[3];\r\n            r[0] = g_machine.mapper_regs[0];\r\n            r[1] = g_machine.mapper_regs[1];\r\n            r[2] = g_machine.mapper_regs[2];\r\n            g_machine.mapper_regs[0] = (r[2] & 0x0F);\r\n            g_machine.mapper_regs[1] = (r[2] & 0xF0) >> 4;\r\n            g_machine.mapper_regs[2] = (r[1] & 0x0F);\r\n            g_machine.mapper_regs[3] = (r[1] & 0xF0) >> 4;\r\n        }\r\n    }\r\n\r\n    // VDP scanline counter\r\n    if (version >= 0x0D)\r\n    {\r\n        u16 w;\r\n        fread (&w, sizeof (u16), 1, f);\r\n        tsms.VDP_Line = w;\r\n    }\r\n    else\r\n    {\r\n        // Leave as is now. Likely to be the same as same game/driver is running.\r\n    }\r\n\r\n    // Read RAM & mapper specific data\r\n    // FIXME: RAM size should be based on value got from current driver\r\n    switch (g_machine.mapper)\r\n    {\r\n    case MAPPER_32kRAM:\r\n    case MAPPER_SC3000_Survivors_Multicart:\r\n        fread (RAM, 0x08000, 1, f);\r\n        break;\r\n    case MAPPER_ColecoVision:\r\n        if (version >= 0x06)\r\n            fread (RAM, 0x00400, 1, f);\r\n        else\r\n            fread (RAM, 0x02000, 1, f); // Previously saved 8 Kb instead of 1 kb\r\n        break;\r\n    case MAPPER_SG1000:\r\n        if (version >= 0x06)\r\n            fread (RAM, 0x01000, 1, f);\r\n        else\r\n            fread (RAM, 0x02000, 1, f); // Previously saved 8 Kb instead of 4 Kb\r\n        break;\r\n    case MAPPER_TVOekaki:\r\n        fread (RAM, 0x01000, 1, f);\r\n        fread (&TVOekaki, sizeof (TVOekaki), 1, f);\r\n        break;\r\n    case MAPPER_SF7000:\r\n        fread (RAM, 0x10000, 1, f);\r\n        fread (&SF7000, sizeof (SF7000), 1, f);\r\n        break;\r\n    case MAPPER_CodeMasters:\r\n        if (sms.SRAM_Mapping_Register & ONBOARD_RAM_EXIST) // Ernie Els Golf Onboard RAM\r\n            fread (RAM, 0x2000 + 0x2000, 1, f);\r\n        else\r\n            fread (RAM, 0x2000, 1, f);\r\n        break;\r\n    case MAPPER_SG1000_Taiwan_MSX_Adapter_TypeA:\r\n        fread (RAM, 0x2000, 1, f);\r\n        fread (RAM + 0x2000, 0x0800, 1, f);\r\n        break;\r\n    // All other mappers save 8KB of RAM (0x2000)\r\n    case MAPPER_Standard:\r\n    case MAPPER_SMS_NoMapper:\r\n    default:\r\n        fread (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change\r\n        break;\r\n    }\r\n\r\n    // Read VRAM\r\n    fread (VRAM, 0x4000, 1, f);\r\n\r\n    // Read Palette\r\n    // This depend on g_machine.driver_id and NOT on g_driver->id\r\n    // Eg: even if palette is unused due to legacy mode set, we save CRAM/PRAM on a SMS\r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_SMS:\r\n        fread (PRAM, 32, 1, f);\r\n        break;\r\n    case DRV_GG:\r\n        fread (PRAM, 64, 1, f);\r\n        fread (&Gear_to_Gear, sizeof (t_gear_to_gear), 1, f);\r\n        break;\r\n    }\r\n\r\n    // Read PSG data\r\n    if (version >= 0x08)\r\n        PSG_Load (f, version);\r\n    else\r\n    {\r\n        // ...If not available, mute PSG volumes by default\r\n        // SN76489_Reset (opt.CPU_Clock_Current, audio_sample_rate);\r\n        PSG_Mute();\r\n        // There is a reason for muting the PSG volumes instead of reseting it all\r\n        // when the PSG data is missing: a same game is more likely to have noises \r\n        // setup the same way, so we want to keep current settings.\r\n    }\r\n\r\n    // Read FM data\r\n    if (version >= 0x03)\r\n        FM_Load(f);\r\n\r\n    // Read port 3F value\r\n    if (version >= 0x04)\r\n        fread (&tsms.Port3F, 1, 1, f);\r\n\r\n    // Previously stored 16 kb pages instead of 8 kb pages\r\n    if (version < 0x07)\r\n        sms.SRAM_Pages *= 2;\r\n\r\n    // Read backed memory unless version<0x09 & emulation 93c46\r\n    if (!(version < 0x09 && g_machine.mapper == MAPPER_93c46))\r\n        BMemory_Load_State(f);\r\n\r\n    // Fix up CPU registers\r\n    // Copy IFF2 bit for old Z80 Registers structure\r\n    if (version < 0x0A)\r\n        sms.R.IFF = ((sms.R.IFF & 0xB7) | ((sms.R.IFF & 0x40) ? IFF_2 : 0x00));\r\n\r\n    return (1);\r\n}\r\n\r\n// LOAD CURRENT GAME IN MASSAGE FORMAT ----------------------------------------\r\nint     Load_Game_MSD (FILE *f)\r\n{\r\n    word   w;\r\n    byte   i, version;\r\n\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Load_Massage));\r\n    /* Skipping \"SNAP\" */\r\n    fseek (f, 0x09, SEEK_SET);\r\n    fread (&version, 1, 1, f);\r\n    if (version > 0)\r\n        return (4); // not the same version, only version 0 defined and supported\r\n    fread (&i, 1, 1, f);\r\n    // Massage 0: SMS, 1: GG, which map to our define\r\n    if (i != 0 && i != 1)\r\n        return (4); // We only know about SMS/GG massage savestates\r\n    if (i != g_machine.driver_id)\r\n        return (5); // not the same machine\r\n    fread (&sms.Country, 1, 1, f);\r\n    /* Skipping FM enable/disable */\r\n    /* Skipping ports 0x00 to 0x06 */\r\n    // FIXME: read those port\r\n    /* Skipping ports 0x3E and 0x3F */\r\n    /* Skipping PSG frequencies/volume */\r\n    /* Skipping PSG latch/data bytes */\r\n    // FIXME: read PSG stuff\r\n    fseek (f, 0x28, SEEK_SET);\r\n    fread (&sms.VDP [0], 11, 1, f);\r\n    fread (&sms.VDP_Address, 2, 1, f);\r\n    fread (&sms.VDP_Access_Mode, 1, 1, f);\r\n    fread (&sms.VDP_Access_First, 1, 1, f);\r\n    fread (&w, 2, 1, f); /* Current Video Scanline */\r\n    tsms.VDP_Line = w;\r\n    fread (&sms.Lines_Left, 1, 1, f);\r\n    fread (&sms.Input_Mode, 1, 1, f); /* Port 0xDE */\r\n    fread (&sms.FM_Register, 1, 1, f);\r\n    fread (&sms.FM_Magic, 1, 1, f);\r\n    FM_Load (f);\r\n    fread (&sms.SRAM_Mapping_Register, 1, 1, f);\r\n    fread (&g_machine.mapper_regs[0], 3, 1, f);\r\n    g_machine.mapper_regs[3] = 0;\r\n    fread (RAM, 0x2000, 1, f);\r\n    fread (VRAM, 0x4000, 1, f);\r\n    switch (g_machine.driver_id)\r\n    {\r\n    case DRV_SMS:\r\n        fread (PRAM, 32, 1, f);\r\n        break;\r\n    case DRV_GG:\r\n        fread (PRAM, 64, 1, f);\r\n        break;\r\n    }\r\n    fread (SRAM, 0x8000, 1, f);\r\n#ifdef MARAT_Z80\r\n    fread (&sms.R.AF.B.l, 1, 1, f);\r\n    fread (&sms.R.AF.B.h, 1, 1, f);\r\n    fread (&sms.R.BC.B.l, 1, 1, f);\r\n    fread (&sms.R.BC.B.h, 1, 1, f);\r\n    fread (&sms.R.HL.B.l, 1, 1, f);\r\n    fread (&sms.R.HL.B.h, 1, 1, f);\r\n    fread (&sms.R.PC.B.l, 1, 1, f);\r\n    fread (&sms.R.PC.B.h, 1, 1, f);\r\n    fread (&sms.R.SP.B.l, 1, 1, f);\r\n    fread (&sms.R.SP.B.h, 1, 1, f);\r\n    fread (&sms.R.I, 1, 1, f);\r\n    fread (&sms.R.R, 1, 1, f);\r\n    sms.R.R7 = sms.R.R & 0x80;\r\n    fread (&sms.R.DE.B.l, 1, 1, f);\r\n    fread (&sms.R.DE.B.h, 1, 1, f);\r\n    fread (&sms.R.BC1.B.l, 1, 1, f);\r\n    fread (&sms.R.BC1.B.h, 1, 1, f);\r\n    fread (&sms.R.DE1.B.l, 1, 1, f);\r\n    fread (&sms.R.DE1.B.h, 1, 1, f);\r\n    fread (&sms.R.HL1.B.l, 1, 1, f);\r\n    fread (&sms.R.HL1.B.h, 1, 1, f);\r\n    fread (&sms.R.AF1.B.l, 1, 1, f);\r\n    fread (&sms.R.AF1.B.h, 1, 1, f);\r\n    fread (&sms.R.IY.B.l, 1, 1, f);\r\n    fread (&sms.R.IY.B.h, 1, 1, f);\r\n    fread (&sms.R.IX.B.l, 1, 1, f);\r\n    fread (&sms.R.IX.B.h, 1, 1, f);\r\n    { // FIXME: should verify\r\n        byte b[3];\r\n        fread (b, 3, 1, f);\r\n        sms.R.IFF = b[0];\r\n        sms.R.IFF = (sms.R.IFF & 0xF9);\r\n        if (b[2] == 1) sms.R.IFF |= 2;\r\n        else\r\n            if (b[2] == 2) sms.R.IFF |= 4;\r\n    }\r\n#else\r\n#error \"Load_Game_MSD() needs MARAT_Z80 core to load registers!\"\r\n#endif\r\n    return (1);\r\n}\r\n\r\nvoid    SaveState_SetSlot(int n)\r\n{\r\n    if (n < 0)  \r\n        n = 0;\r\n    if (n > 99) \r\n        n = 99;\r\n    Msg(MSGT_USER, Msg_Get(MSG_Save_Slot), n);\r\n    opt.State_Current = n;\r\n}\r\n\r\nvoid    SaveState_SetPrevSlot()\r\n{\r\n    SaveState_SetSlot(opt.State_Current - 1);\r\n}\r\n\r\nvoid    SaveState_SetNextSlot()\r\n{\r\n    SaveState_SetSlot(opt.State_Current + 1);\r\n}\r\n\r\n// RETURN FILENAME OF CURRENT SAVEGAME ----------------------------------------\r\nvoid    Save_Get_Filename (char *str)\r\n{\r\n    char buf [FILENAME_LEN];\r\n\r\n    // Create save state directory if it doesn't exist already\r\n    if (!al_filename_exists(g_env.Paths.SavegameDirectory))\r\n        al_make_directory(g_env.Paths.SavegameDirectory);\r\n\r\n    // Compute save state filename\r\n    strcpy(buf, g_env.Paths.MediaImageFile);\r\n    StrPath_RemoveExtension (buf);\r\n    StrPath_RemoveDirectory (buf);\r\n    sprintf(str, \"%s/%s.S%02d\", g_env.Paths.SavegameDirectory, buf, opt.State_Current);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/saves.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - saves.h\n// Save States - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define MEKA_SAVESTATE_VERSION (0x0E)\n\n// 0x06 -> 0x07\n// - sms.SRAM_Pages is multiplied by two\n//   Now a page is 8 kb instead of 16 kb (because of NES)\n\n// 0x07 -> 0x08\n// - saved PSG data\n\n// 0x08 -> 0x09\n// - rewrote 93c46 emulation\n//   93c46 data of version <= 0x07 is not loaded\n\n// 0x09 -> 0x0A\n// - upgraded Z80 core, IFF_2 flag in IFF is now 0x08 instead of 0x40\n//   old save states will copy the bit\n\n// 0x0A -> 0x0B\n// - updated PSG implementation and changed saved data (other than registers)\n\n// 0x0B -> 0x0C\n// - added ROM CRC32 (not used now, but will be useful for tools in the future)\n\n// 0x0C -> 0x0D\n// - added scanline counter. \n//   Having it fixed was a terrible mistake that I did not notice until I looked\n//   at the code recently. It screw up debugging and can break compatibility when\n//   my CPU emulation loop changes.\n\n// 0x0D -> 0x0E\n// - added 4th mapper register *only if needed* (by some Korean mappers)\n//   so that import code in other emulator won't break for most games\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid  SaveState_Load();\nvoid  SaveState_Save();\nvoid  SaveState_SetSlot(int n);\nvoid  SaveState_SetPrevSlot();\nvoid  SaveState_SetNextSlot();\nvoid  Load_Game_Fixup();\n\n//-----------------------------------------------------------------------------\n\nint   Load_Game_MSV(FILE *f);       // Save game in MEKA format\nint   Save_Game_MSV(FILE *f);       // Load game in MEKA format\nint   Load_Game_MSD(FILE *f);       // Load game in Massage format\n\nvoid  Save_Set_Slot(int n);\nvoid  Save_Get_Filename(char *str);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/sdsc.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sdsc.c\n// SDSC ROM Tag and Debug Console (designed by S8-Dev) - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"sdsc.h\"\n#include \"debugger.h\"\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define SDSC_MAGIC      \"SDSC\"\n\nbool have_sdsc_tag = false;\n\n//-----------------------------------------------------------------------------\n// SDSC command buffer state\n//-----------------------------------------------------------------------------\n\n// FIXME: Consider moving all those states into a struct.\n\nint     num_pending_bytes = 0;\nu8      byte_buffer[3];             // We fill this in for multi-byte commands\nu8*     p_next_byte = byte_buffer;  // Points to the next one to write\n\n//-----------------------------------------------------------------------------\n// State for formatting\n//-----------------------------------------------------------------------------\n\n// This is the size of the buffer we accumulate into. We flush when we get a newline.\n// Overflow is not handled particularly well.\nconst int sdsc_console_buffer_size = 16 * 1024;\n\n// This is the buffer we accumulate into\nchar    sdsc_console_buffer[sdsc_console_buffer_size];\n\n// This is the location in the buffer for the next character to go to\nchar*   p_next_char = sdsc_console_buffer;\n\n// This is the offset in the buffer of the most recent format string,\n// pointing at the leading '%'. We set it to NULL when not in a format\n// string, and thus it also signals whether formatting is needed.\nchar*   p_format_start = NULL;\n\n//-----------------------------------------------------------------------------\n// SDSC ROM Tag - Version 1.01\n//-----------------------------------------------------------------------------\n// ROM Offset 0x7FE0 (4 Bytes): \"SDSC\" (ASCII: 0x53, 0x44, 0x53, 0x43)\n// ROM Offset 0x7FE4 (1 Byte): Major Program version number (BCD)\n// ROM Offset 0x7FE5 (1 Byte): Minor Program version number (BCD)\n// ROM Offset 0x7FE6 (1 Byte): Day (BCD)\n// ROM Offset 0x7FE7 (1 Byte): Month (BCD)\n// ROM Offset 0x7FE8 (2 Bytes): Year (BCD) (Little-endian: 0x01 0x20 for 2001)\n// ROM Offset 0x7FEA (2 Bytes): ROM Address of program author, zero-terminated string\n// ROM Offset 0x7FEC (2 Bytes): ROM Address of program name, zero-terminated string.\n// ROM Offset 0x7FEE (2 Bytes): ROM Address of program release notes, zero-terminated string.\n// ROM Offset 0x7FF0 (16 Bytes): Normal SMS/GG header\n// Offset may be 0x4000 earlier for smaller ROMs\n//-----------------------------------------------------------------------------\n\n// Convert a BCD number to decimal\n// Note: no error handling is done, if using A-F values\nstatic int BCD_to_Dec(int bcd)\n{\n    int ret = 0;\n    int pow = 1;\n    while (bcd > 0)\n    {\n        ret += (bcd & 0xF) * pow;\n        bcd >>= 4;\n        pow *= 10;\n    }\n\n    return (ret);\n}\n\n//-----------------------------------------------------------------------------\n// SDSC_String_Get (int offset, int verbose_error)\n// Retrieve string at given ROM offset\n//-----------------------------------------------------------------------------\nchar *  SDSC_String_Get (int offset, int verbose_error)\n{\n    if (offset == 0x0000 || offset == 0xFFFF)\n        return (verbose_error ? strdup(Msg_Get(MSG_LoadROM_SDSC_Unknown)) : NULL);\n    if (offset >= tsms.Size_ROM)\n        return (verbose_error ? strdup(Msg_Get(MSG_LoadROM_SDSC_Error)) : NULL);\n\n    int len = 0;\n    char* src = (char *)(Game_ROM + offset);\n    while (src[len] != EOSTR && offset + len < tsms.Size_ROM)\n        len++;\n\n    // Note: we are not relying on StrNDup there, since it relies on strlen\n    char* result = (char*)malloc(sizeof (char) * (len + 1));\n    strncpy(result, src, len);\n    result[len] = EOSTR;\n    return (result);\n}\n\n// Called after ROM loading\n// Read SDSC Header and display it if found\n// Return whether something has been displayed or not\n// (return value currently not used)\nint         SDSC_Read_and_Display()\n{\n    have_sdsc_tag = false;\n\n    if (tsms.Size_ROM < 0x4000)\n        return false;\n    u8* header = Game_ROM + 0x3fe0;\n    if (strncmp((const char *)header, SDSC_MAGIC, 4) != 0)\n    {\n        if (tsms.Size_ROM < 0x8000)\n            return false;\n        header += 0x4000;\n        if (strncmp((const char *)header, SDSC_MAGIC, 4) != 0)\n            return false;\n    }\n\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_LoadROM_SDSC));\n\n    // Name\n    int offset = *(u16 *)(header + 0xc);\n    char* s = SDSC_String_Get(offset, TRUE);\n    Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_SDSC_Name), s);\n    free (s);\n\n    // Version\n    {\n        int major = BCD_to_Dec (*(u8 *)(header + 0x4));\n        int minor = BCD_to_Dec (*(u8 *)(header + 0x5));\n        Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_SDSC_Version), major, minor);\n    }\n\n    // Date\n    {\n        int day   = BCD_to_Dec (*(u8 *) (header + 0x6));\n        int month = BCD_to_Dec (*(u8 *) (header + 0x7));\n        int year  = BCD_to_Dec (*(u16 *)(header + 0x8));\n        if (year || month || day)\n            Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_SDSC_Date), year, month, day);\n    }\n\n    // Author\n    offset = *(u16 *)(header + 0xA);\n    s = SDSC_String_Get (offset, FALSE);\n    if (s)\n    {\n        Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_SDSC_Author), s);\n        free (s);\n    }\n\n    // Release Note\n    offset = *(u16 *)(header + 0xE);\n    s = SDSC_String_Get (offset, FALSE);\n    if (s)\n    {\n        // Msg(MSGT_USER_LOG, \"len = %d\", strlen(s));\n        Msg(MSGT_USER_LOG, Msg_Get(MSG_LoadROM_SDSC_Release_Note), s);\n        free (s);\n    }\n\n    have_sdsc_tag = true;\n\n    return true;\n}\n\nvoid SDSC_Debug_Console_Control(char c)\n{\n    if (!have_sdsc_tag)\n        return;\n\n    *p_next_byte++ = c;\n    if (--num_pending_bytes == -1)\n    {\n        // First byte of sequence\n        switch (c)\n        {\n        case 1:\n        case 2:\n        default:\n            num_pending_bytes = 0;\n            break;\n        case 3:\n            num_pending_bytes = 1;\n            break;\n        case 4:\n            num_pending_bytes = 2;\n            break;\n        }\n    }\n\n    if (num_pending_bytes == 0)\n    {\n        // Sequence done\n        switch (byte_buffer[0])\n        {\n        case 1:\n            //g_machine_pause_requests = 1; // Not immediate\n            //Machine_Debug_Start(); // Also not immediate\n            // This seems to be what makes it break - but only if the debugger is open.\n            sms.R.Trace = 1;\n            Debugger_Printf(\"SDSC debug console control: suspend emulation\");\n            break;\n        case 2:\n            Debugger_Printf(\"SDSC debug console control: clear console (not implemented)\");\n            break;\n        case 3:\n            {\n                static const char* colours[]\n                {\n                    \"Black\", \"Dark blue\", \"Dark green\", \"Dark cyan\", \"Dark red\", \"Dark magenta\", \"Dark yellow\", \"Dark gray\",\n                    \"Light gray\", \"Light blue\", \"Light green\", \"Light cyan\", \"Light red\", \"Light magenta\", \"Light yellow\", \"White\"\n                };\n                Debugger_Printf(\"SDSC debug console control: set attribute to %02x (%s on %s) (not implemented)\",\n                    byte_buffer[1],\n                    colours[byte_buffer[1] & 0xf],\n                    colours[byte_buffer[1] >> 4]);\n            }\n            break;\n        case 4:\n            Debugger_Printf(\"SDSC debug console control: set cursor position to row %d, column %d (not implemented)\",\n                byte_buffer[1] % 25,\n                byte_buffer[2] % 80);\n            break;\n        default:\n            Debugger_Printf(\"SDSC debug console control: unexpected value %d (not implemented)\", byte_buffer[0]);\n            break;\n        }\n\n        // Reset pointer\n        p_next_byte = byte_buffer;\n    }\n}\n\n// Formats and emits the error message into the SDSC console,\n// setting state variables such that the format string is consumed\n// Always returns false so it can be combined with a return\nbool SDSC_Format_Error(const char* format, ...)\n{\n    if (!have_sdsc_tag)\n        return false;\n\n    // Print the message over the format string\n    va_list params;\n    va_start(params, format);\n    const int chars_added = vsnprintf(p_format_start, sdsc_console_buffer_size - (p_format_start - sdsc_console_buffer), format, params);\n    va_end(params);\n    // Point to the following char\n    p_next_char = p_format_start + chars_added;\n    // Signal that the formatting has been consumed\n    p_format_start = NULL;\n    // Always return false\n    return false;\n}\n\n// Tries to parse the format string into the parameters\n// Returns true if the format string was correctly consumed\n// If there was an error, we return false and emit an error via SDSC_Format_Error()\nbool SDSC_Try_Parse_Format(int& width, char& format, int& data_type, int& parameter)\n{\n    // We iterate through and use this to determine which part we are working on\n    int state = 0;\n    int parameter_bytes_remaining = 0;\n    \n    // We stick a bit in here so we can shift more in and detect when we're done\n    // when this reaches the third byte\n    data_type = 1;\n    // We accumulate the ASCII width into here.\n    // An explicit zero width ought to be an error, but we don't handle that,\n    // and instead use zero as a signal for auto width.\n    width = 0;\n    // We accumulate the \"parameter\" into here.\n    parameter = 0;\n\n    // We walk from p_format_start to p_next_char-1 and see if it's valid\n    // If it is, we do the work and replace the format string with the result, and point pNextChar after it\n    // Else we just return\n    for (char* p_char = p_format_start + 1; p_char < p_next_char; ++p_char)\n    {\n        const char c = *p_char;\n        switch (state)\n        {\n        case 0:\n            // Optional width specifier\n            if (c >= '0' && c <= '9')\n            {\n                width *= 10;\n                width += c - '0';\n                break;\n            }\n            // Else fall through\n        case 1:\n            // Format specifier\n            if (width > 256)\n            {\n                return SDSC_Format_Error(\"[Excessive width %d]\", width);\n            }\n            switch (c)\n            {\n            case 'd':\n            case 'u':\n            case 'x':\n            case 'X':\n            case 'b':\n            case 'a':\n            case 's':\n                format = c;\n                state = 2;\n                break;\n            case '%':\n                // Special case: \"%%\" = \"%\"\n                format = c;\n                return true;\n            default:\n                return SDSC_Format_Error(\"[Invalid format type '%c']\", c);\n            }\n            break;\n        case 2:\n            // Data type\n            // We mash chars together into an int...\n            data_type <<= 8;\n            data_type |= c;\n            if (data_type & 0x010000)\n            {\n                data_type &= 0xffff;\n                // We have two bytes\n                // The second one is enough to determine the width\n                switch (c)\n                {\n                case 'w':\n                case 'b':\n                    // Memory or VRAM address\n                    parameter_bytes_remaining = 2;\n                    break;\n                case 'r':\n                    // Register index\n                    parameter_bytes_remaining = 1;\n                    break;\n                default:\n                    SDSC_Format_Error(\"[Invalid data type '%c%c']\", (data_type >> 8) & 0xff, c);\n                    return false;\n                }\n                ++state;\n            }\n            break;\n        case 3:\n            // First parameter byte\n            parameter |= (u8)c;\n            ++state;\n            if (--parameter_bytes_remaining == 0)\n            {\n                // Skip state 4\n                ++state;\n            }\n            break;\n        case 4:\n            // Second parameter byte\n            parameter |= (u8)c << 8;\n            ++state;\n            break;\n        default:\n            SDSC_Format_Error(\"[Formatting parser reached an invalid state]\");\n            return false;\n        }\n    }\n\n    // Success if we got to 5\n    return state == 5;\n}\n\n// Macro for combining two-character codes into ints\n// Endianness needs to match the way we parse it in\n#define FORMAT_TYPE(s) ((s)[0] << 8 | (s)[1])\n\nbool SDSC_Get_Data(u16& data, bool& is_byte, int data_type, int parameter)\n{\n    switch (data_type)\n    {\n    case FORMAT_TYPE(\"mw\"):\n        // Read 16-bit data from Z80 address\n        data = RdZ80_NoHook(parameter & 0xffff) | RdZ80_NoHook((parameter + 1) & 0xffff) << 8;\n        is_byte = false;\n        break;\n    case FORMAT_TYPE(\"mb\"):\n        // Read 8-bit data from Z80 address\n        data = RdZ80_NoHook(parameter & 0xffff);\n        is_byte = false;\n        break;\n    case FORMAT_TYPE(\"vw\"):\n        // Read 16-bit data from VRAM\n        data = VRAM[parameter & 0x3fff] | VRAM[(parameter + 1) & 0x3fff] << 8;\n        is_byte = false;\n        break;\n    case FORMAT_TYPE(\"vb\"):\n        // Read 8-bit data from VRAM\n        data = VRAM[parameter & 0x3fff];\n        is_byte = false;\n        break;\n    case FORMAT_TYPE(\"pr\"):\n        // Read processor register\n        // ASCII values are a non-standard extension I invented.\n        switch (parameter)\n        {\n        case 'b':\n        case 0x00: data = sms.R.BC.B.h; is_byte = true; break;\n        case 'c':\n        case 0x01: data = sms.R.BC.B.l; is_byte = true; break;\n        case 'd':\n        case 0x02: data = sms.R.DE.B.h; is_byte = true; break;\n        case 'e':\n        case 0x03: data = sms.R.DE.B.l; is_byte = true; break;\n        case 'h':\n        case 0x04: data = sms.R.HL.B.h; is_byte = true; break;\n        case 'l':\n        case 0x05: data = sms.R.HL.B.l; is_byte = true; break;\n        case 'a':\n        case 0x06: data = sms.R.AF.B.h; is_byte = true; break;\n        case 'f':\n        case 0x07: data = sms.R.AF.B.l; is_byte = true; break;\n        case 'p':\n        case 0x08: data = sms.R.PC.W; is_byte = false; break;\n        case 's':\n        case 0x09: data = sms.R.SP.W; is_byte = false; break;\n        case 'x':\n        case 0x0a: data = sms.R.IX.W; is_byte = false; break;\n        case 'y':\n        case 0x0b: data = sms.R.IY.W; is_byte = false; break;\n        case 'B':\n        case 0x0c: data = sms.R.BC.W; is_byte = false; break;\n        case 'D':\n        case 0x0d: data = sms.R.DE.W; is_byte = false; break;\n        case 'H':\n        case 0x0e: data = sms.R.HL.W; is_byte = false; break;\n        case 'A':\n        case 0x0f: data = sms.R.AF.W; is_byte = false; break;\n        case 'r':\n        case 0x10: data = sms.R.R; is_byte = true; break;\n        case 'i':\n        case 0x11: data = sms.R.I; is_byte = true; break;\n        case 0x12: data = sms.R.BC1.W; is_byte = false; break;\n        case 0x13: data = sms.R.DE1.W; is_byte = false; break;\n        case 0x14: data = sms.R.HL1.W; is_byte = false; break;\n        case 0x15: data = sms.R.AF1.W; is_byte = false; break;\n        default:\n            return SDSC_Format_Error(\"[Invalid processor register index %02x]\", parameter);\n        }\n        break;\n    case FORMAT_TYPE(\"vr\"):\n        if (parameter < 16)\n        {\n            // VDP register\n            data = sms.VDP[parameter];\n            is_byte = true;\n        }\n        else if (parameter < 48)\n        {\n            // Palette\n            int index = parameter - 16;\n            switch (g_machine.driver_id)\n            {\n            case DRV_SMS:\n                data = PRAM[index];\n                is_byte = true;\n                break;\n            case DRV_GG:\n                index *= 2;\n                data = PRAM[index] | ((u8)PRAM[index + 1] << 8);\n                is_byte = false;\n                break;\n            default:\n                return SDSC_Format_Error(\"[Can't read palette for this emulated system]\");\n            }\n        }\n        else\n        {\n            return SDSC_Format_Error(\"[Invalid VDP register index %02x]\", parameter);\n        }\n        break;\n    default:\n        return SDSC_Format_Error(\"[Invalid data type '%c%c']\", (char)((data_type >> 8) & 0xff), (char)(data_type & 0xff));\n    }\n    // If we get here, it worked\n    return true;\n}\n\n// Prints data as binary to buffer, skipping leading zeroes\nint SDSC_Print_Binary(char* buffer, u16 data)\n{\n    char* p = buffer;\n    for (int i = 0; i < 16; ++i)\n    {\n        const int bit = data >> (15 - i) & 1;\n        if (bit == 0 && p == buffer && i < 15)\n        {\n            // Skip leading zeroes\n            continue;\n        }\n        *p++ = '0' + bit;\n    }\n    return p - buffer;\n}\n\n// Prints data as ASCII to buffer\n// Non-printable is emitted as '.'\n// is_char = true will make us print exactly one char, even if the data is 0\n// is_char = false will make us print up to <width> characters, or until a 0 is encountered\n// (null-terminated string)\n// offset is an address in the Z80 memory, or VRAM\nint SDSC_Print_ASCII(char* buffer, int buffer_size, bool is_vram, bool is_char, int offset, int width)\n{\n    // Determine how many characters to emit\n    const int max_chars = is_char ? 1 : width > 0 ? width : buffer_size;\n    // We support wrapping the offset as we go\n    char* p = buffer;\n    for (int i = 0; i < max_chars; ++i)\n    {\n        // Get char\n        const char c = is_vram ? VRAM[offset & 0x3fff] : RdZ80_NoHook(offset & 0xffff);\n        // Stop on null for strings\n        if (c == 0 && !is_char)\n            break;\n        // Put into buffer\n        *p++ = isprint(c) ? c : '.';\n        // Move on\n        ++offset;\n    }\n    return p - buffer;\n}\n\n// Tries to format the text and emit it to the console\n// Leaves global state untouched when there is insufficient data to produce a result\n// (either successful formatting or an error message due to an invalid format string)\nvoid SDSC_Try_Format()\n{\n    // First parse the format\n    int width;\n    char format;\n    int data_type;\n    int parameter;\n    if (!SDSC_Try_Parse_Format(width, format, data_type, parameter))\n        return;\n\n    // Handle \"%%\" -> \"%\"\n    if (format == '%')\n    {\n        p_next_char = p_format_start + 1;\n        p_format_start = NULL;\n        return;\n    }\n\n    // Now get the data\n    u16 data = 0;\n    bool is_byte = false;\n    if (!SDSC_Get_Data(data, is_byte, data_type, parameter))\n    {\n        return;\n    }\n\n    // Then print it into a local temporary buffer\n    const int buffer_size = 256 + 1; // Spec says max width is 256\n    char buffer[buffer_size];\n    int formatted_length;\n    switch (format)\n    {\n    case 'd':\n        // Signed decimal\n        formatted_length = snprintf(buffer, buffer_size, \"%d\", is_byte ? (s8)data : (s16)data);\n        break;\n    case 'u':\n        // Unsigned decimal\n        formatted_length = snprintf(buffer, buffer_size, \"%u\", is_byte ? (u8)data : data);\n        break;\n    case 'x':\n        // Lowercase hex\n        formatted_length = snprintf(buffer, buffer_size, \"%x\", is_byte ? (u8)data : data);\n        break;\n    case 'X':\n        // Uppercase hex\n        formatted_length = snprintf(buffer, buffer_size, \"%X\", is_byte ? (u8)data : data);\n        break;\n    case 'b':\n        // Binary\n        formatted_length = SDSC_Print_Binary(buffer, is_byte ? (u8)data : data);\n        break;\n    case 'a':\n    case 's':\n        // ASCII\n        if (data_type != FORMAT_TYPE(\"mb\") && data_type != FORMAT_TYPE(\"vb\"))\n        {\n            SDSC_Format_Error(\"[Invalid format string: format type '%c' with data type '%c%c'\", format, data_type >> 8, data_type & 0xff);\n            return;\n        }\n        formatted_length = SDSC_Print_ASCII(buffer, buffer_size, data_type == FORMAT_TYPE(\"vb\"), format == 'a', parameter, width);\n        break;\n    default:\n        // Should already have checked this...\n        SDSC_Format_Error(\"Invalid format string: format type '%c'\", format);\n        return;\n    }\n\n    // Check width\n    if (width == 0)\n    {\n        // If no width is specified, use the \"natural\" width\n        width = formatted_length;\n    }\n    else if (width > formatted_length)\n    {\n        // If it is wider, pad appropriately\n        char padding;\n        switch (format)\n        {\n        case 'x':\n        case 'X':\n        case 'b':\n            padding = '0';\n            break;\n        default:\n            padding = ' ';\n            break;\n        }\n        int padding_count = width - formatted_length;\n        const int space_in_buffer = sdsc_console_buffer_size - (p_format_start - sdsc_console_buffer);\n        if (padding_count > space_in_buffer)\n        {\n            padding_count = space_in_buffer;\n        }\n        for (int i = 0; i < padding_count; ++i)\n        {\n            *p_format_start++ = padding;\n        }\n    }\n    // Now copy from buffer into the global buffer\n    char* p = buffer;\n    if (width < formatted_length)\n        p += formatted_length - width; // Skip leading chars to fit\n\n    // Replace the format string with the result\n    snprintf(p_format_start, sdsc_console_buffer_size - (p_format_start - sdsc_console_buffer), p, width);\n    p_next_char = p_format_start + formatted_length;\n    // And signal that we are done\n    p_format_start = NULL;\n}\n\nvoid SDSC_Debug_Console_Data(char c)\n{\n    if (!have_sdsc_tag)\n    {\n        return;\n    }\n\n    // Append to buffer\n    *p_next_char++ = c;\n    if (p_format_start != NULL)\n    {\n        // Try if we can process it, or reject it\n        SDSC_Try_Format();\n    }\n    else if (c == '%')\n    {\n        // Point at the leading '%'\n        p_format_start = p_next_char - 1;\n    }\n    else if (c == 10)\n    {\n        // Emit buffer up to this point\n        *p_next_char = NULL;\n        Debugger_Printf(\"SDSC> %s\", sdsc_console_buffer);\n        p_next_char = sdsc_console_buffer;\n    }\n    else if (c == 13)\n    {\n        // Not supported\n        --p_next_char;\n    }\n    else if (c < ' ' || c > 127)\n    {\n        Debugger_Printf(\"SDSC debug console: invalid character $%02x\", c);\n    }\n    if (p_next_char - sdsc_console_buffer >= sdsc_console_buffer_size)\n    {\n        // Buffer overflow\n        --p_next_char;\n        Debugger_Printf(\"SDSC debug console: buffer overflow, dumping contents\");\n        *p_next_char = NULL;\n        Debugger_Printf(\"SDSC> %s\", sdsc_console_buffer);\n        p_next_char = sdsc_console_buffer;\n        p_format_start = NULL;\n        // Push the last char back in\n        *p_next_char++ = c;\n    }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sdsc.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sdsc.h\n// SDSC ROM Tag and Debug Console (designed by S8-Dev) - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nint     SDSC_Read_and_Display();\nvoid    SDSC_Debug_Console_Control(char c);\nvoid    SDSC_Debug_Console_Data(char c);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/setup.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - setup.c\r\n// Interactive Setup - Code\r\n//-----------------------------------------------------------------------------\r\n// Note: the interactive setup is different depending on the system.\r\n// Different version feature different parameters to setup.\r\n//-----------------------------------------------------------------------------\r\n// - DOS, UNIX: Text mode. Soundcard setup.\r\n// - WIN32:     Win32 applet. Soundcard, soundrate, language, debugger enable setup.\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"config.h\"\r\n#include \"setup.h\"\r\n#include \"video.h\"\r\n#include \"sound/s_misc.h\"\r\n#ifdef ARCH_WIN32\r\n#include \"projects/msvc/resource.h\"\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n#ifdef ARCH_WIN32\r\n    static int    Setup_Interactive_Win32();\r\n#else\r\n    static int    Setup_Interactive_Console();\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid Setup_Interactive_Init()\r\n{\r\n    if (opt.Setup_Interactive_Execute)\r\n    {\r\n        ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Setup_Running));\r\n        opt.Setup_Interactive_Execute = FALSE;\r\n        const int ret = Setup_Interactive();\r\n        if (ret == MEKA_ERR_CANCEL)\r\n        {\r\n            // Note: the only reason for setting the state to SHUTDOWN is so that Quit() doesn't pause on the console.\r\n            g_env.state = MEKA_STATE_SHUTDOWN;\r\n            Quit();\r\n        }\r\n    }\r\n}\r\n\r\nint Setup_Interactive()\r\n{\r\n    // Call appropriate setup\r\n    #ifdef ARCH_WIN32\r\n        // Windows setup\r\n        return Setup_Interactive_Win32();\r\n    #else\r\n        // Console setup (DOS & UNIX)\r\n        //return Setup_Interactive_Console();\r\n        return MEKA_ERR_OK;\r\n    #endif\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef ARCH_WIN32\r\n\r\n//extern HINSTANCE      allegro_inst;\r\n\r\n// Win32 Dialog Procedure for interactive setup -------------------------------\r\nstatic BOOL CALLBACK    Setup_Interactive_Win32_DialogProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r\n{\r\n    switch (message)\r\n    {\r\n    case WM_INITDIALOG:\r\n        {\r\n            // Set various localized text\r\n            char buffer[256];\r\n            snprintf(buffer, countof(buffer), \"MEKA - %s\", Msg_Get(MSG_Setup_Setup));\r\n            SetWindowText(hDlg, buffer);\r\n            SetWindowText(GetDlgItem(hDlg, IDC_SETUP_VIDEO_DRIVER_TEXT), Msg_Get(MSG_Setup_Video_Driver));\r\n            SetWindowText(GetDlgItem(hDlg, IDC_SETUP_VIDEO_RESOLUTION_TEXT), Msg_Get(MSG_Setup_Video_DisplayMode));\r\n            SetWindowText(GetDlgItem(hDlg, IDC_SETUP_SOUND_SAMPLERATE_TEXT), Msg_Get(MSG_Setup_SampleRate_Select));\r\n\r\n            HWND combo_hwnd;\r\n            int default_selection;\r\n\r\n            // Fill video driver combo box\r\n            combo_hwnd = GetDlgItem(hDlg, IDC_SETUP_VIDEO_DRIVER);\r\n            default_selection = g_config.video_driver - &g_video_drivers[0];\r\n            t_video_driver* driver = &g_video_drivers[0];\r\n            while (driver->name)\r\n            {\r\n                int driver_idx = driver - &g_video_drivers[0];\r\n                const int combo_idx = SendMessage(combo_hwnd, CB_ADDSTRING, 0, (LPARAM)driver->desc);\r\n                SendMessage(combo_hwnd, CB_SETITEMDATA, combo_idx, (LPARAM)driver_idx);\r\n                driver++;\r\n            }\r\n            if (default_selection != -1)\r\n                SendMessage(combo_hwnd, CB_SETCURSEL, default_selection, 0);\r\n\r\n            // Fill screen format/resolution box\r\n            {\r\n                Video_EnumerateDisplayModes();\r\n                combo_hwnd = GetDlgItem(hDlg, IDC_SETUP_VIDEO_DISPLAY_MODE);\r\n                std::vector<t_video_mode>& display_modes = g_video.display_modes;\r\n                for (size_t i = 0; i != display_modes.size(); i++)\r\n                {\r\n                    t_video_mode* display_mode = &display_modes[i];\r\n                    char buf[256];\r\n                    sprintf(buf, \"%dx%d, %d Hz\", display_mode->w, display_mode->h, /*al_get_pixel_format_bits(display_mode->color_format),*/ display_mode->refresh_rate);\r\n\r\n                    const int combo_idx = SendMessage(combo_hwnd, CB_ADDSTRING, 0, (LPARAM)buf);\r\n                    SendMessage(combo_hwnd, CB_SETITEMDATA, combo_idx, (LPARAM)display_mode);\r\n                }\r\n                default_selection = g_video.display_mode_current_index;\r\n                if (default_selection != -1)\r\n                    SendMessage(combo_hwnd, CB_SETCURSEL, default_selection, 0);\r\n            }\r\n\r\n            // Fill sound rate combo box\r\n            combo_hwnd = GetDlgItem(hDlg, IDC_SETUP_SOUND_SAMPLERATE);\r\n            default_selection = 1; // FIXME: 1= 44100 KH\r\n            for (int i = 0; Sound_Rate_Default_Table[i] != -1; i++)\r\n            {\r\n                char buffer[256];\r\n                snprintf(buffer, countof(buffer), Msg_Get(MSG_Menu_Sound_Rate_Hz), Sound_Rate_Default_Table[i]);\r\n                const int combo_idx = SendMessage(combo_hwnd, CB_ADDSTRING, 0, (LPARAM)buffer);\r\n                SendMessage(combo_hwnd, CB_SETITEMDATA, combo_idx, (LPARAM)i);\r\n                if (Sound_Rate_Default_Table[i] == Sound.SampleRate)\r\n                    default_selection = i;\r\n            }\r\n            if (default_selection != -1)\r\n                SendMessage(combo_hwnd, CB_SETCURSEL, default_selection, 0);\r\n\r\n            // Fill language combo box\r\n            {\r\n                combo_hwnd = GetDlgItem(hDlg, IDC_SETUP_LANGUAGE);\r\n                for (t_list* langs = Messages.Langs; langs; langs = langs->next)\r\n                {\r\n                    t_lang* lang = (t_lang*)langs->elem;\r\n                    const int combo_idx = SendMessage(combo_hwnd, CB_ADDSTRING, 0, (LPARAM)lang->Name);\r\n                    SendMessage(combo_hwnd, CB_SETITEMDATA, combo_idx, (LPARAM)lang);\r\n                    // printf(\"lang %s %i\\n\", lang->Name, combo_idx);\r\n                }\r\n                int n = SendMessage(combo_hwnd, CB_GETCOUNT, 0, 0);\r\n                // Now set default selection\r\n                // Note: we have to do it that way because the combo box is sorted!\r\n                for (int i = 0; i < n; i++)\r\n                {\r\n                    t_lang *lang = (t_lang *)SendMessage(combo_hwnd, CB_GETITEMDATA, i, 0);\r\n                    if (lang == Messages.Lang_Cur)\r\n                    {\r\n                        SendMessage(combo_hwnd, CB_SETCURSEL, i, 0);\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            // Move to foreground, seems to be needed\r\n            SetForegroundWindow(hDlg);\r\n\r\n            return FALSE;\r\n        }\r\n    case WM_COMMAND:\r\n        {\r\n            switch (LOWORD(wParam))\r\n            {\r\n            case IDOK:\r\n                {\r\n                    if (HIWORD(wParam) == BN_CLICKED)\r\n                    {\r\n                        int  n;\r\n                        HWND combo_hwnd;\r\n\r\n                        // Video Driver\r\n                        if ((n = SendMessage(GetDlgItem(hDlg, IDC_SETUP_VIDEO_DRIVER), CB_GETCURSEL, 0, 0)) != CB_ERR)\r\n                            g_config.video_driver = &g_video_drivers[n];\r\n\r\n                        // Video Display Mode\r\n                        combo_hwnd = GetDlgItem(hDlg, IDC_SETUP_VIDEO_DISPLAY_MODE);\r\n                        if ((n = SendMessage(combo_hwnd, CB_GETCURSEL, 0, 0)) != CB_ERR)\r\n                        {\r\n                            t_video_mode* display_mode = (t_video_mode*)SendMessage(combo_hwnd, CB_GETITEMDATA, n, 0);\r\n                            g_config.video_mode_gui_res_x = display_mode->w;\r\n                            g_config.video_mode_gui_res_y = display_mode->h;\r\n                            g_config.video_mode_gui_refresh_rate = display_mode->refresh_rate;\r\n                        }\r\n\r\n                        // Sample Rate\r\n                        if ((n = SendMessage(GetDlgItem(hDlg, IDC_SETUP_SOUND_SAMPLERATE), CB_GETCURSEL, 0, 0)) != CB_ERR)\r\n                            Sound.SampleRate = Sound_Rate_Default_Table[n];\r\n\r\n                        // Language\r\n                        combo_hwnd = GetDlgItem(hDlg, IDC_SETUP_LANGUAGE);\r\n                        if ((n = SendMessage(combo_hwnd, CB_GETCURSEL, 0, 0)) != CB_ERR)\r\n                        {\r\n                            t_lang *lang = (t_lang *)SendMessage(combo_hwnd, CB_GETITEMDATA, n, 0);\r\n                            Messages.Lang_Cur = lang; // FIXME\r\n                        }\r\n\r\n                        // Debugger enable\r\n                        EndDialog(hDlg, 0);\r\n                    }\r\n                    return TRUE;\r\n                }\r\n            case IDCLOSE:\r\n                {\r\n                    if (HIWORD(wParam) == BN_CLICKED)\r\n                        EndDialog(hDlg, 2);\r\n                    return TRUE;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return FALSE;\r\n}\r\n\r\n// Interactive Setup (Win32 version) ------------------------------------------\r\n// Let user choose his sound card driver, sound rate and language\r\nstatic int Setup_Interactive_Win32()\r\n{\r\n    const HINSTANCE hInstance = GetModuleHandle(NULL);\r\n    const HWND hWndParent = 0; // win_get_window()\r\n    const int ret = DialogBox(hInstance, MAKEINTRESOURCE(IDD_SETUP), hWndParent, Setup_Interactive_Win32_DialogProc);\r\n    if (ret == -1)\r\n        return (MEKA_ERR_FAIL);\r\n    if (ret == 2)\r\n        return (MEKA_ERR_CANCEL);\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\n#else\r\n\r\n// Interactive Setup (Console version) ----------------------------------------\r\n// Let user choose his sound card driver\r\nstatic int Setup_Interactive_Console()\r\n{\r\n    // Print setup message\r\n    ConsolePrintf (\"[%s]\\n\", Msg_Get(MSG_Setup_Setup));\r\n\r\n    // Print sound card selection message\r\n//    ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Setup_Soundcard_Select));\r\n//#ifdef ARCH_WIN32\r\n//  ConsolePrintf(\"%s\\n\", Msg_Get(MSG_Setup_Soundcard_Select_Tips_Win32));\r\n//#endif\r\n\r\n    return MEKA_ERR_OK;\r\n}\r\n\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/setup.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - setup.h\r\n// Interactive Setup - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Setup_Interactive_Init();\r\nint     Setup_Interactive();\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/sf7000.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sf7000.c\n// SF-7000 (Super Control Station) Emulation - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"mappers.h\"\n#include \"bios.h\"\n#include \"sf7000.h\"\n\n//-----------------------------------------------------------------------------\n// The SF-7000 is an addon to the SC-3000. It provides the later one with:\n//   - a 3 inches floppy disk drive\n//   - 64 kb of RAM\n//   - a Centronics parallel port\n//   - a RS232 Serial port\n// The SF-7000 also contains an embedded 8 kb ROM called the IPL (Initial\n// Program Loader) which is disablable after use and replaced by 8 kb of RAM\n// in the memory map. The SF-7000 always boot from the IPL, at location 0x0000.\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// MEMORY MAP\n//    0x0000 -> 0x3FFF : IPL ROM or RAM (depending on port 0xE6, bit 6)\n//    0x4000 -> 0xFFFF : RAM\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// PORT MAP (Note: those are called from IOPORTS.C)\n//-----------------------------------------------------------------------------\n// P.P.I (8255A)\n//   0xE4 - PA: Input        - FDC/Printer check\n//   0xE5 - PB: Input        - Printer data output (parallel)\n//   0xE6 - PC: Output       - FDC/Printer control\n//   0xE7 - Control Register\n//-----------------------------------------------------------------------------\n// FDC (765AC)\n//   0xE0 - Status Register\n//   0xE1 - Data Register\n//-----------------------------------------------------------------------------\n// USART (8251)\n//   0xE8 - USARTD (Data)\n//   0xE9 - USARTC (Command)\n//-----------------------------------------------------------------------------\n// Meaning of P.P.I. ports:\n//    PA0 - FDC INT : INT signal from inout from FDC\n//    PA1 - BUSY from Centronics printer\n//    PA2 - Pin 17 of the FDC ?\n// PB0..7 - Data outputs to Centronics printer\n//    PC0 - /INUSE signal to FDD\n//    PC1 - /MOTOR ON signal to FDD\n//    PC2 - TC signal to FDD\n//    PC3 - RESET signal to FDC\n//    PC4 - N.C.\n//    PC5 - N.C.\n//    PC6 - /ROM SEL: Switching between IPL ROM and RAM\n//    PC7 - /STROBE to Centronics printer\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// >>> Si tu as des docs a propos du registre de controle, je ne dis pas non ;)\n// >> Quel registre de contrle ? FDC? 8255?\n// > Oui, celui qui est mapp sur le port 0xE7.\n// J'ai une description complte dans un bouquin pour interfacer le z80.\n// J'ai sous la main un cours d'IUT, voici en gros le principe :\n// --- Lors de l'init, utiliser CTRL avec :\n// bit 7 :  1\n// bit 6 et 5 : mode de fonctionnement Groupe A\n// bit 4 : sens port A (0=en sorties)\n// bit 3 : sens 1/2 port C suprieur (0=en sorties)\n// bit 2 : mode de fonctionnement Groupe B\n// bit 1 : sens port B (0=en sorties)\n// bit 0 : sens 1/2 port C infrieur (0=en sorties)\n// --- Oprations de Set/Reset du port C, utiliser CTRL avec :\n// bit 7 :  0\n// bit 6,5,4 : inutiliss\n// bit 3,2,1 : numro du bit du Port C  affecter\n// bit 0 : valeur 0 ou 1\n// exemple : LD A,5 ; OUT CTRL = mise  1 du bit 2 du port C\n//-----------------------------------------------------------------------------\n\nt_sf7000 SF7000;\n\nvoid    SF7000_Reset()\n{\n    SF7000.Port_E4 = 0x00;\n    SF7000.Port_E5 = 0x00;\n    SF7000.Port_E6 = 0x00;\n    SF7000.Port_E7 = 0x00;\n    SF7000.Port_E8 = 0x00;\n    SF7000.Port_E9 = 0x00;\n}\n\nvoid    SF7000_IPL_Mapping_Update()\n{\n    if (IPL_Disabled)\n    {\n        Map_8k_RAM (0, 0);\n        Map_8k_RAM (1, 1);\n    }\n    else\n    {\n        Map_16k_Other (0, BIOS_ROM_SF7000);\n    }\n}\n\n// [MAPPER: SF-7000] WRITE BYTE -----------------------------------------------\nWRITE_FUNC (Write_Mapper_SF7000)\n{\n    /*\n    int Page = Addr >> 13;\n    if ((Page == 0 || Page == 1) && (IPL_Enabled))\n    {\n    //Out_SF7000 (0xE6, SF7000.Port_E6 | 0x40);\n    //Write_Error (Addr, Value);\n    Msg(MSGT_DEBUG, Msg_Get(MSG_Debug_Trap_Write), sms.R.PC.W, Value, Addr);\n    return;\n    }\n    Mem_Pages [Page] [Addr] = Value;\n    */\n\n    // Allowing to write even with IPL is enabled is needed\n    // (Sega Basic Disk Version needs that at least)\n    RAM [Addr] = Value;\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sf7000.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sf7000.h\n// SF-7000 (Super Control Station) Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define IPL_Enabled             (!(SF7000.Port_E6 & 0x40))\n#define IPL_Disabled            (SF7000.Port_E6 & 0x40)\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    SF7000_Reset();\nvoid    SF7000_IPL_Mapping_Update();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_sf7000\n{\n    u8  Port_E4, Port_E5, Port_E6, Port_E7;\n    u8  Port_E8, Port_E9;\n};\n\nextern t_sf7000 SF7000;\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sg1ksc3k.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - sg1ksc3k.c\r\n// SG-1000/SC-3000 Specifics Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"fskipper.h\"\r\n#include \"inputs_t.h\"\r\n#include \"patch.h\"\r\n#include \"vdp.h\"\r\n#include \"video.h\"\r\n#include \"video_m2.h\"\r\n#include \"debugger.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nword    Loop_SG1000_SC3000()\r\n{\r\n    int interrupt = INT_NONE;\r\n\r\n    // Update sound cycle counter\r\n    Sound.CycleCounter += opt.Cur_IPeriod;\r\n\r\n    tsms.VDP_Line = (tsms.VDP_Line + 1) % g_machine.TV_lines;\r\n\r\n    // Debugger hook\r\n    #ifdef MEKA_Z80_DEBUGGER\r\n    if (Debugger.active)\r\n        Debugger_RasterLine_Hook(tsms.VDP_Line);\r\n    #endif\r\n\r\n    if (tsms.VDP_Line == 0)\r\n    {\r\n        if (Interrupt_Loop_Misc(&interrupt))\r\n            Macro_Stop_CPU;\r\n        Interrupt_Loop_Misc_Line_Zero();\r\n    }\r\n\r\n    if (tsms.VDP_Line >= 0 && tsms.VDP_Line < 192)\r\n    {\r\n        // Skip collision check if the sprite collision flag is already set\r\n        if (!(sms.VDP_Status & VDP_STATUS_SpriteCollision))\r\n            Check_Sprites_Collision_Modes_1_2_3_Line (tsms.VDP_Line);\r\n    }\r\n\r\n    if (tsms.VDP_Line == 192)\r\n    {\r\n        if (fskipper.Show_Current_Frame)\r\n        {\r\n            // Msg(MSGT_DEBUG, \"Loop_SG1000_SC3000: Refresh_Modes_0_1_2_3()\");\r\n            Refresh_Modes_0_1_2_3();\r\n        }\r\n\r\n        sms.VDP_Status |= VDP_STATUS_VBlank;\r\n        //if (!(sms.VDP_Status & VDP_STATUS_SpriteCollision))\r\n        //   Check_Sprites_Collision_Modes_1_2_3();\r\n\r\n        // Note: refresh screen may reset the system, so you can NOT change\r\n        // the status AFTER it, or else it would screw the newly emulated code\r\n        // Msg(MSGT_DEBUG, \"Loop_SG1000_SC3000: Video_RefreshScreen()\");\r\n        Video_RefreshScreen();\r\n\r\n        if ((opt.Force_Quit) || (CPU_Loop_Stop))\r\n            Macro_Stop_CPU;\r\n    }\r\n\r\n    if ((VBlank_ON) /* && (sms.VDP_Access_Mode == VDP_Access_Mode_1) */\r\n        && (sms.VDP_Status & VDP_STATUS_VBlank))\r\n    {\r\n        interrupt = INT_IRQ;\r\n        // Msg(MSGT_DEBUG, \"At PC=%04X: V-Blank\", CPU_GetPC);\r\n    }\r\n\r\n    if (interrupt == INT_IRQ)\r\n    {\r\n        #ifdef MARAT_Z80\r\n            sms.R.IRequest = interrupt;\r\n        #elif MAME_Z80\r\n            z80_set_irq_line (0, ASSERT_LINE);\r\n        #endif\r\n    }\r\n    else\r\n        // Note: NMI should have the priority over standard Interrupts (by definition)\r\n        // but this behavior is weird to emulate, and should not to be needed in the\r\n        // case we are using CPU_ForceNMI now.\r\n        if (CPU_ForceNMI)\r\n        {\r\n            CPU_ForceNMI = FALSE;\r\n            sms.R.IRequest = interrupt;\r\n            return (INT_NMI);\r\n        }\r\n\r\n        return (interrupt);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/sg1ksc3k.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sg1ksc3k.h\n// SG-1000/SC-3000 Specifics Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nword    Loop_SG1000_SC3000();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/shared.cpp",
    "content": "#include \"shared.h\"\r\n"
  },
  {
    "path": "meka/srcs/shared.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - shared.h\n// Shared headers, includes, variables and constants\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Configuration\n//-----------------------------------------------------------------------------\n\n#define MEKA_SOUND              // Enable sound\n#define MEKA_ZIP                // Enable ZIP file support\n#define MEKA_JOYPAD             // Enable joypad support\n#define MEKA_Z80_DEBUGGER       // Enable Z80 debugger\n#define MARAT_Z80               // Z80 emulator to use\n\n#define MEKA_NAME               \"MEKA\"\n#define MEKA_VERSION            \"0.80-alpha\"\n#define MEKA_VERSION_HIGH       (0)\n#define MEKA_VERSION_LOW        (80)\n#define MEKA_NAME_VERSION       MEKA_NAME \" \" MEKA_VERSION\n#define MEKA_HOMEPAGE           \"http://www.smspower.org/meka\"\n#define MEKA_AUTHORS            \"Omar Cornut (Bock), Marat Fayzullin, Mitsutaka Okazaki, Maxim & more contributors\"\n#define MEKA_AUTHORS_SHORT      \"Omar Cornut and MEKA team\"\n#define MEKA_DATE               \"1998-2025\"\n\nextern char MEKA_BUILD_DATE[];\nextern char MEKA_BUILD_TIME[];\n\n//-----------------------------------------------------------------------------\n// System Includes\n//-----------------------------------------------------------------------------\n\n#include \"system.h\"\n#include \"libmisc.h\"\n\n//-----------------------------------------------------------------------------\n// Z80 CPU cores\n//-----------------------------------------------------------------------------\n\n#ifdef MARAT_Z80\n// with Marat Faizullin's Z80 Core\n  #include \"z80marat/Z80.h\"\n#elif RAZE_Z80\n// with Richard Mitton's Z80 Core\n  #include \"z80raze/raze.h\"\n#elif MAME_Z80\n// with MAME's Z80 Core\n  #include \"z80mame/z80.h\"\n#else\n  #error \"No CPU choosen for compilation.\"\n#endif\n\n//-----------------------------------------------------------------------------\n// Forward declaration\n//-----------------------------------------------------------------------------\n\nstruct t_tv_type;\nstruct t_widget;\n\n//-----------------------------------------------------------------------------\n// MEKA shared components includes\n//-----------------------------------------------------------------------------\n// FIXME: remove them if possible, in favor of manual include of what's needed.\n//-----------------------------------------------------------------------------\n#include \"meka.h\"           // Main structures and definitions\n#include \"bmemory.h\"        // Backed memory devices emulation\n#include \"country.h\"        // Country interfacing and emulation\n#include \"cpu.h\"            // Interface with CPU / Interrupt emulation\n#include \"data.h\"           // Data file loading and data processing\n#include \"drivers.h\"        // Drivers structures\n#include \"errors.h\"         // Errors code and handling\n#include \"gui.h\"            // Graphical User Interface (includes 14 other files)\n#include \"fonts.h\"          // Fonts helper and wrapper\n#include \"inputs.h\"         // Inputs processing\n#include \"inputs_u.h\"       // Inputs update\n#include \"ioports.h\"        // IO Ports emulation\n#include \"machine.h\"        // Emulated machine initialization/reset\n#include \"mainloop.h\"       // Main Loop\n#include \"message.h\"        // Messages system and all messages\n#include \"misc.h\"           // Miscellaneous\n#include \"skin.h\"           // Interface Skins\n#include \"sound/sound.h\"    // Sound Engine (include other files)\n#include \"tools.h\"          // Various tools\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/sk1100.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - sk1100.c\r\n// SK-1100 (Sega Keyboard) / SC-3000 Keyboard Emulation - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"inputs_t.h\"\r\n#include \"sk1100.h\"\r\n#include \"skin_bg.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_sk1100_key\r\n{\r\n    int     row;\r\n    int     bit;\r\n    char    desc[16];\r\n};\r\n\r\n#define SK1100_KEYS_NUM (62)\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic t_sk1100_key SK1100_Keys [SK1100_KEYS_NUM] =\r\n{\r\n  // Row: 0 -------------------------------------------------------------------\r\n  {  0, 0x0001, \"1\"              }, //  0\r\n  {  0, 0x0002, \"Q\"              }, //  1\r\n  {  0, 0x0004, \"A\"              }, //  2\r\n  {  0, 0x0008, \"Z\"              }, //  3\r\n  {  0, 0x0010, \"Eng Dier's\"     }, //  4\r\n  {  0, 0x0020, \",\"              }, //  5\r\n  {  0, 0x0040, \"K\"              }, //  6\r\n  {  0, 0x0080, \"I\"              }, //  7\r\n  {  0, 0x0100, \"8\"              }, //  8\r\n  // Row: 1 -------------------------------------------------------------------\r\n  {  1, 0x0001, \"2\"              }, //  9\r\n  {  1, 0x0002, \"W\"              }, // 10\r\n  {  1, 0x0004, \"S\"              }, // 11\r\n  {  1, 0x0008, \"X\"              }, // 12\r\n  {  1, 0x0010, \"Space\"          }, // 13\r\n  {  1, 0x0020, \".\"              }, // 14\r\n  {  1, 0x0040, \"L\"              }, // 15\r\n  {  1, 0x0080, \"O\"              }, // 16\r\n  {  1, 0x0100, \"9\"              }, // 17\r\n  // Row: 2 -------------------------------------------------------------------\r\n  {  2, 0x0001, \"3\"              }, // 18\r\n  {  2, 0x0002, \"E\"              }, // 19\r\n  {  2, 0x0004, \"D\"              }, // 20\r\n  {  2, 0x0008, \"C\"              }, // 21\r\n  {  2, 0x0010, \"Home/Clear\"     }, // 22\r\n  {  2, 0x0020, \"/\"              }, // 23\r\n  {  2, 0x0040, \";\"              }, // 24\r\n  {  2, 0x0080, \"P\"              }, // 25\r\n  {  2, 0x0100, \"0\"              }, // 26\r\n  // Row: 3 -------------------------------------------------------------------\r\n  {  3, 0x0001, \"4\"              }, // 27\r\n  {  3, 0x0002, \"R\"              }, // 28\r\n  {  3, 0x0004, \"F\"              }, // 29\r\n  {  3, 0x0008, \"V\"              }, // 30\r\n  {  3, 0x0010, \"Insert/Delete\"  }, // 31\r\n  {  3, 0x0020, \"Pi\"             }, // 32\r\n  {  3, 0x0040, \":\"              }, // 33\r\n  {  3, 0x0080, \"@\"              }, // 34\r\n  {  3, 0x0100, \"-\"              }, // 35\r\n  // Row: 4 -------------------------------------------------------------------\r\n  {  4, 0x0001, \"5\"              }, // 36\r\n  {  4, 0x0002, \"T\"              }, // 37\r\n  {  4, 0x0004, \"G\"              }, // 38\r\n  {  4, 0x0008, \"B\"              }, // 39\r\n  // 4, 0x0010, <UNUSED>\r\n  {  4, 0x0020, \"Down Arrow\"     }, // 40\r\n  {  4, 0x0040, \"]\"              }, // 41\r\n  {  4, 0x0080, \"[\"              }, // 42\r\n  {  4, 0x0100, \"^\"              }, // 43\r\n  // Row: 5 -------------------------------------------------------------------\r\n  {  5, 0x0001, \"6\"              }, // 44\r\n  {  5, 0x0002, \"Y\"              }, // 45\r\n  {  5, 0x0004, \"H\"              }, // 46\r\n  {  5, 0x0008, \"N\"              }, // 47\r\n  // 5, 0x0010, <UNUSED>\r\n  {  5, 0x0020, \"Left Arrow\"     }, // 48\r\n  {  5, 0x0040, \"Return\"         }, // 49\r\n  // 5, 0x0080, <UNUSED>\r\n  {  5, 0x0100, \"\\x9d\"              }, // 50\r\n  // 5, 0x0200, <UNUSED>\r\n  // 5, 0x0400, <UNUSED>\r\n  {  5, 0x0800, \"Func\"           }, // 51\r\n  // Row: 6 -------------------------------------------------------------------\r\n  {  6, 0x0001, \"7\"              }, // 52\r\n  {  6, 0x0002, \"U\"              }, // 53\r\n  {  6, 0x0004, \"J\"              }, // 54\r\n  {  6, 0x0008, \"M\"              }, // 55\r\n  // 6, 0x0010, <UNUSED>\r\n  {  6, 0x0020, \"Right Arrow\"    }, // 56\r\n  {  6, 0x0040, \"Up Arrow\"       }, // 57\r\n  // 6, 0x0080, <UNUSED>\r\n  {  6, 0x0100, \"Break\"          }, // 58\r\n  {  6, 0x0200, \"Graph\"          }, // 59\r\n  {  6, 0x0400, \"Ctrl\"           }, // 60\r\n  {  6, 0x0800, \"Shift\"          }  // 61\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_sk1100_map\r\n{\r\n    int   key_pc;\r\n    int   key_sk1100;\r\n};\r\n\r\n#define SK1100_MAPPING_NUM (62+7)\r\n\r\nstatic  t_sk1100_map SK1100_Mapping [SK1100_MAPPING_NUM] =\r\n{\r\n    // Row: 0 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_1,               0      },\r\n    { ALLEGRO_KEY_Q,               1      },\r\n    { ALLEGRO_KEY_A,               2      },\r\n    { ALLEGRO_KEY_Z,               3      },\r\n    { ALLEGRO_KEY_ALT,             4      }, // Eng Dier's\r\n    { ALLEGRO_KEY_COMMA,           5      },\r\n    { ALLEGRO_KEY_K,               6      },\r\n    { ALLEGRO_KEY_I,               7      },\r\n    { ALLEGRO_KEY_8,               8      },\r\n    // Row: 1 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_2,               9      },\r\n    { ALLEGRO_KEY_W,              10      },\r\n    { ALLEGRO_KEY_S,              11      },\r\n    { ALLEGRO_KEY_X,              12      },\r\n    { ALLEGRO_KEY_SPACE,          13      },\r\n    { ALLEGRO_KEY_FULLSTOP,       14      }, // .\r\n    { ALLEGRO_KEY_L,              15      },\r\n    { ALLEGRO_KEY_O,              16      },\r\n    { ALLEGRO_KEY_9,              17      },\r\n    // Row: 2 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_3,              18      },\r\n    { ALLEGRO_KEY_E,              19      },\r\n    { ALLEGRO_KEY_D,              20      },\r\n    { ALLEGRO_KEY_C,              21      },\r\n    { ALLEGRO_KEY_ALTGR,          22      }, // Home Clear\r\n    { ALLEGRO_KEY_SLASH,          23      },\r\n    { ALLEGRO_KEY_SEMICOLON,      24      }, // ;\r\n  { ALLEGRO_KEY_SEMICOLON2,     24      }, // ; ++\r\n  { ALLEGRO_KEY_COLON2,         33      }, // :\r\n    { ALLEGRO_KEY_P,              25      },\r\n    { ALLEGRO_KEY_0,              26      },\r\n    // Row: 3 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_4,              27      },\r\n    { ALLEGRO_KEY_R,              28      },\r\n    { ALLEGRO_KEY_F,              29      },\r\n    { ALLEGRO_KEY_V,              30      },\r\n    { ALLEGRO_KEY_RCTRL,      31      }, // Insert/Delete\r\n    { ALLEGRO_KEY_BACKSPACE,      31      }, // Insert/Delete ++\r\n    { ALLEGRO_KEY_ABNT_C1,        32      }, // Pi\r\n    { ALLEGRO_KEY_PAD_SLASH,      32      }, // Pi ++\r\n    { ALLEGRO_KEY_BACKSLASH2,     32      }, // Pi ++\r\n    { ALLEGRO_KEY_QUOTE,          33      }, // :\r\n    { ALLEGRO_KEY_OPENBRACE,      34,     }, // @\r\n    { ALLEGRO_KEY_MINUS,          35      },\r\n    // Row: 4 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_5,              36      },\r\n    { ALLEGRO_KEY_T,              37      },\r\n    { ALLEGRO_KEY_G,              38      },\r\n    { ALLEGRO_KEY_B,              39      },\r\n    { ALLEGRO_KEY_DOWN,           40      }, // Down Arrow\r\n    { ALLEGRO_KEY_BACKSLASH,      41      }, // ]\r\n    { ALLEGRO_KEY_CLOSEBRACE,     42      }, // [\r\n    { ALLEGRO_KEY_EQUALS,         43      }, // ^\r\n    // Row: 5 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_6,              44      },\r\n    { ALLEGRO_KEY_Y,              45      },\r\n    { ALLEGRO_KEY_H,              46      },\r\n    { ALLEGRO_KEY_N,        47      },\r\n    { ALLEGRO_KEY_LEFT,           48      }, // Left Arrow\r\n    { ALLEGRO_KEY_ENTER,          49      }, // Return\r\n    { ALLEGRO_KEY_YEN,            50,     }, // Yen\r\n    { ALLEGRO_KEY_TILDE,          50,     }, // Yen ++\r\n    { ALLEGRO_KEY_TAB,            51      }, // Func\r\n    // Row: 6 -------------------------------------------------------------------\r\n    { ALLEGRO_KEY_7,              52      },\r\n    { ALLEGRO_KEY_U,              53      },\r\n    { ALLEGRO_KEY_J,              54      },\r\n    { ALLEGRO_KEY_M,              55      },\r\n    { ALLEGRO_KEY_RIGHT,          56      }, // Right Arrow\r\n    { ALLEGRO_KEY_UP,             57      }, // Up Arrow\r\n    { ALLEGRO_KEY_END,            58      }, // Break             (!!?)\r\n    { ALLEGRO_KEY_LCTRL,          59      }, // Graph\r\n    { ALLEGRO_KEY_CAPSLOCK,       60      }, // Ctrl\r\n    { ALLEGRO_KEY_LSHIFT,         61      }, // Shift\r\n    { ALLEGRO_KEY_RSHIFT,         61      }, // Shift ++\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Enable/disable SK-1100 emulation\r\nvoid    SK1100_Switch()\r\n{\r\n    Inputs.SK1100_Enabled ^= 1;\r\n    gui_menu_toggle_check (menus_ID.inputs, 7);\r\n    Skins_Background_Redraw();\r\n    gui.info.must_redraw = TRUE;\r\n    if (Inputs.SK1100_Enabled)\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_SK1100_Enabled));\r\n    else\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Inputs_SK1100_Disabled));\r\n}\r\n\r\n// Clear SK-1100 data for emulation\r\nvoid    SK1100_Clear()\r\n{\r\n    int i;\r\n    for (i = 0; i < 7; i ++)\r\n        tsms.Control [i] = 0xFFFF;\r\n}\r\n\r\n// Update SK-1100 data for emulation\r\nvoid    SK1100_Update()\r\n{\r\n    int i;\r\n    SK1100_Clear();\r\n    for (i = 0; i != SK1100_MAPPING_NUM; i ++)\r\n    {\r\n    const t_sk1100_map* k = &SK1100_Mapping[i];\r\n        if (Inputs_KeyDown(k->key_pc))\r\n        {\r\n            const t_sk1100_key *sk1100_key = &SK1100_Keys[k->key_sk1100];\r\n            tsms.Control [sk1100_key->row] &= (~sk1100_key->bit);\r\n            tsms.Control_Check_GUI = FALSE;\r\n      //Msg(MSGT_USER, \"Pressed %d -> %d\", k->key_pc, k->key_sk1100);\r\n        }\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/sk1100.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sk1100.h\n// SK-1100 (Sega Keyboard) / SC-3000 Keyboard Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    SK1100_Switch();\nvoid    SK1100_Clear();\nvoid    SK1100_Update();\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/skin.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - skin.c\n// Interface Skins - Code\n//-----------------------------------------------------------------------------\n// Note: 'skins' referred as 'themes' to user.\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"skin_bg.h\"\n#include \"libparse.h\"\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define SKIN_FADE_SPEED_DEFAULT     (1.0f / 40.0f)      // Takes 40 frames (2/3 of a second) to switch\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_skin_manager\n{\n    t_list *            skins;\n    t_skin *            skin_current;\n    bool                skin_fade;\n    float               skin_fade_pos;\n    float               skin_fade_speed;\n    t_skin *            skin_fade_from;\n    char *              skin_configuration_name;\n    ALLEGRO_BITMAP *    background_picture;\n    bool                quit_after_fade;\n};\n\nstatic t_skin_manager   Skins;\n\nstruct t_skin_color\n{\n    const char *        identifier;\n    const char *        default_identifier;\n};\n\n// Table associating skin color definitions to name\nconst t_skin_color      SkinColorData[SKIN_COLOR_MAX_] =\n{\n    { \"background_color\",                       NULL                            }, // 0\n    { \"background_grid_color\",                  \"background_color\"              },\n    { \"window_border_color\",                    NULL                            },\n    { \"window_background_color\",                NULL                            },\n    { \"window_titlebar_color\",                  NULL                            },\n    { \"window_titlebar_text_color\",             NULL                            },\n    { \"window_titlebar_text_unactive_color\",    NULL                            },\n    { \"window_text_color\",                      NULL                            },\n    { \"window_text_highlight_color\",            NULL                            },\n    { \"window_separators_color\",                \"window_border_color\"           },\n    { \"menu_background_color\",                  NULL                            }, // 10\n    { \"menu_border_color\",                      NULL                            },\n    { \"menu_selection_color\",                   NULL                            },\n    { \"menu_text_color\",                        NULL                            },\n    { \"menu_text_unactive_color\",               NULL                            },\n    { \"widget_generic_background_color\",        \"menu_background_color\"         },\n    { \"widget_generic_selection_color\",         \"menu_selection_color\"          },\n    { \"widget_generic_border_color\",            \"window_border_color\"           },\n    { \"widget_generic_text_color\",              \"window_text_highlight_color\"   },\n    { \"widget_generic_text_unactive_color\",     \"window_text_color\"             },\n    { \"widget_listbox_background_color\",        \"menu_background_color\"         }, // 20\n    { \"widget_listbox_border_color\",            \"menu_border_color\"             },\n    { \"widget_listbox_selection_color\",         \"menu_selection_color\"          },\n    { \"widget_listbox_text_color\",              \"menu_text_color\"               },\n    { \"widget_scrollbar_background_color\",      \"window_background_color\"       },\n    { \"widget_scrollbar_scroller_color\",        \"menu_selection_color\"          },\n    { \"widget_statusbar_background_color\",      \"menu_background_color\"         },\n    { \"widget_statusbar_border_color\",          \"menu_border_color\"             },\n    { \"widget_statusbar_text_color\",            \"menu_text_color\"               },\n};\n\nALLEGRO_COLOR       SkinCurrent_NativeColorTable[SKIN_COLOR_MAX_];\n\n//-----------------------------------------------------------------------------\n// Forward declaration\n//-----------------------------------------------------------------------------\n\nstatic t_skin *     Skin_New(const char *name);\nstatic void         Skin_Delete(t_skin *skin);\nstatic bool         Skin_IsValid(t_skin *skin);\n\nstatic void         Skins_UpdateNativeColorTable();\n\n//-----------------------------------------------------------------------------\n// SKIN - Functions\n//-----------------------------------------------------------------------------\n\nt_skin *    Skin_New(const char *name)\n{\n    t_skin *skin;\n    int i;\n\n    // Check parameters\n    assert(name != NULL);\n\n    // Create and setup empty skin\n    skin = (t_skin*)malloc(sizeof(t_skin));\n    skin->enabled = FALSE;\n    skin->name = strdup(name);\n    skin->authors = NULL;\n    for (i = 0; i < SKIN_COLOR_MAX_; i++)\n    {\n        skin->colors[i] = 0xFF00FF;\n        skin->colors_defined[i] = FALSE;\n    }\n    skin->effect = SKIN_EFFECT_NONE;\n\n    // Setup empty gradients\n    skin->gradient_menu.enabled = FALSE;\n    skin->gradient_menu.color_start = skin->gradient_menu.color_end = 0xFF00FF;\n    skin->gradient_menu.pos_start = skin->gradient_menu.pos_end = 100;\n    skin->gradient_window_titlebar.enabled = FALSE;\n    skin->gradient_window_titlebar.color_start = skin->gradient_window_titlebar.color_end = 0xFF00FF;\n    skin->gradient_window_titlebar.pos_start = skin->gradient_window_titlebar.pos_end = 100;\n\n    // Setup background picture\n    skin->background_picture = NULL;\n    skin->background_picture_mode = SKIN_BACKGROUND_PICTURE_MODE_DEFAULT;\n\n    return (skin);\n}\n\nvoid        Skin_Delete(t_skin *skin)\n{\n    // Check parameters\n    assert(skin != NULL);\n\n    // Delete members\n    free(skin->name);\n    if (skin->authors)\n        free(skin->authors);\n    if (skin->background_picture)\n        free(skin->background_picture);\n\n    // Delete\n    free(skin);\n}\n\nbool        Skin_IsValid(t_skin *skin)\n{\n    int     i;\n    for (i = 0; i < SKIN_COLOR_MAX_; i++)\n    {\n        if (!skin->colors_defined)\n            return false;\n    }\n    return true;\n}\n\nbool        Skin_PostProcess(t_skin *skin)\n{\n    bool valid = TRUE;\n    int i;\n\n    // Apply default colors\n    for (i = 0; i < SKIN_COLOR_MAX_; i++)\n    {\n        if (!skin->colors_defined[i])\n        {\n            if (SkinColorData[i].default_identifier != NULL)\n            {\n                // FIXME: Find index from identifier.. Ahem...\n                int identifier_idx;\n                for (identifier_idx = 0; identifier_idx < SKIN_COLOR_MAX_; identifier_idx++)\n                    if (!strcmp(SkinColorData[identifier_idx].identifier, SkinColorData[i].default_identifier))\n                    {\n                        skin->colors[i] = skin->colors[identifier_idx];\n                        skin->colors_defined[i] = skin->colors_defined[identifier_idx];\n                        break;\n                    }\n            }\n            if (!skin->colors_defined[i])\n                valid = FALSE;\n        }\n    }\n\n    // Apply gradient colors\n    skin->gradient_window_titlebar.color_start = skin->colors[COLOR_SKIN_INDEX(COLOR_SKIN_WINDOW_TITLEBAR)];\n    skin->gradient_menu.color_start            = skin->colors[COLOR_SKIN_INDEX(COLOR_SKIN_MENU_BACKGROUND)];\n    if (!skin->gradient_window_titlebar.enabled)\n        skin->gradient_window_titlebar.color_end = skin->gradient_window_titlebar.color_start;\n    if (!skin->gradient_menu.enabled)\n        skin->gradient_menu.color_end = skin->gradient_menu.color_start;\n\n    return (valid);\n}\n\n//-----------------------------------------------------------------------------\n// SKINS - Functions\n//-----------------------------------------------------------------------------\n\nvoid        Skins_Init_Values()\n{\n    Skins.skin_configuration_name = NULL;\n}\n\n// Initialize skin system\nvoid        Skins_Init()\n{\n    t_skin *skin_first_valid = NULL;\n\n    Skins.skins                 = NULL;\n    Skins.skin_current          = NULL;    // To be set before running program\n    Skins.skin_fade             = FALSE;\n    Skins.skin_fade_pos         = 0.0f;\n    Skins.skin_fade_speed       = SKIN_FADE_SPEED_DEFAULT;\n    Skins.skin_fade_from        = NULL;\n    Skins.background_picture    = NULL;\n    Skins.quit_after_fade       = FALSE;\n\n    // Load skins from MEKA.THM file\n    Skins_Load(g_env.Paths.SkinFile);\n\n    // Post process skins and verify skin validity (all colors sets, etc)\n    {\n        t_list *skins;\n        for (skins = Skins.skins; skins != NULL; skins = skins->next)\n        {\n            t_skin* skin = (t_skin*)skins->elem;\n            Skin_PostProcess(skin);\n            if (Skin_IsValid(skin))\n            {\n                skin->enabled = TRUE;\n                if (!skin_first_valid)\n                    skin_first_valid = skin;\n            }\n            else\n            {\n                skin->enabled = FALSE;\n                ConsolePrintf(Msg_Get(MSG_Theme_Error_Theme_Missing_Data), skin->name);\n                ConsoleEnablePause();\n            }\n        }\n    }\n\n    // Verify that we have at least 1 loaded skin\n    if (skin_first_valid == NULL)\n        Quit_Msg(\"%s\", Msg_Get(MSG_Theme_Error_Not_Enough));\n\n    // Set current skin\n    Skins.skin_current = NULL;\n    if (Skins.skin_configuration_name != NULL)\n        Skins.skin_current = Skins_FindSkinByName(Skins.skin_configuration_name);\n    if (Skins.skin_current == NULL)\n        Skins.skin_current = skin_first_valid;\n}\n\nstatic int  Skins_ParseGradient(char *line, t_skin_gradient *gradient)\n{\n    u32 color_end;\n    int pos_start, pos_end;\n    char value[256];\n\n    if (gradient->enabled)\n        return MEKA_ERR_ALREADY_DEFINED;\n    if (!parse_getword(value, sizeof(value), &line, \"\", ';', PARSE_FLAGS_NONE))\n        return MEKA_ERR_SYNTAX;\n    if (sscanf(value, \"%d%%-%d%% #%06x\", &pos_start, &pos_end, &color_end) != 3)\n        return MEKA_ERR_SYNTAX;\n    if (pos_start < 0 || pos_start > 100 || pos_end < 0 || pos_end > 100 || pos_end < pos_start)\n        return MEKA_ERR_VALUE_OUT_OF_BOUND;\n    gradient->enabled       = TRUE;\n    gradient->color_end     = color_end;\n    gradient->pos_start     = pos_start;\n    gradient->pos_end       = pos_end;\n    return MEKA_ERR_OK;\n}\n\nstatic int  Skins_ParseLine(char *line)\n{\n    if (line[0] == '[')\n    {\n        line++;\n\n        // Get name\n        char skin_name[256];\n        if (!parse_getword(skin_name, sizeof(skin_name), &line, \"]\", ';', PARSE_FLAGS_DONT_EAT_SEPARATORS))\n            return MEKA_ERR_SYNTAX;\n        if (*line != ']')\n            return MEKA_ERR_SYNTAX;\n\n        // Create new skin\n        t_skin* skin = Skin_New(skin_name);\n        list_add(&Skins.skins, skin);\n        Skins.skin_current = skin;\n        return MEKA_ERR_OK;\n    }\n    else\n    {\n        t_skin *skin = Skins.skin_current;\n\n        // Read line\n        char var[256];\n        char value[256];\n        if (!parse_getword(var, sizeof(var), &line, \"=\", ';', PARSE_FLAGS_NONE))\n            return MEKA_ERR_OK;\n        parse_skip_spaces(&line);\n\n        if (!skin)\n            return MEKA_ERR_MISSING;\n\n        // Check if it's a skin color\n        int i;\n        for (i = 0; i < SKIN_COLOR_MAX_; i++)\n            if (strcmp(var, SkinColorData[i].identifier) == 0)\n                break;\n        if (i != SKIN_COLOR_MAX_)\n        {\n            // Got a color attributes\n            u32 color;\n            if (skin->colors_defined[i])\n                return MEKA_ERR_ALREADY_DEFINED;\n            if (!parse_getword(value, sizeof(value), &line, \"\", ';', PARSE_FLAGS_NONE))\n                return MEKA_ERR_SYNTAX;\n            if (sscanf(value, \"#%06x\", &color) != 1)\n                return MEKA_ERR_SYNTAX;\n            skin->colors[i] = color;\n            skin->colors_defined[i] = TRUE;\n            return MEKA_ERR_OK;\n        }\n\n        // Another type of attribute, check them manually\n\n        // - Authors\n        if (strcmp(var, \"authors\") == 0)\n        {\n            if (skin->authors != NULL)\n                return MEKA_ERR_ALREADY_DEFINED;\n            if (!parse_getword(value, sizeof(value), &line, \"\", ';', PARSE_FLAGS_NONE))\n                return MEKA_ERR_SYNTAX;\n            skin->authors = strdup(value);\n            return MEKA_ERR_OK;\n        }\n\n        // - Comments\n        if (strcmp(var, \"comments\") == 0)\n        {\n            // Currently ignored\n            return MEKA_ERR_OK;\n        }\n\n        // - Background Picture\n        if (strcmp(var, \"background_picture\") == 0)\n        {\n            if (skin->background_picture != NULL)\n                return MEKA_ERR_ALREADY_DEFINED;\n            line = strchr(line, '\\\"');\n            if (!line)\n                return MEKA_ERR_SYNTAX;\n            line++;\n            if (!parse_getword(value, sizeof(value), &line, \"\\\"\", ';', PARSE_FLAGS_NONE))\n                return MEKA_ERR_SYNTAX;\n            line++;\n            skin->background_picture = strdup(value);\n            if (parse_getword(value, sizeof(value), &line, \" \\t\", ';', PARSE_FLAGS_NONE))\n            {\n                if (!strcmp(value, \"center\"))\n                    skin->background_picture_mode = SKIN_BACKGROUND_PICTURE_MODE_CENTER;\n                else if (!strcmp(value, \"stretch\"))\n                    skin->background_picture_mode = SKIN_BACKGROUND_PICTURE_MODE_STRETCH;\n                else if (!strcmp(value, \"stretch_int\"))\n                    skin->background_picture_mode = SKIN_BACKGROUND_PICTURE_MODE_STRETCH_INT;\n                else if (!strcmp(value, \"tile\"))\n                    skin->background_picture_mode = SKIN_BACKGROUND_PICTURE_MODE_TILE;\n                else\n                    return MEKA_ERR_SYNTAX;\n            }\n            return MEKA_ERR_OK;\n        }\n\n        // - Window TitleBar Gradient\n        if (strcmp(var, \"window_titlebar_gradient\") == 0)\n            return Skins_ParseGradient(line, &skin->gradient_window_titlebar);\n\n        // - Menu Gradient\n        if (strcmp(var, \"menu_gradient\") == 0)\n            return Skins_ParseGradient(line, &skin->gradient_menu);\n\n        // - Effect\n        if (strcmp(var, \"effect\") == 0)\n        {\n            if (skin->effect != SKIN_EFFECT_NONE)\n                return MEKA_ERR_ALREADY_DEFINED;\n            if (!parse_getword(value, sizeof(value), &line, \"\", ';', PARSE_FLAGS_NONE))\n                return MEKA_ERR_SYNTAX;\n            if (!strcmp(value, \"none\"))\n                skin->effect = SKIN_EFFECT_NONE;\n            else if (!strcmp(value, \"blood\"))\n                skin->effect = SKIN_EFFECT_BLOOD;\n            else if (!strcmp(value, \"hearts\"))\n                skin->effect = SKIN_EFFECT_HEARTS;\n            else\n                return MEKA_ERR_SYNTAX;\n            return MEKA_ERR_OK;\n        }\n\n        // FIXME\n        return MEKA_ERR_SYNTAX;\n        //return MEKA_ERR_OK;\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Skins_Load(const char *filename)\n// Load given Meka Skin file\n//-----------------------------------------------------------------------------\nvoid        Skins_Load(const char *filename)\n{\n    ConsolePrint(Msg_Get(MSG_Theme_Loading));\n\n    // Open and read file\n    t_tfile* tf;\n    tf = tfile_read(filename);\n    if (tf == NULL)\n    {\n        ConsolePrintf (\"%s\\n\", meka_strerror());\n        return;\n    }\n\n    // Ok\n    ConsolePrint(\"\\n\");\n\n    // Parse each line\n    int line_cnt = 0;\n    for (t_list* lines = tf->data_lines; lines; lines = lines->next)\n    {\n        char* line = (char*)lines->elem;\n        line_cnt += 1;\n        switch (Skins_ParseLine(line))\n        {\n        case MEKA_ERR_SYNTAX:\n            tfile_free(tf); \n            Quit_Msg(Msg_Get(MSG_Theme_Error_Syntax), line_cnt);\n            break;\n        case MEKA_ERR_MISSING:\n            tfile_free(tf); \n            Quit_Msg(Msg_Get(MSG_Theme_Error_Missing_Theme_Name), line_cnt);\n            break;\n        case MEKA_ERR_ALREADY_DEFINED:\n            tfile_free(tf);\n            Quit_Msg(Msg_Get(MSG_Theme_Error_Attribute_Defined), line_cnt);\n            break;\n        case MEKA_ERR_VALUE_OUT_OF_BOUND:\n            tfile_free(tf);\n            Quit_Msg(Msg_Get(MSG_Theme_Error_Out_of_Bound), line_cnt);\n            break;\n        }\n    }\n\n    // Reverse list\n    list_reverse(&Skins.skins);\n    Skins.skin_current = NULL;\n\n    // Free file data\n    tfile_free(tf);\n}\n\nvoid        Skins_Close()\n{\n    // Free all strings\n    list_free_custom (&Skins.skins, (t_list_free_handler)Skin_Delete);\n    free(Skins.skin_configuration_name);\n    Skins.skins = NULL;\n    Skins.skin_current = NULL;\n}\n\nvoid        Skins_SetSkinConfiguration(const char *skin_name)\n{\n    if (Skins.skin_configuration_name != NULL)\n        free(Skins.skin_configuration_name);\n    Skins.skin_configuration_name = strdup(skin_name);\n}\n\nt_skin *    Skins_FindSkinByName(const char *skin_name)\n{\n    for (t_list* skins = Skins.skins; skins != NULL; skins = skins->next)\n    {\n        t_skin* skin = (t_skin*)skins->elem;\n        if (skin->enabled && stricmp(skin_name, skin->name) == 0)\n            return (skin);\n    }\n    return (NULL);\n}\n\nvoid        Skins_Apply()\n{\n    // Update native color table\n    Skins_UpdateNativeColorTable();\n\n    // Dirty\n    gui.info.must_redraw = TRUE;\n    Skins_Background_Redraw();\n\n    // Layout all boxes\n    gui_relayout_all();\n}\n\nvoid        Skins_StartupFadeIn()\n{\n    // Setup fade-in from black, or using some special effect?\n    t_skin *skin = Skins.skin_current;\n    Skins.skin_current = NULL;\n    Skins_Select(skin, FALSE);\n    Skins_Apply();\n}\n\nvoid        Skins_Select(t_skin *skin, bool fade)\n{\n    if (skin == Skins.skin_current)\n        return;\n\n    // Setup fade\n    if (fade)\n    {\n        Skins.skin_fade         = TRUE;\n        Skins.skin_fade_pos     = 0.0f;\n        Skins.skin_fade_speed   = SKIN_FADE_SPEED_DEFAULT;\n        Skins.skin_fade_from    = Skins.skin_current;\n    }\n    Skins.skin_current = skin;\n\n    // Load background picture, if any\n    if (Skins.background_picture != NULL)\n    {\n        al_destroy_bitmap(Skins.background_picture);\n        Skins.background_picture = NULL;\n    }\n    if (Skins.skin_current->background_picture != NULL)\n    {\n        char filename[FILENAME_LEN];\n        sprintf(filename, \"%s/%s\", g_env.Paths.EmulatorDirectory, Skins.skin_current->background_picture);\n        Skins.background_picture = al_load_bitmap(filename);\n        if (Skins.background_picture == NULL)\n        {\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Theme_Error_BG));\n            Msg(MSGT_USER_LOG, Msg_Get(MSG_Theme_Error_BG_FileName), Skins.skin_current->background_picture);\n        }\n    }\n}\n\nvoid        Skins_Update()\n{\n    //{\n    //    char buf[128];\n    //    sprintf(buf, \"Skin %p %p\", Skins.skin_current->colors[0], SkinCurrent_NativeColorTable[0]);\n    //    Font_Print(F_LARGE, gui_buffer, buf, 20, 20, COLOR_WHITE);\n    //}\n\n    // Update fade (if any)\n    if (Skins.skin_fade)\n    {\n        Skins.skin_fade_pos += Skins.skin_fade_speed;\n        if (Skins.skin_fade_pos >= 1.0f)\n        {\n            Skins.skin_fade = FALSE;\n            Skins.skin_fade_pos = 1.0f;\n        }\n        Skins_Apply();\n    }\n\n    // Quit after fade\n    if (Skins.quit_after_fade && !Skins.skin_fade)\n        opt.Force_Quit = TRUE;\n}\n\n//-----------------------------------------------------------------------------\n\nstatic ALLEGRO_COLOR Skins_ColorBlendToNative(u32 color1, u32 color2, float fact1, float fact2)\n{\n    const int r1 = (color1 & 0x00FF0000) >> 16;\n    const int g1 = (color1 & 0x0000FF00) >> 8;\n    const int b1 = (color1 & 0x000000FF) >> 0;\n    const int r2 = (color2 & 0x00FF0000) >> 16;\n    const int g2 = (color2 & 0x0000FF00) >> 8;\n    const int b2 = (color2 & 0x000000FF) >> 0;\n    const int r  = (fact1 * r1) + (fact2 * r2);\n    const int g  = (fact1 * g1) + (fact2 * g2);\n    const int b  = (fact1 * b1) + (fact2 * b2);\n    assert(r >= 0 && r <= 255);\n    assert(g >= 0 && g <= 255);\n    assert(b >= 0 && b <= 255);\n    return al_map_rgb(r, g, b);\n}\n\nstatic u32  Skins_ColorBlend(u32 color1, u32 color2, float fact1, float fact2)\n{\n    const int r1 = (color1 & 0x00FF0000) >> 16;\n    const int g1 = (color1 & 0x0000FF00) >> 8;\n    const int b1 = (color1 & 0x000000FF) >> 0;\n    const int r2 = (color2 & 0x00FF0000) >> 16;\n    const int g2 = (color2 & 0x0000FF00) >> 8;\n    const int b2 = (color2 & 0x000000FF) >> 0;\n    const int r  = (fact1 * r1) + (fact2 * r2);\n    const int g  = (fact1 * g1) + (fact2 * g2);\n    const int b  = (fact1 * b1) + (fact2 * b2);\n    assert(r >= 0 && r <= 255);\n    assert(g >= 0 && g <= 255);\n    assert(b >= 0 && b <= 255);\n    return (r << 16) | (g << 8) | (b);\n}\n\nstatic ALLEGRO_COLOR Skins_ColorToNative(u32 color)\n{\n    const int r = (color & 0x00FF0000) >> 16;\n    const int g = (color & 0x0000FF00) >> 8;\n    const int b = (color & 0x000000FF) >> 0;\n    return al_map_rgb(r, g, b);\n}\n\nstatic void Skins_UpdateNativeGradient(t_skin_gradient *gradient, u32 color_start, u32 color_end)\n{\n    gradient->native_color_start    = Skins_ColorToNative(color_start);\n    gradient->native_color_end      = Skins_ColorToNative(color_end);\n    for (int i = 0; i < SKIN_GRADIENT_NATIVE_COLOR_BUFFER_SIZE; i++)\n    {\n        const float fact2 = (float)i / (float)(SKIN_GRADIENT_NATIVE_COLOR_BUFFER_SIZE - 1);\n        const float fact1 = 1.0f - fact2;\n        gradient->native_color_buffer[i] = Skins_ColorBlendToNative(color_start, color_end, fact1, fact2);\n    }\n}\n\nstatic void Skins_UpdateNativeColorTable()\n{\n    int     i;\n    t_skin *skin = Skins.skin_current;\n    assert(skin != NULL);\n\n    if (Skins.skin_fade)\n    {\n        // Blend colors when fading\n        const float fact1 = Skins.skin_fade_pos;\n        const float fact2 = 1.0f - fact1;\n        const t_skin *skin1 = skin;\n        const t_skin *skin2 = Skins.skin_fade_from;\n\n        // Update main colors\n        for (i = 0; i < SKIN_COLOR_MAX_; i++)\n            SkinCurrent_NativeColorTable[i] = Skins_ColorBlendToNative(skin1->colors[i], skin2->colors[i], fact1, fact2);\n\n        // Update gradient data\n        Skins_UpdateNativeGradient(&skin->gradient_menu, \n            Skins_ColorBlend(skin1->gradient_menu.color_start, skin2->gradient_menu.color_start, fact1, fact2),\n            Skins_ColorBlend(skin1->gradient_menu.color_end,   skin2->gradient_menu.color_end,   fact1, fact2));\n        Skins_UpdateNativeGradient(&skin->gradient_window_titlebar, \n            Skins_ColorBlend(skin1->gradient_window_titlebar.color_start, skin2->gradient_window_titlebar.color_start, fact1, fact2),\n            Skins_ColorBlend(skin1->gradient_window_titlebar.color_end,   skin2->gradient_window_titlebar.color_end,   fact1, fact2));\n    }\n    else\n    {\n        // Update main colors\n        for (i = 0; i < SKIN_COLOR_MAX_; i++)\n            SkinCurrent_NativeColorTable[i] = Skins_ColorToNative(skin->colors[i]);\n\n        // Update gradient data\n        Skins_UpdateNativeGradient(&skin->gradient_menu, skin->gradient_menu.color_start, skin->gradient_menu.color_end);\n        Skins_UpdateNativeGradient(&skin->gradient_window_titlebar, skin->gradient_window_titlebar.color_start, skin->gradient_window_titlebar.color_end);\n    }\n}\n\nstatic void Skins_MenuHandlerSelectSkin(t_menu_event *event)\n{\n    // Switch smoothly to new theme\n    t_skin* skin = (t_skin*)event->user_data;\n    Skins_Select(skin, TRUE);\n    Skins_Apply();\n\n    // Check new selected theme in menu\n    gui_menu_uncheck_all (menus_ID.themes);\n    gui_menu_check (menus_ID.themes, event->menu_item_idx);\n}\n\nvoid        Skins_MenuInit(int menu_id)\n{\n    for (t_list* skins = Skins.skins; skins != NULL; skins = skins->next)\n    {\n        t_skin* skin = (t_skin*)skins->elem;\n        if (skin->enabled)\n        {\n            menu_add_item(menu_id, skin->name, NULL,\n                MENU_ITEM_FLAG_ACTIVE | ((Skins.skin_current == skin) ? MENU_ITEM_FLAG_CHECKED : 0),\n                (t_menu_callback)Skins_MenuHandlerSelectSkin, skin);\n        }\n    }\n}\n\nvoid        Skins_QuitAfterFade()\n{\n    Skins.quit_after_fade = TRUE;\n}\n\nt_skin *    Skins_GetCurrentSkin()\n{\n    return Skins.skin_current;\n}\n\nALLEGRO_BITMAP *    Skins_GetBackgroundPicture()\n{\n    return Skins.background_picture;\n}\n\n//-----------------------------------------------------------------------------\n// Functions - Gradients\n//-----------------------------------------------------------------------------\n\nvoid    SkinGradient_DrawHorizontal(t_skin_gradient *gradient, ALLEGRO_BITMAP *bitmap, t_frame *frame)\n{\n    const int x1 = frame->pos.x;\n    const int y1 = frame->pos.y;\n    const int x2 = frame->pos.x + frame->size.x;\n    const int y2 = frame->pos.y + frame->size.y;\n\n    if (!gradient->enabled)\n    {\n        // Fill with start color\n        al_set_target_bitmap(bitmap);\n        al_draw_filled_rectangle(x1, y1, x2+1, y2+1, gradient->native_color_start);\n    }\n    else\n    {\n        // Draw gradient\n        const int gradient_pos_start = ((x2 - x1) * gradient->pos_start) / 100;\n        const int gradient_pos_end   = ((x2 - x1) * gradient->pos_end)   / 100;\n        const int gradient_size      = gradient_pos_end - gradient_pos_start;\n        al_set_target_bitmap(bitmap);\n        if (gradient_pos_start != 0)\n            al_draw_filled_rectangle(x1, y1+0.5f, x1 + gradient_pos_start + 1, y2+1.5f, gradient->native_color_start);\n        if ( gradient_size > 0 )\n        {\n            for (int n = 0; n <= gradient_size; n++)\n            {\n                const int gradient_idx = n * (SKIN_GRADIENT_NATIVE_COLOR_BUFFER_SIZE - 1) / gradient_size;\n                const int x = x1 + n + gradient_pos_start;\n                const ALLEGRO_COLOR color = gradient->native_color_buffer[gradient_idx];\n                al_draw_line(x+0.5f, y1+0.5f, x+0.5f, y2+1.5f, color, 0.0f);\n            }\n        }\n        if (gradient_pos_end < frame->size.x+1)\n            al_draw_filled_rectangle(x1 + gradient_pos_end, y1+0.5f, x2+1, y2+1.5f, gradient->native_color_end);\n    }\n}\n\nvoid    SkinGradient_DrawVertical(t_skin_gradient *gradient, ALLEGRO_BITMAP *bitmap, t_frame *frame)\n{\n    const int x1 = frame->pos.x;\n    const int y1 = frame->pos.y;\n    const int x2 = frame->pos.x + frame->size.x;\n    const int y2 = frame->pos.y + frame->size.y;\n\n    al_set_target_bitmap(bitmap);\n    if (!gradient->enabled)\n    {\n        // Fill with start color\n        al_draw_filled_rectangle(x1, y1, x2+1, y2+1, gradient->native_color_start);\n    }\n    else\n    {\n        // Draw gradient\n        const int gradient_pos_start = ((y2 - y1) * gradient->pos_start) / 100;\n        const int gradient_pos_end   = ((y2 - y1) * gradient->pos_end)   / 100;\n        const int gradient_size      = gradient_pos_end - gradient_pos_start;\n        if (gradient_pos_start != 0)\n            al_draw_filled_rectangle(x1, y1, x2 + 1, y1 + gradient_pos_start + 1, gradient->native_color_start);\n        if ( gradient_size > 0 )\n        {\n            for (int n = 0; n <= gradient_size; n++)\n            {\n                const int gradient_idx = n * (SKIN_GRADIENT_NATIVE_COLOR_BUFFER_SIZE - 1) / gradient_size;\n                const int y = y1 + n + gradient_pos_start;\n                const ALLEGRO_COLOR color = gradient->native_color_buffer[gradient_idx];\n                al_draw_hline(x1, y, x2, color);\n            }\n        }\n        if (gradient_pos_end < frame->size.y+1)\n            al_draw_filled_rectangle(x1, y1 + gradient_pos_end, x2 + 1, y2 + 1, gradient->native_color_end);\n    }\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/skin.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - skin.h\n// Interface Skins - Headers\n//-----------------------------------------------------------------------------\n// Note: 'skins' referred as 'themes' to user.\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n// User definitions\n#define COLOR_SKIN_BACKGROUND                       SkinCurrent_NativeColorTable[0]\n#define COLOR_SKIN_BACKGROUND_GRID                  SkinCurrent_NativeColorTable[1]\n#define COLOR_SKIN_WINDOW_BORDER                    SkinCurrent_NativeColorTable[2]\n#define COLOR_SKIN_WINDOW_BACKGROUND                SkinCurrent_NativeColorTable[3]\n#define COLOR_SKIN_WINDOW_TITLEBAR                  SkinCurrent_NativeColorTable[4]\n#define COLOR_SKIN_WINDOW_TITLEBAR_TEXT             SkinCurrent_NativeColorTable[5]\n#define COLOR_SKIN_WINDOW_TITLEBAR_TEXT_UNACTIVE    SkinCurrent_NativeColorTable[6]\n#define COLOR_SKIN_WINDOW_TEXT                      SkinCurrent_NativeColorTable[7]\n#define COLOR_SKIN_WINDOW_TEXT_HIGHLIGHT            SkinCurrent_NativeColorTable[8]\n#define COLOR_SKIN_WINDOW_SEPARATORS                SkinCurrent_NativeColorTable[9]\n#define COLOR_SKIN_MENU_BACKGROUND                  SkinCurrent_NativeColorTable[10]\n#define COLOR_SKIN_MENU_BORDER                      SkinCurrent_NativeColorTable[11]\n#define COLOR_SKIN_MENU_SELECTION                   SkinCurrent_NativeColorTable[12]\n#define COLOR_SKIN_MENU_TEXT                        SkinCurrent_NativeColorTable[13]\n#define COLOR_SKIN_MENU_TEXT_UNACTIVE               SkinCurrent_NativeColorTable[14]\n#define COLOR_SKIN_WIDGET_GENERIC_BACKGROUND        SkinCurrent_NativeColorTable[15]\n#define COLOR_SKIN_WIDGET_GENERIC_SELECTION         SkinCurrent_NativeColorTable[16]\n#define COLOR_SKIN_WIDGET_GENERIC_BORDER            SkinCurrent_NativeColorTable[17]\n#define COLOR_SKIN_WIDGET_GENERIC_TEXT              SkinCurrent_NativeColorTable[18]\n#define COLOR_SKIN_WIDGET_GENERIC_TEXT_UNACTIVE     SkinCurrent_NativeColorTable[19]\n#define COLOR_SKIN_WIDGET_LISTBOX_BACKGROUND        SkinCurrent_NativeColorTable[20]\n#define COLOR_SKIN_WIDGET_LISTBOX_BORDER            SkinCurrent_NativeColorTable[21]\n#define COLOR_SKIN_WIDGET_LISTBOX_SELECTION         SkinCurrent_NativeColorTable[22]\n#define COLOR_SKIN_WIDGET_LISTBOX_TEXT              SkinCurrent_NativeColorTable[23]\n#define COLOR_SKIN_WIDGET_SCROLLBAR_BACKGROUND      SkinCurrent_NativeColorTable[24]\n#define COLOR_SKIN_WIDGET_SCROLLBAR_SCROLLER        SkinCurrent_NativeColorTable[25]\n#define COLOR_SKIN_WIDGET_STATUSBAR_BACKGROUND      SkinCurrent_NativeColorTable[26]\n#define COLOR_SKIN_WIDGET_STATUSBAR_BORDER          SkinCurrent_NativeColorTable[27]\n#define COLOR_SKIN_WIDGET_STATUSBAR_TEXT            SkinCurrent_NativeColorTable[28]\n\n#define COLOR_SKIN_INDEX(_COLOR)                    ((int)(&_COLOR - &SkinCurrent_NativeColorTable[0]))\n\n#define SKIN_COLOR_MAX_                             29\n\n#define SKIN_GRADIENT_NATIVE_COLOR_BUFFER_SIZE      (256)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nextern ALLEGRO_COLOR    SkinCurrent_NativeColorTable[SKIN_COLOR_MAX_];\n\nstruct t_skin_gradient\n{\n    bool                enabled;            // if not enabled, fill with native_gradient_start[0]\n    int                 pos_start;          // 0-100%\n    int                 pos_end;            // 0-100%, >= pos_start\n    u32                 color_start;\n    u32                 color_end;\n    ALLEGRO_COLOR       native_color_start;\n    ALLEGRO_COLOR       native_color_end;\n    ALLEGRO_COLOR       native_color_buffer[SKIN_GRADIENT_NATIVE_COLOR_BUFFER_SIZE];\n};\n\nenum t_skin_effect\n{\n    SKIN_EFFECT_NONE    = 0,\n    SKIN_EFFECT_BLOOD   = 1,\n    SKIN_EFFECT_HEARTS  = 2,\n};\n\nenum t_skin_background_picture_mode\n{\n    SKIN_BACKGROUND_PICTURE_MODE_CENTER         = 0,\n    SKIN_BACKGROUND_PICTURE_MODE_STRETCH        = 1,\n    SKIN_BACKGROUND_PICTURE_MODE_STRETCH_INT    = 2,\n    SKIN_BACKGROUND_PICTURE_MODE_TILE           = 3,\n    SKIN_BACKGROUND_PICTURE_MODE_DEFAULT        = SKIN_BACKGROUND_PICTURE_MODE_STRETCH,\n};\n\nstruct t_skin\n{\n    bool                            enabled;\n    char *                          name;\n    char *                          authors;\n    u32                             colors[SKIN_COLOR_MAX_];\n    bool                            colors_defined[SKIN_COLOR_MAX_];\n    t_skin_gradient                 gradient_window_titlebar;\n    t_skin_gradient                 gradient_menu;\n    t_skin_effect                   effect;\n    char *                          background_picture;\n    t_skin_background_picture_mode  background_picture_mode;\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid                Skins_Init_Values               ();\nvoid                Skins_Init                      ();\nvoid                Skins_Load                      (const char *filename);\nvoid                Skins_Close                     ();\n\nvoid                Skins_StartupFadeIn             ();\nvoid                Skins_Apply                     ();\nvoid                Skins_Update                    ();\nvoid                Skins_MenuInit                  (int menu_id);\nvoid                Skins_Select                    (t_skin *skin, bool fade);\n\nvoid                Skins_QuitAfterFade             ();\n\nvoid                Skins_SetSkinConfiguration      (const char *skin_name);\n\nt_skin *            Skins_GetCurrentSkin            ();\nt_skin *            Skins_FindSkinByName            (const char *skin_name);\nALLEGRO_BITMAP *    Skins_GetBackgroundPicture      ();\n\n//-----------------------------------------------------------------------------\n\nvoid                SkinGradient_DrawHorizontal(t_skin_gradient *gradient, ALLEGRO_BITMAP *bitmap, t_frame *frame);\nvoid                SkinGradient_DrawVertical(t_skin_gradient *gradient, ALLEGRO_BITMAP *bitmap, t_frame *frame);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/skin_bg.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - themes_b.c\r\n// Interface - Background Refresh - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"skin_bg.h\"\r\n#include \"vmachine.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     Skins_Background_Redraw_Grid()\r\n{\r\n    al_clear_to_color(COLOR_SKIN_BACKGROUND);\r\n\r\n    // Draw grid\r\n    if (!alx_color_equals(&COLOR_SKIN_BACKGROUND_GRID, &COLOR_SKIN_BACKGROUND) && \r\n        gui.info.grid_distance > 0)\r\n    {\r\n        int i;\r\n        const ALLEGRO_COLOR color = COLOR_SKIN_BACKGROUND_GRID;\r\n        for (i = gui.info.grid_distance; i < gui.info.screen.y; i += gui.info.grid_distance)\r\n            al_draw_line(0, i, gui.info.screen.x, i, color, 0);\r\n        for (i = gui.info.grid_distance; i < gui.info.screen.x; i += gui.info.grid_distance)\r\n            al_draw_line(i, 0, i, gui.info.screen.y, color, 0);\r\n    }\r\n}\r\n\r\nstatic void     Skins_Background_Draw_Tile(ALLEGRO_BITMAP *bmp)\r\n{\r\n    int     sx, sy;\r\n    int     cx, cy;\r\n\r\n    sx = al_get_bitmap_width(bmp);\r\n    sy = al_get_bitmap_height(bmp);\r\n    cy = 0;\r\n    while (cy < gui.info.screen.y)\r\n    {\r\n        cx = 0;\r\n        while (cx < gui.info.screen.x)\r\n        {\r\n            al_draw_bitmap(bmp, cx, cy, 0);\r\n            cx += sx;\r\n        }\r\n        cy += sy;\r\n    }\r\n}\r\n\r\nstatic void     Skins_Background_Draw_Stretch(ALLEGRO_BITMAP *bmp)\r\n{\r\n    al_draw_scaled_bitmap(bmp, \r\n        0.0f, 0.0f, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp),\r\n        0, gui.info.bars_height + 2,\r\n        gui.info.screen.x, gui.info.screen.y - 2 * (gui.info.bars_height + 2),\r\n        0);\r\n}\r\n\r\nstatic void     Skins_Background_Draw_StretchInteger(ALLEGRO_BITMAP *bmp)\r\n{\r\n    int         size_x;\r\n    int         size_y;\r\n    int         factor = 0;\r\n\r\n    // Find best fit factor\r\n    const int w = al_get_bitmap_width(bmp);\r\n    const int h = al_get_bitmap_height(bmp);\r\n    do\r\n    {\r\n        factor += 1;\r\n        size_x = (gui.info.screen.x - w * factor) / 2;\r\n        size_y = (gui.info.screen.y - 2 * (gui.info.bars_height + 2) - h * factor) / 2;\r\n    }\r\n    while (size_x >= 0 && size_y >= 0);\r\n    factor -= 1;\r\n\r\n    // Draw grid\r\n    Skins_Background_Redraw_Grid();\r\n\r\n    if (factor == 0)\r\n    {\r\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Theme_Error_BG_Big));\r\n        return;\r\n    }\r\n\r\n    {\r\n        int sx = (gui.info.screen.x - w * factor) / 2;\r\n        int sy = (gui.info.screen.y - 2 * (gui.info.bars_height + 2) - h * factor) / 2;\r\n        sy += gui.info.bars_height + 2;\r\n        al_draw_scaled_bitmap(bmp, 0, 0, w, h, sx, sy, w * factor, h * factor, 0x0000);\r\n    }\r\n}\r\n\r\nstatic void     Skins_Background_Draw_Center(ALLEGRO_BITMAP *bmp)\r\n{\r\n    const int   pos_x = (gui.info.screen.x - al_get_bitmap_width(bmp)) >> 1;\r\n    const int   pos_y = (gui.info.screen.y - al_get_bitmap_height(bmp)) >> 1;\r\n    Skins_Background_Redraw_Grid();\r\n    al_draw_bitmap(bmp, pos_x, pos_y, 0x0000);\r\n}\r\n\r\n\r\nvoid    Skins_Background_Redraw()\r\n{\r\n#ifdef DEBUG_WHOLE\r\n    Msg(MSGT_DEBUG, \"Skins_Background_Redraw();\");\r\n#endif\r\n\r\n    gui.info.must_redraw = TRUE;\r\n    \r\n    al_set_target_bitmap(gui_background);\r\n\r\n    t_skin* skin = Skins_GetCurrentSkin();\r\n    ALLEGRO_BITMAP* background = Skins_GetBackgroundPicture();\r\n    if (background != NULL)\r\n    {\r\n        switch (skin->background_picture_mode)\r\n        {\r\n        case SKIN_BACKGROUND_PICTURE_MODE_CENTER:\r\n            Skins_Background_Draw_Center(background);\r\n            break;\r\n        case SKIN_BACKGROUND_PICTURE_MODE_STRETCH:\r\n            Skins_Background_Draw_Stretch(background);\r\n            break;\r\n        case SKIN_BACKGROUND_PICTURE_MODE_STRETCH_INT:\r\n            Skins_Background_Draw_StretchInteger(background);\r\n            break;\r\n        case SKIN_BACKGROUND_PICTURE_MODE_TILE:\r\n            Skins_Background_Draw_Tile(background);\r\n            break;\r\n        default:\r\n            //assert(0);\r\n            Skins_Background_Draw_Stretch(background);\r\n            break;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        Skins_Background_Redraw_Grid();\r\n        VMachine_Draw();\r\n    }\r\n\r\n    // Draw SK-1100 centered on bottom\r\n    if (Inputs.SK1100_Enabled)\r\n    {\r\n        ALLEGRO_BITMAP *bmp = Graphics.Inputs.SK1100_Keyboard;\r\n        al_draw_bitmap(bmp,\r\n            (gui.info.screen.x - al_get_bitmap_width(bmp)) / 2,\r\n            (gui.info.screen.y - al_get_bitmap_height(bmp) - 40), 0x0000);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/skin_bg.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - skin_bg.h\n// Interface - Background Refresh - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Skins_Background_Redraw();\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/skin_fx.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - skin_fx.c\r\n// Special effects - Code\r\n// was: Bloodlust theme                                          B.elieve\r\n//-----------------------------------------------------------------------------\r\n// FIXME: Super old code, terrible. Don't look! Close your eyes! Leave now!\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"skin_fx.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n#define MAX_BLOOD_DROP          (500)\r\n#define MAX_HEARTS              (16)\r\n\r\nstruct t_skinfx_particle\r\n{\r\n    int   v;            // 0: not active, 1->4: active\r\n    float x, y;\r\n    float ix, iy;       // Initial position\r\n    float vx, vy;       // Velocity\r\n    float sin_amp;\r\n    float sin_phase;\r\n    float sin_speed;\r\n    ALLEGRO_COLOR save; // Backup of pixel\r\n};\r\n\r\nstatic ALLEGRO_BITMAP *     hearts_save[MAX_HEARTS];\r\nstatic t_skinfx_particle    g_skinfx_particles[MAX_BLOOD_DROP];\r\nstatic int                  g_skinfx_particles_next_spawn;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void gui_applet_blood_create (int v, int x, int y);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n\r\nvoid SkinFx_Init()\r\n{\r\n    g_skinfx_particles_next_spawn = 0;\r\n    for (int i = 0; i != MAX_BLOOD_DROP; i ++)\r\n        gui_applet_blood_create(0, 0, 0);\r\n    for (int i = 0; i != MAX_HEARTS; i ++)\r\n        hearts_save [i] = NULL;\r\n}\r\n\r\nvoid SkinFx_CreateVideoBuffers()\r\n{\r\n    SkinFx_DestroyVideoBuffers();\r\n\r\n    const int hw = al_get_bitmap_width(Graphics.Misc.Heart1);\r\n    const int hh = al_get_bitmap_height(Graphics.Misc.Heart1);\r\n    for (int i = 0; i != MAX_HEARTS; i ++)\r\n        hearts_save [i] = al_create_bitmap(hw, hh);\r\n}\r\n\r\nvoid SkinFx_DestroyVideoBuffers()\r\n{\r\n    for (int i = 0; i != MAX_HEARTS; i ++)\r\n    {\r\n        if (hearts_save[i] != NULL)\r\n            al_destroy_bitmap(hearts_save[i]);\r\n        hearts_save[i] = NULL;\r\n    }\r\n}\r\n\r\nstatic void SkinFx_UpdateBlood()\r\n{\r\n    int i;\r\n\r\n    // This is the colors originally used when MEKA was working in palette mode\r\n    // Nowadays, I guess the logic should be changed to take a single base color and create altered variations of it\r\n    ALLEGRO_COLOR blood_colors[4];\r\n    blood_colors[0] = COLOR_SKIN_WINDOW_BACKGROUND;\r\n    blood_colors[1] = COLOR_SKIN_WINDOW_BORDER;\r\n    blood_colors[2] = COLOR_SKIN_MENU_SELECTION;\r\n    blood_colors[3] = COLOR_SKIN_MENU_BACKGROUND;\r\n\r\n    // Create new drops around cursor\r\n    for (i = 0; i < 4; i ++)\r\n        gui_applet_blood_create(RandomInt(4), gui.mouse.x - 2 + RandomInt(5), gui.mouse.y - 2 + RandomInt(5));\r\n    for (i = 0; i < 2; i ++)\r\n        gui_applet_blood_create(RandomInt(4), gui.mouse.x - 4 + RandomInt(9), gui.mouse.y - 4 + RandomInt(9));\r\n    gui_applet_blood_create(RandomInt(4), gui.mouse.x - 5 + RandomInt(11), gui.mouse.y - 5 + RandomInt(11));\r\n\r\n    // Create new drops below currently focused window\r\n    t_gui_box* b = gui.boxes_z_ordered[0];\r\n    if (b && (b->flags & GUI_BOX_FLAGS_ACTIVE))\r\n    {\r\n        for (i = 0; i < 4; i ++)\r\n        {\r\n            gui_applet_blood_create(RandomInt(4),\r\n                b->frame.pos.x - 2 + RandomInt(b->frame.size.x + 4), b->frame.pos.y + b->frame.size.y + 2);\r\n        }\r\n    }\r\n\r\n    // Update drops\r\n    for (i = 0; i < MAX_BLOOD_DROP; i ++)\r\n    {\r\n        t_skinfx_particle* p = &g_skinfx_particles[i];\r\n        p->x += p->vx;\r\n        p->y += p->vy;\r\n        if (p->x < 0 || p->x >= gui.info.screen.x || p->y < 0 || p->y >= gui.info.screen.y)\r\n            p->v = 0;\r\n    }\r\n\r\n    al_lock_bitmap(gui_buffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);\r\n    al_set_target_bitmap(gui_buffer);\r\n\r\n    // Save old colors\r\n    for (i = 0; i < MAX_BLOOD_DROP; i ++)\r\n    {\r\n        t_skinfx_particle* p = &g_skinfx_particles[i];\r\n        if (p->v)\r\n            p->save = al_get_pixel(gui_buffer, p->x, p->y);\r\n    }\r\n\r\n    // Draw blood drops\r\n    for (i = 0; i < MAX_BLOOD_DROP; i ++)\r\n    {\r\n        t_skinfx_particle* p = &g_skinfx_particles[i];\r\n        if (p->v)\r\n            al_put_pixel(p->x, p->y, blood_colors[p->v]);\r\n    }\r\n\r\n    al_unlock_bitmap(gui_buffer);\r\n}\r\n\r\nstatic void SkinFx_UpdateHearts()\r\n{\r\n    // Create a new heart\r\n    if (RandomInt(60) == 0)\r\n        gui_applet_blood_create (RandomInt(2), RandomInt(gui.info.screen.x), gui.info.screen.y - gui.info.bars_height);\r\n\r\n    // Floating hearts\r\n    for (int i = 0; i < MAX_HEARTS; i ++)\r\n    {\r\n        t_skinfx_particle* p = &g_skinfx_particles[i];\r\n        p->y += p->vy;\r\n        p->sin_phase += p->sin_speed;\r\n        p->x = p->ix + p->sin_amp * sinf(p->sin_phase);\r\n    }\r\n\r\n    // Save old graphics\r\n    const int w = al_get_bitmap_width(Graphics.Misc.Heart1);\r\n    const int h = al_get_bitmap_height(Graphics.Misc.Heart1);\r\n    for (int i = 0; i < MAX_HEARTS; i ++)\r\n    {\r\n        t_skinfx_particle* p = &g_skinfx_particles[i];\r\n        al_set_target_bitmap(hearts_save[i]);\r\n        al_draw_bitmap_region(gui_buffer, p->x, p->y, w, h, 0, 0, 0x0000);\r\n    }\r\n\r\n    // Draw hearts\r\n    al_set_target_bitmap(gui_buffer);\r\n    for (int i = 0; i < MAX_HEARTS; i ++)\r\n    {\r\n        t_skinfx_particle* p = &g_skinfx_particles[i];\r\n        al_draw_bitmap(p->v ? Graphics.Misc.Heart1 : Graphics.Misc.Heart2, p->x, p->y, 0);\r\n    }\r\n}\r\n\r\nvoid    special_effects_update_after()\r\n{\r\nreturn;\r\n    t_skin *skin = Skins_GetCurrentSkin();\r\n    switch (skin->effect)\r\n    {\r\n    case SKIN_EFFECT_BLOOD:\r\n        SkinFx_UpdateBlood();\r\n        break;\r\n    case SKIN_EFFECT_HEARTS:\r\n        SkinFx_UpdateHearts();\r\n        break;\r\n    }\r\n}\r\n\r\nvoid    special_effects_update_before()\r\n{\r\nreturn;\r\n    t_skin *skin = Skins_GetCurrentSkin();\r\n\r\n    al_lock_bitmap(gui_buffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);\r\n\r\n    al_set_target_bitmap(gui_buffer);\r\n    switch (skin->effect)\r\n    {\r\n        // BLOOD DROPS -------------------------------------------------------------\r\n    case SKIN_EFFECT_BLOOD:\r\n        for (int i = 0; i < MAX_BLOOD_DROP; i ++)\r\n        {\r\n            t_skinfx_particle* p = &g_skinfx_particles[i];\r\n            if (p->v && p->save.a != 0)\r\n                al_put_pixel(p->x, p->y, p->save);\r\n        }\r\n        break;\r\n    case SKIN_EFFECT_HEARTS:\r\n        // Save old graphics --------------------------------------------------\r\n        const int w = al_get_bitmap_width(Graphics.Misc.Heart1);\r\n        const int h = al_get_bitmap_height(Graphics.Misc.Heart1);\r\n        for (int i = 0; i < MAX_HEARTS; i ++)\r\n        {\r\n            t_skinfx_particle* p = &g_skinfx_particles[i];\r\n            al_draw_bitmap_region(hearts_save[i], 0, 0, w, h, p->x, p->y, 0x0000);\r\n        }\r\n        break;\r\n    }\r\n    al_unlock_bitmap(gui_buffer);\r\n}\r\n\r\nstatic void    gui_applet_blood_create (int v, int x, int y)\r\n{\r\n    int   max = 1;\r\n\r\n    t_skin *skin = Skins_GetCurrentSkin();\r\n    t_skinfx_particle* p = &g_skinfx_particles[g_skinfx_particles_next_spawn];\r\n    switch (skin->effect)\r\n    {\r\n    case SKIN_EFFECT_BLOOD:\r\n        max = MAX_BLOOD_DROP;\r\n        p->v = v;\r\n        p->x = p->ix = x;\r\n        p->y = p->iy = y;\r\n        p->vy = 0.0f;\r\n        p->vy = RandomFloat(0.30f, 0.70f);\r\n        p->sin_amp = 0.0f;\r\n        p->sin_phase = 0.0f;\r\n        p->sin_speed = RandomFloat(-0.02f, +0.02f);\r\n        p->save = al_map_rgba(0,0,0,0);\r\n        break;\r\n    case SKIN_EFFECT_HEARTS:\r\n        max = MAX_HEARTS;\r\n        p->v = v;\r\n        p->x = p->ix = x;\r\n        p->y = p->iy = y;\r\n        p->vx = 0.0f;\r\n        p->vy = RandomFloat(-1.2f, -0.8f);\r\n        p->sin_amp = RandomFloat(20.0f, 70.0f);\r\n        p->sin_phase = RandomFloat(0.0f, MATH_PI*2.0f);\r\n        p->sin_speed = RandomFloat(-0.02f, +0.02f);\r\n        p->save = al_map_rgba(0,0,0,0);\r\n        break;\r\n    }\r\n\r\n    g_skinfx_particles_next_spawn = (g_skinfx_particles_next_spawn + 1) % max;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/skin_fx.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - skin_fx.h\r\n// Special effects - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid SkinFx_Init();\r\nvoid SkinFx_CreateVideoBuffers();\r\nvoid SkinFx_DestroyVideoBuffers();\r\n\r\nvoid special_effects_update_after();\r\nvoid special_effects_update_before();\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/smsid/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<packages>\r\n  <package id=\"Allegro\" version=\"5.2.10\" targetFramework=\"native\" />\r\n  <package id=\"AllegroDeps\" version=\"1.15.0\" targetFramework=\"native\" />\r\n</packages>"
  },
  {
    "path": "meka/srcs/smsid/smsid.cpp",
    "content": "#include \"shared.h\"\r\n#include \"db.h\"\r\n#include \"vdp.h\"\r\n#include <zlib.h>\r\n#include <string>\r\n\r\n//#define MEKA_NAM_PATH\t\t\"meka.nam\"\r\n//#define MEKA_NAM_PATH\t\t\"C:\\\\S-Sms\\\\mekasvn\\\\trunk\\\\meka.nam\"\r\n\r\nstatic bool\t\tSystem_SetClipboardText(const char *text);\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n\tconst char* filename = NULL;\r\n\tconst char* opt_meka_nam = \"meka.nam\";\r\n\tbool opt_copy_to_clipboard = false;\r\n\r\n\tfor (int n = 1; n < argc; n++)\r\n\t{\r\n\t\tconst char* arg = argv[n];\r\n\t\tif (arg[0] == '-' || arg[0] == '/')\r\n\t\t{\r\n\t\t\tif (strcmp(arg+1, \"c\") == 0)\r\n\t\t\t{\r\n\t\t\t\topt_copy_to_clipboard = true;\r\n\t\t\t}\r\n\t\t\telse if (strcmp(arg+1, \"db\") == 0)\r\n\t\t\t{\r\n\t\t\t\tn++;\r\n\t\t\t\tif (n >= argc)\r\n\t\t\t\t{\r\n\t\t\t\t\tprintf(\"Error: missing filename as argument to option '%s'\\n\", arg);\r\n\t\t\t\t\treturn 1;\r\n\t\t\t\t}\r\n\t\t\t\topt_meka_nam = argv[n];\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Error: unknown argument '%s'\\n\", arg);\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfilename = arg;\r\n\t\t}\r\n\t}\r\n\r\n\tif (filename == NULL)\r\n\t{\r\n\t\tprintf(\"smsid 1.0\\n\");\r\n\t\tprintf(\"Syntax: smsid [/db <file>] [/c] <rom>\\n\");\r\n\t\tprintf(\" /db    path to meka.nam [meka.nam]\\n\");\r\n\t\tprintf(\" /c     copy text to OS clipboard [false]\\n\");\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tFILE* f = fopen(filename, \"rb\");\r\n\tif (!f)\r\n\t{\r\n\t\tprintf(\"Error: unable to input file '%s', aborting.\\n\", filename);\r\n\t\treturn 1;\r\n\t}\r\n\r\n\tfseek(f, 0, SEEK_END);\r\n\tconst int rom_size = ftell(f);\r\n\tfseek(f, 0, SEEK_SET);\r\n\r\n\tunsigned char* rom_data = new unsigned char[rom_size];\r\n\tif (fread(rom_data, 1, rom_size, f) != rom_size)\r\n\t{\r\n\t\tprintf(\"Error: unable to read file data, aborting.\\n\");\r\n\t\treturn 1;\r\n\t}\r\n\r\n\tconst u32 crc = crc32(0, rom_data, rom_size);\r\n\t//const u32 crc = 0xe5ff50d8;\r\n\t//const u32 crc = 0xaed9aac4;\r\n\tfclose(f);\r\n\tdelete[] rom_data;\r\n\r\n\tif (!DB_Init(opt_meka_nam, false))\r\n\t{\r\n\t\tprintf(\"Error: failed to open DB file '%s'\\n\", opt_meka_nam);\r\n\t\treturn 1;\r\n\t}\r\n\r\n\tif (opt_copy_to_clipboard)\r\n\t\tprintf(\"(copying following output to OS clipboard)\\n\");\r\n\r\n\tstd::string s;\r\n\r\n\tt_db_entry* entry = DB_Entry_Find(crc, NULL);\r\n\tif (entry)\r\n\t{\r\n\t\tchar buf[256];\r\n\t\tsprintf(buf, \"%s %08x %08X%08X   %s\", \r\n\t\t\tDB_FindDriverNameById(entry->system),\r\n\t\t\tentry->crc_crc32, \r\n\t\t\tentry->crc_mekacrc.v[0], entry->crc_mekacrc.v[1],\r\n\t\t\tentry->names[0].name);\r\n\t\ts += buf;\r\n\r\n\t\tint countries = 0;\r\n\t\tfor (int i = 0; i != DB_COUNTRY_COUNT_; i++)\r\n\t\t{\r\n\t\t\tif (entry->country & (1 << i))\r\n\t\t\t{\r\n\t\t\t\tif (countries == 0)\r\n\t\t\t\t\ts += \" (\";\r\n\t\t\t\telse\r\n\t\t\t\t\ts += \",\";\r\n\t\t\t\ts += DB_FindCountryNameByFlag(1 << i);\r\n\t\t\t\tcountries++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (countries > 0)\r\n\t\t\ts += \")\";\r\n\t\ts += \"\\n\";\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts = \"Unknown.\\n\";\r\n\t}\r\n\tprintf(\"%s\", s.c_str());\r\n\r\n\tif (opt_copy_to_clipboard)\r\n\t{\r\n\t\tSystem_SetClipboardText(s.c_str());\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nstatic bool\t\tSystem_SetClipboardText(const char *text)\r\n{\r\n\t// Open clipboard\r\n\tif (!OpenClipboard(NULL))\r\n\t\treturn false;\r\n\r\n\t// Global alloc\r\n\tconst int text_length = strlen(text) + 1;\r\n\tHGLOBAL text_handle = GlobalAlloc(GMEM_MOVEABLE, text_length * sizeof(char)); \r\n\tif (text_handle == NULL)\r\n\t\treturn false;\r\n\r\n\t// Lock the handle and copy the text to the buffer. \r\n\tchar *text_copy = (char *)GlobalLock(text_handle); \r\n\tstrcpy(text_copy, text);\r\n\tGlobalUnlock(text_handle); \r\n\r\n\tEmptyClipboard();\r\n\tSetClipboardData(CF_TEXT, text_handle);\r\n\tCloseClipboard();\r\n\treturn true;\r\n}\r\n\r\n"
  },
  {
    "path": "meka/srcs/smsid/smsid.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{3391017C-51A4-477A-9C31-BB5D68A07928}</ProjectGuid>\r\n    <RootNamespace>smsid</RootNamespace>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup>\r\n    <_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <OutDir>../../objs/smsid/$(Configuration)\\</OutDir>\r\n    <IntDir>../../objs/smsid/$(Configuration)\\</IntDir>\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <Allegro_LibraryType>StaticMonolithRelease</Allegro_LibraryType>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <OutDir>../../objs/smsid/$(Configuration)\\</OutDir>\r\n    <IntDir>../../objs/smsid/$(Configuration)\\</IntDir>\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <Allegro_LibraryType>StaticMonolithRelease</Allegro_LibraryType>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>Disabled</Optimization>\r\n      <AdditionalIncludeDirectories>../%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MinimalRebuild>false</MinimalRebuild>\r\n      <ExceptionHandling />\r\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r\n      <PrecompiledHeader />\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>\r\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\r\n      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <IgnoreSpecificDefaultLibraries>libcmt; msvcrt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <ProgramDatabaseFile>$(IntDir)smsid.pdb</ProgramDatabaseFile>\r\n      <SubSystem>Console</SubSystem>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <AdditionalIncludeDirectories>../%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <ExceptionHandling />\r\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <PrecompiledHeader />\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>\r\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\r\n      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <ProgramDatabaseFile>$(IntDir)smsid.pdb</ProgramDatabaseFile>\r\n      <SubSystem>Console</SubSystem>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\r\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r\n      <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"..\\db.cpp\" />\r\n    <ClCompile Include=\"..\\libmisc.cpp\" />\r\n    <ClCompile Include=\"..\\libparse.cpp\" />\r\n    <ClCompile Include=\"smsid_stubs.cpp\" />\r\n    <ClCompile Include=\"smsid.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\db.h\" />\r\n    <ClInclude Include=\"..\\libmisc.h\" />\r\n    <ClInclude Include=\"..\\libparse.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"packages.config\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n    <Import Project=\"..\\projects\\msvc\\packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets\" Condition=\"Exists('..\\projects\\msvc\\packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets')\" />\r\n    <Import Project=\"..\\projects\\msvc\\packages\\Allegro.5.2.10\\build\\native\\Allegro.targets\" Condition=\"Exists('..\\projects\\msvc\\packages\\Allegro.5.2.10\\build\\native\\Allegro.targets')\" />\r\n  </ImportGroup>\r\n  <Target Name=\"EnsureNuGetPackageBuildImports\" BeforeTargets=\"PrepareForBuild\">\r\n    <PropertyGroup>\r\n      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>\r\n    </PropertyGroup>\r\n    <Error Condition=\"!Exists('..\\projects\\msvc\\packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\projects\\msvc\\packages\\AllegroDeps.1.15.0\\build\\native\\AllegroDeps.targets'))\" />\r\n    <Error Condition=\"!Exists('..\\projects\\msvc\\packages\\Allegro.5.2.10\\build\\native\\Allegro.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\projects\\msvc\\packages\\Allegro.5.2.10\\build\\native\\Allegro.targets'))\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "meka/srcs/smsid/smsid.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"deps\">\r\n      <UniqueIdentifier>{a5be66af-df94-4229-8108-c7289ada6f8f}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"smsid.cpp\" />\r\n    <ClCompile Include=\"..\\db.cpp\">\r\n      <Filter>deps</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libmisc.cpp\">\r\n      <Filter>deps</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"..\\libparse.cpp\">\r\n      <Filter>deps</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"smsid_stubs.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\db.h\">\r\n      <Filter>deps</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libmisc.h\">\r\n      <Filter>deps</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\libparse.h\">\r\n      <Filter>deps</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"packages.config\" />\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "meka/srcs/smsid/smsid_stubs.cpp",
    "content": "// Minimum stub for db.c to link properly\n#include \"shared.h\"\n#include \"db.h\"\n#include \"vdp.h\"\n\n// from meka.c\nt_meka_config g_config;\n\n// from misc.c\nvoid* Memory_Alloc(size_t size)\n{\n\treturn malloc(size);\n}\n\n// from console.c\nvoid ConsolePrint(char const* msg)\n{\n\tprintf(\"%s\", msg);\n}\n\nvoid ConsolePrintf(char const* format, ...)\n{\n\tchar buf[512];\n\tva_list args;\n\tva_start(args, format);\n\tvsnprintf(buf, countof(buf), format, args);\n\tva_end(args);\n}\n\nvoid Quit_Msg(char const* format, ...)\n{\n\tchar buf[512];\n\tva_list args;\n\tva_start(args, format);\n\tvsnprintf(buf, countof(buf), format, args);\n\tva_end(args);\n\texit(0);\n}\n\nconst char*\tMsg_Get(int n)\n{\n\tswitch (n)\n\t{\n\tcase MSG_DB_Loading: return \"\";//Silent//\"Loading MEKA.NAM...\";\n\tcase MSG_DB_SyntaxError: return \"On line %d: Syntax error!\";\n\t}\n\tassert(0);\n\treturn \"*Msg_Get()ERROR*\";\n}\n\n// from errors.c\nint meka_errno = MEKA_ERR_OK;\nconst char* meka_strerror()\n{\n\treturn \"*ERROR*\";\n}\n\n// from vdp.c\nint     VDP_Model_FindByName(const char* name)\n{\n    if (!strcmp(name, \"315-5124\"))\n        return VDP_MODEL_315_5124;\n    else if (!strcmp(name, \"315-5246\")) //|| !strcmp(name, \"315-5226\")) // Prior to 2024 we had this listed (incorrectly) as 315-5226, however it was never used by meka.nam\n        return VDP_MODEL_315_5246;\n    else if (!strcmp(name, \"315-5378\"))\n        return VDP_MODEL_315_5378;\n    else if (!strcmp(name, \"315-5313\"))\n        return VDP_MODEL_315_5313;\n    return -1;\n}\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/2413tone.h",
    "content": "0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x45,0x4d,0x55,0x32,0x34,0x31,0x33,0x00,\r\n0x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x01,0x31,0x00,0x08,0xd8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x25,0x11,0x00,0x00,0xf8,0xda,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r\n\r\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/emu2413.cpp",
    "content": "/**\r\n * emu2413 v1.5.9\r\n * https://github.com/digital-sound-antiques/emu2413\r\n * Copyright (C) 2020 Mitsutaka Okazaki\r\n *\r\n * This source refers to the following documents. The author would like to thank all the authors who have\r\n * contributed to the writing of them.\r\n * - [YM2413 notes](http://www.smspower.org/Development/YM2413) by andete\r\n * - ymf262.c by Jarek Burczynski\r\n * - [VRC7 presets](https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2#opll_vrc7_patch_format) by Nuke.YKT\r\n * - YMF281B presets by Chabin\r\n */\r\n#include \"shared.h\"\r\n#include \"emu2413.h\"\r\n#include <math.h>\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#ifndef INLINE\r\n#if defined(_MSC_VER)\r\n#define INLINE __inline\r\n#elif defined(__GNUC__)\r\n#define INLINE __inline__\r\n#else\r\n#define INLINE inline\r\n#endif\r\n#endif\r\n\r\n#define _PI_ 3.14159265358979323846264338327950288\r\n\r\n#define OPLL_TONE_NUM 3\r\n/* clang-format off */\r\nstatic uint8_t default_inst[OPLL_TONE_NUM][(16 + 3) * 8] = {{\r\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0: User\r\n0x71,0x61,0x1e,0x17,0xd0,0x78,0x00,0x17, // 1: Violin\r\n0x13,0x41,0x1a,0x0d,0xd8,0xf7,0x23,0x13, // 2: Guitar\r\n0x13,0x01,0x99,0x00,0xf2,0xc4,0x11,0x23, // 3: Piano\r\n0x31,0x61,0x0e,0x07,0xa8,0x64,0x70,0x27, // 4: Flute\r\n0x32,0x21,0x1e,0x06,0xe0,0x76,0x00,0x28, // 5: Clarinet\r\n0x31,0x22,0x16,0x05,0xe0,0x71,0x00,0x18, // 6: Oboe\r\n0x21,0x61,0x1d,0x07,0x82,0x81,0x10,0x07, // 7: Trumpet\r\n0x23,0x21,0x2d,0x14,0xa2,0x72,0x00,0x07, // 8: Organ\r\n0x61,0x61,0x1b,0x06,0x64,0x65,0x10,0x17, // 9: Horn\r\n0x41,0x61,0x0b,0x18,0x85,0xf7,0x71,0x07, // A: Synthesizer\r\n0x13,0x01,0x83,0x11,0xfa,0xe4,0x10,0x04, // B: Harpsichord\r\n0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, // C: Vibraphone\r\n0x61,0x50,0x0c,0x05,0xc2,0xf5,0x20,0x42, // D: Synthesizer Bass\r\n0x01,0x01,0x55,0x03,0xc9,0x95,0x03,0x02, // E: Acoustic Bass\r\n0x61,0x41,0x89,0x03,0xf1,0xe4,0x40,0x13, // F: Electric Guitar\r\n0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, // R: Bass Drum\r\n0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x48, // R: High-Hat(M) / Snare Drum(C)\r\n0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, // R: Tom-tom(M) / Top Cymbal(C)\r\n},{\r\n/* VRC7 presets from Nuke.YKT */\r\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n0x03,0x21,0x05,0x06,0xe8,0x81,0x42,0x27,\r\n0x13,0x41,0x14,0x0d,0xd8,0xf6,0x23,0x12,\r\n0x11,0x11,0x08,0x08,0xfa,0xb2,0x20,0x12,\r\n0x31,0x61,0x0c,0x07,0xa8,0x64,0x61,0x27,\r\n0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28,\r\n0x02,0x01,0x06,0x00,0xa3,0xe2,0xf4,0xf4,\r\n0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07,\r\n0x23,0x21,0x22,0x17,0xa2,0x72,0x01,0x17,\r\n0x35,0x11,0x25,0x00,0x40,0x73,0x72,0x01,\r\n0xb5,0x01,0x0f,0x0F,0xa8,0xa5,0x51,0x02,\r\n0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12,\r\n0x71,0x23,0x11,0x06,0x65,0x74,0x18,0x16,\r\n0x01,0x02,0xd3,0x05,0xc9,0x95,0x03,0x02,\r\n0x61,0x63,0x0c,0x00,0x94,0xC0,0x33,0xf6,\r\n0x21,0x72,0x0d,0x00,0xc1,0xd5,0x56,0x06,\r\n0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d,\r\n0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68,\r\n0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55,\r\n},{\r\n/* YMF281B presets */\r\n0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0: User\r\n0x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16, // 1: Electric Strings (form Chabin's patch)\r\n0x40,0x10,0x45,0x00,0xf6,0x83,0x73,0x63, // 2: Bow Wow (based on plgDavid's patch, KSL fixed)\r\n0x13,0x01,0x99,0x00,0xf2,0xc3,0x21,0x23, // 3: Electric Guitar (similar to YM2413 but different DR(C))\r\n0x01,0x61,0x0b,0x0f,0xf9,0x64,0x70,0x17, // 4: Organ (based on Chabin, TL/DR fixed)\r\n0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, // 5: Clarinet (identical to YM2413)\r\n0x60,0x01,0x82,0x0e,0xf9,0x61,0x20,0x27, // 6: Saxophone (based on plgDavid, PM/EG fixed)\r\n0x21,0x61,0x1c,0x07,0x84,0x81,0x11,0x07, // 7: Trumpet (similar to YM2413 but different TL/DR(M))\r\n0x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28, // 8: Street Organ (from Chabin)\r\n0x01,0x21,0x07,0x03,0xa5,0x71,0x51,0x07, // 9: Synth Brass (based on Chabin, TL fixed)\r\n0x06,0x01,0x5e,0x07,0xf3,0xf3,0xf6,0x13, // A: Electric Piano (based on Chabin, DR/RR/KR fixed)\r\n0x00,0x00,0x18,0x06,0xf5,0xf3,0x20,0x23, // B: Bass (based on Chabin, EG fixed)\r\n0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, // C: Vibraphone (identical to YM2413)\r\n0x35,0x64,0x00,0x00,0xff,0xf3,0x77,0xf5, // D: Chimes (from plgDavid)\r\n0x11,0x31,0x00,0x07,0xdd,0xf3,0xff,0xfb, // E: Tom Tom II (from plgDavid)\r\n0x3a,0x21,0x00,0x07,0x80,0x84,0x0f,0xf5, // F: Noise (based on plgDavid, AR fixed)\r\n0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, // R: Bass Drum (identical to YM2413)\r\n0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, // R: High-Hat(M) / Snare Drum(C) (identical to YM2413)\r\n0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, // R: Tom-tom(M) / Top Cymbal(C) (identical to YM2413)\r\n}};\r\n/* clang-format on */\r\n\r\n/* phase increment counter */\r\n#define DP_BITS 19\r\n#define DP_WIDTH (1 << DP_BITS)\r\n#define DP_BASE_BITS (DP_BITS - PG_BITS)\r\n\r\n/* dynamic range of envelope output */\r\n#define EG_STEP 0.375\r\n#define EG_BITS 7\r\n#define EG_MUTE ((1 << EG_BITS) - 1)\r\n#define EG_MAX (EG_MUTE - 4)\r\n\r\n/* dynamic range of total level */\r\n#define TL_STEP 0.75\r\n#define TL_BITS 6\r\n\r\n/* dynamic range of sustine level */\r\n#define SL_STEP 3.0\r\n#define SL_BITS 4\r\n\r\n/* damper speed before key-on. key-scale affects. */\r\n#define DAMPER_RATE 12\r\n\r\n#define TL2EG(d) ((d) << 1)\r\n\r\n/* sine table */\r\n#define PG_BITS 10 /* 2^10 = 1024 length sine table */\r\n#define PG_WIDTH (1 << PG_BITS)\r\n\r\n/* clang-format off */\r\n/* exp_table[x] = round((exp2((double)x / 256.0) - 1) * 1024) */\r\nstatic uint16_t exp_table[256] = {\r\n0,    3,    6,    8,    11,   14,   17,   20,   22,   25,   28,   31,   34,   37,   40,   42,\r\n45,   48,   51,   54,   57,   60,   63,   66,   69,   72,   75,   78,   81,   84,   87,   90,\r\n93,   96,   99,   102,  105,  108,  111,  114,  117,  120,  123,  126,  130,  133,  136,  139,\r\n142,  145,  148,  152,  155,  158,  161,  164,  168,  171,  174,  177,  181,  184,  187,  190,\r\n194,  197,  200,  204,  207,  210,  214,  217,  220,  224,  227,  231,  234,  237,  241,  244,\r\n248,  251,  255,  258,  262,  265,  268,  272,  276,  279,  283,  286,  290,  293,  297,  300,\r\n304,  308,  311,  315,  318,  322,  326,  329,  333,  337,  340,  344,  348,  352,  355,  359,\r\n363,  367,  370,  374,  378,  382,  385,  389,  393,  397,  401,  405,  409,  412,  416,  420,\r\n424,  428,  432,  436,  440,  444,  448,  452,  456,  460,  464,  468,  472,  476,  480,  484,\r\n488,  492,  496,  501,  505,  509,  513,  517,  521,  526,  530,  534,  538,  542,  547,  551,\r\n555,  560,  564,  568,  572,  577,  581,  585,  590,  594,  599,  603,  607,  612,  616,  621,\r\n625,  630,  634,  639,  643,  648,  652,  657,  661,  666,  670,  675,  680,  684,  689,  693,\r\n698,  703,  708,  712,  717,  722,  726,  731,  736,  741,  745,  750,  755,  760,  765,  770,\r\n774,  779,  784,  789,  794,  799,  804,  809,  814,  819,  824,  829,  834,  839,  844,  849,\r\n854,  859,  864,  869,  874,  880,  885,  890,  895,  900,  906,  911,  916,  921,  927,  932,\r\n937,  942,  948,  953,  959,  964,  969,  975,  980,  986,  991,  996, 1002, 1007, 1013, 1018\r\n};\r\n/* fullsin_table[x] = round(-log2(sin((x + 0.5) * PI / (PG_WIDTH / 4) / 2)) * 256) */\r\nstatic uint16_t fullsin_table[PG_WIDTH] = {\r\n2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979,  949,  920,  894,  869,\r\n846,  825,  804,  785,  767,  749,  732,  717,  701,  687,  672,  659,  646,  633,  621,  609,\r\n598,  587,  576,  566,  556,  546,  536,  527,  518,  509,  501,  492,  484,  476,  468,  461,\r\n453,  446,  439,  432,  425,  418,  411,  405,  399,  392,  386,  380,  375,  369,  363,  358,\r\n352,  347,  341,  336,  331,  326,  321,  316,  311,  307,  302,  297,  293,  289,  284,  280,\r\n276,  271,  267,  263,  259,  255,  251,  248,  244,  240,  236,  233,  229,  226,  222,  219,\r\n215,  212,  209,  205,  202,  199,  196,  193,  190,  187,  184,  181,  178,  175,  172,  169,\r\n167,  164,  161,  159,  156,  153,  151,  148,  146,  143,  141,  138,  136,  134,  131,  129,\r\n127,  125,  122,  120,  118,  116,  114,  112,  110,  108,  106,  104,  102,  100,  98,   96,\r\n94,   92,   91,   89,   87,   85,   83,   82,   80,   78,   77,   75,   74,   72,   70,   69,\r\n67,   66,   64,   63,   62,   60,   59,   57,   56,   55,   53,   52,   51,   49,   48,   47,\r\n46,   45,   43,   42,   41,   40,   39,   38,   37,   36,   35,   34,   33,   32,   31,   30,\r\n29,   28,   27,   26,   25,   24,   23,   23,   22,   21,   20,   20,   19,   18,   17,   17,\r\n16,   15,   15,   14,   13,   13,   12,   12,   11,   10,   10,   9,    9,    8,    8,    7,\r\n7,    7,    6,    6,    5,    5,    5,    4,    4,    4,    3,    3,    3,    2,    2,    2,\r\n2,    1,    1,    1,    1,    1,    1,    1,    0,    0,    0,    0,    0,    0,    0,    0,\r\n};\r\n/* clang-format on */\r\n\r\nstatic uint16_t halfsin_table[PG_WIDTH];\r\nstatic uint16_t *wave_table_map[2] = {fullsin_table, halfsin_table};\r\n\r\n/* pitch modulator */\r\n/* offset to fnum, rough approximation of 14 cents depth. */\r\nstatic int8_t pm_table[8][8] = {\r\n    {0, 0, 0, 0, 0, 0, 0, 0},    // fnum = 000xxxxxx\r\n    {0, 0, 1, 0, 0, 0, -1, 0},   // fnum = 001xxxxxx\r\n    {0, 1, 2, 1, 0, -1, -2, -1}, // fnum = 010xxxxxx\r\n    {0, 1, 3, 1, 0, -1, -3, -1}, // fnum = 011xxxxxx\r\n    {0, 2, 4, 2, 0, -2, -4, -2}, // fnum = 100xxxxxx\r\n    {0, 2, 5, 2, 0, -2, -5, -2}, // fnum = 101xxxxxx\r\n    {0, 3, 6, 3, 0, -3, -6, -3}, // fnum = 110xxxxxx\r\n    {0, 3, 7, 3, 0, -3, -7, -3}, // fnum = 111xxxxxx\r\n};\r\n\r\n/* amplitude lfo table */\r\n/* The following envelop pattern is verified on real YM2413. */\r\n/* each element repeates 64 cycles */\r\nstatic uint8_t am_table[210] = {0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  //\r\n                                2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  //\r\n                                4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,  5,  //\r\n                                6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  //\r\n                                8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  //\r\n                                10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, //\r\n                                12, 12, 12, 12, 12, 12, 12, 12,                                 //\r\n                                13, 13, 13,                                                     //\r\n                                12, 12, 12, 12, 12, 12, 12, 12,                                 //\r\n                                11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, //\r\n                                9,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  //\r\n                                7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  //\r\n                                5,  5,  5,  5,  5,  5,  5,  5,  4,  4,  4,  4,  4,  4,  4,  4,  //\r\n                                3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  //\r\n                                1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0};\r\n\r\n/* envelope decay increment step table */\r\n/* based on andete's research */\r\nstatic uint8_t eg_step_tables[4][8] = {\r\n    {0, 1, 0, 1, 0, 1, 0, 1},\r\n    {0, 1, 0, 1, 1, 1, 0, 1},\r\n    {0, 1, 1, 1, 0, 1, 1, 1},\r\n    {0, 1, 1, 1, 1, 1, 1, 1},\r\n};\r\n\r\nenum __OPLL_EG_STATE { ATTACK, DECAY, SUSTAIN, RELEASE, DAMP, UNKNOWN };\r\n\r\nstatic uint32_t ml_table[16] = {1,     1 * 2, 2 * 2,  3 * 2,  4 * 2,  5 * 2,  6 * 2,  7 * 2,\r\n                                8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2};\r\n\r\n#define dB2(x) ((x)*2)\r\nstatic double kl_table[16] = {dB2(0.000),  dB2(9.000),  dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125),\r\n                              dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500),\r\n                              dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)};\r\n\r\nstatic uint32_t tll_table[8 * 16][1 << TL_BITS][4];\r\nstatic int32_t rks_table[8 * 2][2];\r\n\r\nstatic OPLL_PATCH null_patch = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r\nstatic OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];\r\n\r\n/* don't forget min/max is defined as a macro in stdlib.h of Visual C. */\r\n#ifndef min\r\nstatic INLINE int min(int i, int j) { return (i < j) ? i : j; }\r\n#endif\r\n#ifndef max\r\nstatic INLINE int max(int i, int j) { return (i > j) ? i : j; }\r\n#endif\r\n\r\n/***************************************************\r\n\r\n           Internal Sample Rate Converter\r\n\r\n****************************************************/\r\n/* Note: to disable internal rate converter, set clock/72 to output sampling rate. */\r\n\r\n/*\r\n * LW is truncate length of sinc(x) calculation.\r\n * Lower LW is faster, higher LW results better quality.\r\n * LW must be a non-zero positive even number, no upper limit.\r\n * LW=16 or greater is recommended when upsampling.\r\n * LW=8 is practically okay for downsampling.\r\n */\r\n#define LW 16\r\n\r\n/* resolution of sinc(x) table. sinc(x) where 0.0<=x<1.0 corresponds to sinc_table[0...SINC_RESO-1] */\r\n#define SINC_RESO 256\r\n#define SINC_AMP_BITS 12\r\n\r\n// double hamming(double x) { return 0.54 - 0.46 * cos(2 * PI * x); }\r\nstatic double blackman(double x) { return 0.42 - 0.5 * cos(2 * _PI_ * x) + 0.08 * cos(4 * _PI_ * x); }\r\nstatic double sinc(double x) { return (x == 0.0 ? 1.0 : sin(_PI_ * x) / (_PI_ * x)); }\r\nstatic double windowed_sinc(double x) { return blackman(0.5 + 0.5 * x / (LW / 2)) * sinc(x); }\r\n\r\n/* f_inp: input frequency. f_out: output frequencey, ch: number of channels */\r\nOPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch) {\r\n  OPLL_RateConv *conv = static_cast<OPLL_RateConv*>(malloc(sizeof(OPLL_RateConv)));\r\n  int i;\r\n\r\n  conv->ch = ch;\r\n  conv->f_ratio = f_inp / f_out;\r\n  conv->buf = static_cast<int16_t**>(malloc(sizeof(void *) * ch));\r\n  for (i = 0; i < ch; i++) {\r\n    conv->buf[i] = static_cast<int16_t*>(malloc(sizeof(conv->buf[0][0]) * LW));\r\n  }\r\n\r\n  /* create sinc_table for positive 0 <= x < LW/2 */\r\n  conv->sinc_table = static_cast<int16_t*>(malloc(sizeof(conv->sinc_table[0]) * SINC_RESO * LW / 2));\r\n  for (i = 0; i < SINC_RESO * LW / 2; i++) {\r\n    const double x = (double)i / SINC_RESO;\r\n    if (f_out < f_inp) {\r\n      /* for downsampling */\r\n      conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x / conv->f_ratio) / conv->f_ratio);\r\n    } else {\r\n      /* for upsampling */\r\n      conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x));\r\n    }\r\n  }\r\n\r\n  return conv;\r\n}\r\n\r\nstatic INLINE int16_t lookup_sinc_table(int16_t *table, double x) {\r\n  int16_t index = (int16_t)(x * SINC_RESO);\r\n  if (index < 0)\r\n    index = -index;\r\n  return table[min(SINC_RESO * LW / 2 - 1, index)];\r\n}\r\n\r\nvoid OPLL_RateConv_reset(OPLL_RateConv *conv) {\r\n  int i;\r\n  conv->timer = 0;\r\n  for (i = 0; i < conv->ch; i++) {\r\n    memset(conv->buf[i], 0, sizeof(conv->buf[i][0]) * LW);\r\n  }\r\n}\r\n\r\n/* put original data to this converter at f_inp. */\r\nvoid OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data) {\r\n  int16_t *buf = conv->buf[ch];\r\n  int i;\r\n  for (i = 0; i < LW - 1; i++) {\r\n    buf[i] = buf[i + 1];\r\n  }\r\n  buf[LW - 1] = data;\r\n}\r\n\r\n/* get resampled data from this converter at f_out. */\r\n/* this function must be called f_out / f_inp times per one putData call. */\r\nint16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch) {\r\n  int16_t *buf = conv->buf[ch];\r\n  int32_t sum = 0;\r\n  int k;\r\n  double dn;\r\n  conv->timer += conv->f_ratio;\r\n  dn = conv->timer - floor(conv->timer);\r\n  conv->timer = dn;\r\n\r\n  for (k = 0; k < LW; k++) {\r\n    double x = ((double)k - (LW / 2 - 1)) - dn;\r\n    sum += buf[k] * lookup_sinc_table(conv->sinc_table, x);\r\n  }\r\n  return sum >> SINC_AMP_BITS;\r\n}\r\n\r\nvoid OPLL_RateConv_delete(OPLL_RateConv *conv) {\r\n  int i;\r\n  for (i = 0; i < conv->ch; i++) {\r\n    free(conv->buf[i]);\r\n  }\r\n  free(conv->buf);\r\n  free(conv->sinc_table);\r\n  free(conv);\r\n}\r\n\r\n/***************************************************\r\n\r\n                  Create tables\r\n\r\n****************************************************/\r\n\r\nstatic void makeSinTable(void) {\r\n  int x;\r\n\r\n  for (x = 0; x < PG_WIDTH / 4; x++) {\r\n    fullsin_table[PG_WIDTH / 4 + x] = fullsin_table[PG_WIDTH / 4 - x - 1];\r\n  }\r\n\r\n  for (x = 0; x < PG_WIDTH / 2; x++) {\r\n    fullsin_table[PG_WIDTH / 2 + x] = 0x8000 | fullsin_table[x];\r\n  }\r\n\r\n  for (x = 0; x < PG_WIDTH / 2; x++)\r\n    halfsin_table[x] = fullsin_table[x];\r\n\r\n  for (x = PG_WIDTH / 2; x < PG_WIDTH; x++)\r\n    halfsin_table[x] = 0xfff;\r\n}\r\n\r\nstatic void makeTllTable(void) {\r\n\r\n  int32_t tmp;\r\n  int32_t fnum, block, TL, KL;\r\n\r\n  for (fnum = 0; fnum < 16; fnum++) {\r\n    for (block = 0; block < 8; block++) {\r\n      for (TL = 0; TL < 64; TL++) {\r\n        for (KL = 0; KL < 4; KL++) {\r\n          if (KL == 0) {\r\n            tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL);\r\n          } else {\r\n            tmp = (int32_t)(kl_table[fnum] - dB2(3.000) * (7 - block));\r\n            if (tmp <= 0)\r\n              tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL);\r\n            else\r\n              tll_table[(block << 4) | fnum][TL][KL] = (uint32_t)((tmp >> (3 - KL)) / EG_STEP) + TL2EG(TL);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\nstatic void makeRksTable(void) {\r\n  int fnum8, block;\r\n  for (fnum8 = 0; fnum8 < 2; fnum8++)\r\n    for (block = 0; block < 8; block++) {\r\n      rks_table[(block << 1) | fnum8][1] = (block << 1) + fnum8;\r\n      rks_table[(block << 1) | fnum8][0] = block >> 1;\r\n    }\r\n}\r\n\r\nstatic void makeDefaultPatch(void) {\r\n  int i, j;\r\n  for (i = 0; i < OPLL_TONE_NUM; i++)\r\n    for (j = 0; j < 19; j++)\r\n      OPLL_getDefaultPatch(i, j, &default_patch[i][j * 2]);\r\n}\r\n\r\nstatic uint8_t table_initialized = 0;\r\n\r\nstatic void initializeTables(void) {\r\n  makeTllTable();\r\n  makeRksTable();\r\n  makeSinTable();\r\n  makeDefaultPatch();\r\n  table_initialized = 1;\r\n}\r\n\r\n/*********************************************************\r\n\r\n                      Synthesizing\r\n\r\n*********************************************************/\r\n#define SLOT_BD1 12\r\n#define SLOT_BD2 13\r\n#define SLOT_HH 14\r\n#define SLOT_SD 15\r\n#define SLOT_TOM 16\r\n#define SLOT_CYM 17\r\n\r\n/* utility macros */\r\n#define MOD(o, x) (&(o)->slot[(x) << 1])\r\n#define CAR(o, x) (&(o)->slot[((x) << 1) | 1])\r\n#define BIT(s, b) (((s) >> (b)) & 1)\r\n\r\n#if OPLL_DEBUG\r\nstatic void _debug_print_patch(OPLL_SLOT *slot) {\r\n  OPLL_PATCH *p = slot->patch;\r\n  printf(\"[slot#%d am:%d pm:%d eg:%d kr:%d ml:%d kl:%d tl:%d ws:%d fb:%d A:%d D:%d S:%d R:%d]\\n\", slot->number, //\r\n         p->AM, p->PM, p->EG, p->KR, p->ML,                                                                     //\r\n         p->KL, p->TL, p->WS, p->FB,                                                                            //\r\n         p->AR, p->DR, p->SL, p->RR);\r\n}\r\n\r\nstatic char *_debug_eg_state_name(OPLL_SLOT *slot) {\r\n  switch (slot->eg_state) {\r\n  case ATTACK:\r\n    return \"attack\";\r\n  case DECAY:\r\n    return \"decay\";\r\n  case SUSTAIN:\r\n    return \"sustain\";\r\n  case RELEASE:\r\n    return \"release\";\r\n  case DAMP:\r\n    return \"damp\";\r\n  default:\r\n    return \"unknown\";\r\n  }\r\n}\r\n\r\nstatic INLINE void _debug_print_slot_info(OPLL_SLOT *slot) {\r\n  char *name = _debug_eg_state_name(slot);\r\n  printf(\"[slot#%d state:%s fnum:%03x rate:%d-%d]\\n\", slot->number, name, slot->blk_fnum, slot->eg_rate_h,\r\n         slot->eg_rate_l);\r\n  _debug_print_patch(slot);\r\n  fflush(stdout);\r\n}\r\n#endif\r\n\r\nstatic INLINE int get_parameter_rate(OPLL_SLOT *slot) {\r\n\r\n  if ((slot->type & 1) == 0 && slot->key_flag == 0) {\r\n    return 0;\r\n  }\r\n\r\n  switch (slot->eg_state) {\r\n  case ATTACK:\r\n    return slot->patch->AR;\r\n  case DECAY:\r\n    return slot->patch->DR;\r\n  case SUSTAIN:\r\n    return slot->patch->EG ? 0 : slot->patch->RR;\r\n  case RELEASE:\r\n    if (slot->sus_flag) {\r\n      return 5;\r\n    } else if (slot->patch->EG) {\r\n      return slot->patch->RR;\r\n    } else {\r\n      return 7;\r\n    }\r\n  case DAMP:\r\n    return DAMPER_RATE;\r\n  default:\r\n    return 0;\r\n  }\r\n}\r\n\r\nenum SLOT_UPDATE_FLAG {\r\n  UPDATE_WS = 1,\r\n  UPDATE_TLL = 2,\r\n  UPDATE_RKS = 4,\r\n  UPDATE_EG = 8,\r\n  UPDATE_ALL = 255,\r\n};\r\n\r\nstatic INLINE void request_update(OPLL_SLOT *slot, int flag) { slot->update_requests |= flag; }\r\n\r\nstatic void commit_slot_update(OPLL_SLOT *slot) {\r\n\r\n#if OPLL_DEBUG\r\n  if (slot->last_eg_state != slot->eg_state) {\r\n    _debug_print_slot_info(slot);\r\n    slot->last_eg_state = slot->eg_state;\r\n  }\r\n#endif\r\n\r\n  if (slot->update_requests & UPDATE_WS) {\r\n    slot->wave_table = wave_table_map[slot->patch->WS];\r\n  }\r\n\r\n  if (slot->update_requests & UPDATE_TLL) {\r\n    if ((slot->type & 1) == 0) {\r\n      slot->tll = tll_table[slot->blk_fnum >> 5][slot->patch->TL][slot->patch->KL];\r\n    } else {\r\n      slot->tll = tll_table[slot->blk_fnum >> 5][slot->volume][slot->patch->KL];\r\n    }\r\n  }\r\n\r\n  if (slot->update_requests & UPDATE_RKS) {\r\n    slot->rks = rks_table[slot->blk_fnum >> 8][slot->patch->KR];\r\n  }\r\n\r\n  if (slot->update_requests & (UPDATE_RKS | UPDATE_EG)) {\r\n    int p_rate = get_parameter_rate(slot);\r\n\r\n    if (p_rate == 0) {\r\n      slot->eg_shift = 0;\r\n      slot->eg_rate_h = 0;\r\n      slot->eg_rate_l = 0;\r\n      return;\r\n    }\r\n\r\n    slot->eg_rate_h = min(15, p_rate + (slot->rks >> 2));\r\n    slot->eg_rate_l = slot->rks & 3;\r\n    if (slot->eg_state == ATTACK) {\r\n      slot->eg_shift = (0 < slot->eg_rate_h && slot->eg_rate_h < 12) ? (13 - slot->eg_rate_h) : 0;\r\n    } else {\r\n      slot->eg_shift = (slot->eg_rate_h < 13) ? (13 - slot->eg_rate_h) : 0;\r\n    }\r\n  }\r\n\r\n  slot->update_requests = 0;\r\n}\r\n\r\nstatic void reset_slot(OPLL_SLOT *slot, int number) {\r\n  slot->number = number;\r\n  slot->type = number % 2;\r\n  slot->pg_keep = 0;\r\n  slot->wave_table = wave_table_map[0];\r\n  slot->pg_phase = 0;\r\n  slot->output[0] = 0;\r\n  slot->output[1] = 0;\r\n  slot->eg_state = RELEASE;\r\n  slot->eg_shift = 0;\r\n  slot->rks = 0;\r\n  slot->tll = 0;\r\n  slot->key_flag = 0;\r\n  slot->sus_flag = 0;\r\n  slot->blk_fnum = 0;\r\n  slot->blk = 0;\r\n  slot->fnum = 0;\r\n  slot->volume = 0;\r\n  slot->pg_out = 0;\r\n  slot->eg_out = EG_MUTE;\r\n  slot->patch = &null_patch;\r\n}\r\n\r\nstatic INLINE void slotOn(OPLL *opll, int i) {\r\n  OPLL_SLOT *slot = &opll->slot[i];\r\n  slot->key_flag = 1;\r\n  slot->eg_state = DAMP;\r\n  request_update(slot, UPDATE_EG);\r\n}\r\n\r\nstatic INLINE void slotOff(OPLL *opll, int i) {\r\n  OPLL_SLOT *slot = &opll->slot[i];\r\n  slot->key_flag = 0;\r\n  if (slot->type & 1) {\r\n    slot->eg_state = RELEASE;\r\n    request_update(slot, UPDATE_EG);\r\n  }\r\n}\r\n\r\nstatic INLINE void update_key_status(OPLL *opll) {\r\n  const uint8_t r14 = opll->reg[0x0e];\r\n  const uint8_t rhythm_mode = BIT(r14, 5);\r\n  uint32_t new_slot_key_status = 0;\r\n  uint32_t updated_status;\r\n  int ch;\r\n\r\n  for (ch = 0; ch < 9; ch++)\r\n    if (opll->reg[0x20 + ch] & 0x10)\r\n      new_slot_key_status |= 3 << (ch * 2);\r\n\r\n  if (rhythm_mode) {\r\n    if (r14 & 0x10)\r\n      new_slot_key_status |= 3 << SLOT_BD1;\r\n\r\n    if (r14 & 0x01)\r\n      new_slot_key_status |= 1 << SLOT_HH;\r\n\r\n    if (r14 & 0x08)\r\n      new_slot_key_status |= 1 << SLOT_SD;\r\n\r\n    if (r14 & 0x04)\r\n      new_slot_key_status |= 1 << SLOT_TOM;\r\n\r\n    if (r14 & 0x02)\r\n      new_slot_key_status |= 1 << SLOT_CYM;\r\n  }\r\n\r\n  updated_status = opll->slot_key_status ^ new_slot_key_status;\r\n\r\n  if (updated_status) {\r\n    int i;\r\n    for (i = 0; i < 18; i++)\r\n      if (BIT(updated_status, i)) {\r\n        if (BIT(new_slot_key_status, i)) {\r\n          slotOn(opll, i);\r\n        } else {\r\n          slotOff(opll, i);\r\n        }\r\n      }\r\n  }\r\n\r\n  opll->slot_key_status = new_slot_key_status;\r\n}\r\n\r\nstatic INLINE void set_patch(OPLL *opll, int32_t ch, int32_t num) {\r\n  opll->patch_number[ch] = num;\r\n  MOD(opll, ch)->patch = &opll->patch[num * 2 + 0];\r\n  CAR(opll, ch)->patch = &opll->patch[num * 2 + 1];\r\n  request_update(MOD(opll, ch), UPDATE_ALL);\r\n  request_update(CAR(opll, ch), UPDATE_ALL);\r\n}\r\n\r\nstatic INLINE void set_sus_flag(OPLL *opll, int ch, int flag) {\r\n  CAR(opll, ch)->sus_flag = flag;\r\n  request_update(CAR(opll, ch), UPDATE_EG);\r\n  if (MOD(opll, ch)->type & 1) {\r\n    MOD(opll, ch)->sus_flag = flag;\r\n    request_update(MOD(opll, ch), UPDATE_EG);\r\n  }\r\n}\r\n\r\n/* set volume ( volume : 6bit, register value << 2 ) */\r\nstatic INLINE void set_volume(OPLL *opll, int ch, int volume) {\r\n  CAR(opll, ch)->volume = volume;\r\n  request_update(CAR(opll, ch), UPDATE_TLL);\r\n}\r\n\r\nstatic INLINE void set_slot_volume(OPLL_SLOT *slot, int volume) {\r\n  slot->volume = volume;\r\n  request_update(slot, UPDATE_TLL);\r\n}\r\n\r\n/* set f-Nnmber ( fnum : 9bit ) */\r\nstatic INLINE void set_fnumber(OPLL *opll, int ch, int fnum) {\r\n  OPLL_SLOT *car = CAR(opll, ch);\r\n  OPLL_SLOT *mod = MOD(opll, ch);\r\n  car->fnum = fnum;\r\n  car->blk_fnum = (car->blk_fnum & 0xe00) | (fnum & 0x1ff);\r\n  mod->fnum = fnum;\r\n  mod->blk_fnum = (mod->blk_fnum & 0xe00) | (fnum & 0x1ff);\r\n  request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\r\n  request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\r\n}\r\n\r\n/* set block data (blk : 3bit ) */\r\nstatic INLINE void set_block(OPLL *opll, int ch, int blk) {\r\n  OPLL_SLOT *car = CAR(opll, ch);\r\n  OPLL_SLOT *mod = MOD(opll, ch);\r\n  car->blk = blk;\r\n  car->blk_fnum = ((blk & 7) << 9) | (car->blk_fnum & 0x1ff);\r\n  mod->blk = blk;\r\n  mod->blk_fnum = ((blk & 7) << 9) | (mod->blk_fnum & 0x1ff);\r\n  request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\r\n  request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL);\r\n}\r\n\r\nstatic INLINE void update_rhythm_mode(OPLL *opll) {\r\n  const uint8_t new_rhythm_mode = (opll->reg[0x0e] >> 5) & 1;\r\n\r\n  if (opll->rhythm_mode != new_rhythm_mode) {\r\n\r\n    if (new_rhythm_mode) {\r\n      opll->slot[SLOT_HH].type = 3;\r\n      opll->slot[SLOT_HH].pg_keep = 1;\r\n      opll->slot[SLOT_SD].type = 3;\r\n      opll->slot[SLOT_TOM].type = 3;\r\n      opll->slot[SLOT_CYM].type = 3;\r\n      opll->slot[SLOT_CYM].pg_keep = 1;\r\n      set_patch(opll, 6, 16);\r\n      set_patch(opll, 7, 17);\r\n      set_patch(opll, 8, 18);\r\n      set_slot_volume(&opll->slot[SLOT_HH], ((opll->reg[0x37] >> 4) & 15) << 2);\r\n      set_slot_volume(&opll->slot[SLOT_TOM], ((opll->reg[0x38] >> 4) & 15) << 2);\r\n    } else {\r\n      opll->slot[SLOT_HH].type = 0;\r\n      opll->slot[SLOT_HH].pg_keep = 0;\r\n      opll->slot[SLOT_SD].type = 1;\r\n      opll->slot[SLOT_TOM].type = 0;\r\n      opll->slot[SLOT_CYM].type = 1;\r\n      opll->slot[SLOT_CYM].pg_keep = 0;\r\n      set_patch(opll, 6, opll->reg[0x36] >> 4);\r\n      set_patch(opll, 7, opll->reg[0x37] >> 4);\r\n      set_patch(opll, 8, opll->reg[0x38] >> 4);\r\n    }\r\n  }\r\n\r\n  opll->rhythm_mode = new_rhythm_mode;\r\n}\r\n\r\nstatic void update_ampm(OPLL *opll) {\r\n  if (opll->test_flag & 2) {\r\n    opll->pm_phase = 0;\r\n    opll->am_phase = 0;\r\n  } else {\r\n    opll->pm_phase += (opll->test_flag & 8) ? 1024 : 1;\r\n    opll->am_phase += (opll->test_flag & 8) ? 64 : 1;\r\n  }\r\n  opll->lfo_am = am_table[(opll->am_phase >> 6) % sizeof(am_table)];\r\n}\r\n\r\nstatic void update_noise(OPLL *opll, int cycle) {\r\n  int i;\r\n  for (i = 0; i < cycle; i++) {\r\n    if (opll->noise & 1) {\r\n      opll->noise ^= 0x800200;\r\n    }\r\n    opll->noise >>= 1;\r\n  }\r\n}\r\n\r\nstatic void update_short_noise(OPLL *opll) {\r\n  const uint32_t pg_hh = opll->slot[SLOT_HH].pg_out;\r\n  const uint32_t pg_cym = opll->slot[SLOT_CYM].pg_out;\r\n\r\n  const uint8_t h_bit2 = BIT(pg_hh, PG_BITS - 8);\r\n  const uint8_t h_bit7 = BIT(pg_hh, PG_BITS - 3);\r\n  const uint8_t h_bit3 = BIT(pg_hh, PG_BITS - 7);\r\n\r\n  const uint8_t c_bit3 = BIT(pg_cym, PG_BITS - 7);\r\n  const uint8_t c_bit5 = BIT(pg_cym, PG_BITS - 5);\r\n\r\n  opll->short_noise = (h_bit2 ^ h_bit7) | (h_bit3 ^ c_bit5) | (c_bit3 ^ c_bit5);\r\n}\r\n\r\nstatic INLINE void calc_phase(OPLL_SLOT *slot, int32_t pm_phase, uint8_t reset) {\r\n  const int8_t pm = slot->patch->PM ? pm_table[(slot->fnum >> 6) & 7][(pm_phase >> 10) & 7] : 0;\r\n  if (reset) {\r\n    slot->pg_phase = 0;\r\n  }\r\n  slot->pg_phase += (((slot->fnum & 0x1ff) * 2 + pm) * ml_table[slot->patch->ML]) << slot->blk >> 2;\r\n  slot->pg_phase &= (DP_WIDTH - 1);\r\n  slot->pg_out = slot->pg_phase >> DP_BASE_BITS;\r\n}\r\n\r\nstatic INLINE uint8_t lookup_attack_step(OPLL_SLOT *slot, uint32_t counter) {\r\n  int index;\r\n\r\n  switch (slot->eg_rate_h) {\r\n  case 12:\r\n    index = (counter & 0xc) >> 1;\r\n    return 4 - eg_step_tables[slot->eg_rate_l][index];\r\n  case 13:\r\n    index = (counter & 0xc) >> 1;\r\n    return 3 - eg_step_tables[slot->eg_rate_l][index];\r\n  case 14:\r\n    index = (counter & 0xc) >> 1;\r\n    return 2 - eg_step_tables[slot->eg_rate_l][index];\r\n  case 0:\r\n  case 15:\r\n    return 0;\r\n  default:\r\n    index = counter >> slot->eg_shift;\r\n    return eg_step_tables[slot->eg_rate_l][index & 7] ? 4 : 0;\r\n  }\r\n}\r\n\r\nstatic INLINE uint8_t lookup_decay_step(OPLL_SLOT *slot, uint32_t counter) {\r\n  int index;\r\n\r\n  switch (slot->eg_rate_h) {\r\n  case 0:\r\n    return 0;\r\n  case 13:\r\n    index = ((counter & 0xc) >> 1) | (counter & 1);\r\n    return eg_step_tables[slot->eg_rate_l][index];\r\n  case 14:\r\n    index = ((counter & 0xc) >> 1);\r\n    return eg_step_tables[slot->eg_rate_l][index] + 1;\r\n  case 15:\r\n    return 2;\r\n  default:\r\n    index = counter >> slot->eg_shift;\r\n    return eg_step_tables[slot->eg_rate_l][index & 7];\r\n  }\r\n}\r\n\r\nstatic INLINE void start_envelope(OPLL_SLOT *slot) {\r\n  if (min(15, slot->patch->AR + (slot->rks >> 2)) == 15) {\r\n    slot->eg_state = DECAY;\r\n    slot->eg_out = 0;\r\n  } else {\r\n    slot->eg_state = ATTACK;\r\n  }\r\n  request_update(slot, UPDATE_EG);\r\n}\r\n\r\nstatic INLINE void calc_envelope(OPLL_SLOT *slot, OPLL_SLOT *buddy, uint16_t eg_counter, uint8_t test) {\r\n\r\n  uint32_t mask = (1 << slot->eg_shift) - 1;\r\n  uint8_t s;\r\n\r\n  if (slot->eg_state == ATTACK) {\r\n    if (0 < slot->eg_out && 0 < slot->eg_rate_h && (eg_counter & mask & ~3) == 0) {\r\n      s = lookup_attack_step(slot, eg_counter);\r\n      if (0 < s) {\r\n        slot->eg_out = max(0, ((int)slot->eg_out - (slot->eg_out >> s) - 1));\r\n      }\r\n    }\r\n  } else {\r\n    if (slot->eg_rate_h > 0 && (eg_counter & mask) == 0) {\r\n      slot->eg_out = min(EG_MUTE, slot->eg_out + lookup_decay_step(slot, eg_counter));\r\n    }\r\n  }\r\n\r\n  switch (slot->eg_state) {\r\n  case DAMP:\r\n    // DAMP to ATTACK transition is occured when the envelope reaches EG_MAX (max attenuation but it's not mute).\r\n    // Do not forget to check (eg_counter & mask) == 0 to synchronize it with the progress of the envelope.\r\n    if (slot->eg_out >= EG_MAX && (eg_counter & mask) == 0) {\r\n      start_envelope(slot);\r\n      if (slot->type & 1) {\r\n        if (!slot->pg_keep) {\r\n          slot->pg_phase = 0;\r\n        }\r\n        if (buddy && !buddy->pg_keep) {\r\n          buddy->pg_phase = 0;\r\n        }\r\n      }\r\n    }\r\n    break;\r\n\r\n  case ATTACK:\r\n    if (slot->eg_out == 0) {\r\n      slot->eg_state = DECAY;\r\n      request_update(slot, UPDATE_EG);\r\n    }\r\n    break;\r\n\r\n  case DECAY:\r\n    // DECAY to SUSTAIN transition must be checked at every cycle regardless of the conditions of the envelope rate and\r\n    // counter. i.e. the transition is not synchronized with the progress of the envelope.\r\n    if ((slot->eg_out >> 3) == slot->patch->SL) {\r\n      slot->eg_state = SUSTAIN;\r\n      request_update(slot, UPDATE_EG);\r\n    }\r\n    break;\r\n\r\n  case SUSTAIN:\r\n  case RELEASE:\r\n  default:\r\n    break;\r\n  }\r\n\r\n  if (test) {\r\n    slot->eg_out = 0;\r\n  }\r\n}\r\n\r\nstatic void update_slots(OPLL *opll) {\r\n  int i;\r\n  opll->eg_counter++;\r\n\r\n  for (i = 0; i < 18; i++) {\r\n    OPLL_SLOT *slot = &opll->slot[i];\r\n    OPLL_SLOT *buddy = NULL;\r\n    if (slot->type == 0) {\r\n      buddy = &opll->slot[i + 1];\r\n    }\r\n    if (slot->type == 1) {\r\n      buddy = &opll->slot[i - 1];\r\n    }\r\n    if (slot->update_requests) {\r\n      commit_slot_update(slot);\r\n    }\r\n    calc_envelope(slot, buddy, opll->eg_counter, opll->test_flag & 1);\r\n    calc_phase(slot, opll->pm_phase, opll->test_flag & 4);\r\n  }\r\n}\r\n\r\n/* output: -4095...4095 */\r\nstatic INLINE int16_t lookup_exp_table(uint16_t i) {\r\n  /* from andete's expression */\r\n  int16_t t = (exp_table[(i & 0xff) ^ 0xff] + 1024);\r\n  int16_t res = t >> ((i & 0x7f00) >> 8);\r\n  return ((i & 0x8000) ? ~res : res) << 1;\r\n}\r\n\r\nstatic INLINE int16_t to_linear(uint16_t h, OPLL_SLOT *slot, int16_t am) {\r\n  uint16_t att;\r\n  if (slot->eg_out > EG_MAX)\r\n    return 0;\r\n\r\n  att = min(EG_MUTE, (slot->eg_out + slot->tll + am)) << 4;\r\n  return lookup_exp_table(h + att);\r\n}\r\n\r\nstatic INLINE int16_t calc_slot_car(OPLL *opll, int ch, int16_t fm) {\r\n  OPLL_SLOT *slot = CAR(opll, ch);\r\n\r\n  uint8_t am = slot->patch->AM ? opll->lfo_am : 0;\r\n\r\n  slot->output[1] = slot->output[0];\r\n  slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + 2 * (fm >> 1)) & (PG_WIDTH - 1)], slot, am);\r\n\r\n  return slot->output[0];\r\n}\r\n\r\nstatic INLINE int16_t calc_slot_mod(OPLL *opll, int ch) {\r\n  OPLL_SLOT *slot = MOD(opll, ch);\r\n\r\n  int16_t fm = slot->patch->FB > 0 ? (slot->output[1] + slot->output[0]) >> (9 - slot->patch->FB) : 0;\r\n  uint8_t am = slot->patch->AM ? opll->lfo_am : 0;\r\n\r\n  slot->output[1] = slot->output[0];\r\n  slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + fm) & (PG_WIDTH - 1)], slot, am);\r\n\r\n  return slot->output[0];\r\n}\r\n\r\nstatic INLINE int16_t calc_slot_tom(OPLL *opll) {\r\n  OPLL_SLOT *slot = MOD(opll, 8);\r\n\r\n  return to_linear(slot->wave_table[slot->pg_out], slot, 0);\r\n}\r\n\r\n/* Specify phase offset directly based on 10-bit (1024-length) sine table */\r\n#define _PD(phase) ((PG_BITS < 10) ? (phase >> (10 - PG_BITS)) : (phase << (PG_BITS - 10)))\r\n\r\nstatic INLINE int16_t calc_slot_snare(OPLL *opll) {\r\n  OPLL_SLOT *slot = CAR(opll, 7);\r\n\r\n  uint32_t phase;\r\n\r\n  if (BIT(slot->pg_out, PG_BITS - 2))\r\n    phase = (opll->noise & 1) ? _PD(0x300) : _PD(0x200);\r\n  else\r\n    phase = (opll->noise & 1) ? _PD(0x0) : _PD(0x100);\r\n\r\n  return to_linear(slot->wave_table[phase], slot, 0);\r\n}\r\n\r\nstatic INLINE int16_t calc_slot_cym(OPLL *opll) {\r\n  OPLL_SLOT *slot = CAR(opll, 8);\r\n\r\n  uint32_t phase = opll->short_noise ? _PD(0x300) : _PD(0x100);\r\n\r\n  return to_linear(slot->wave_table[phase], slot, 0);\r\n}\r\n\r\nstatic INLINE int16_t calc_slot_hat(OPLL *opll) {\r\n  OPLL_SLOT *slot = MOD(opll, 7);\r\n\r\n  uint32_t phase;\r\n\r\n  if (opll->short_noise)\r\n    phase = (opll->noise & 1) ? _PD(0x2d0) : _PD(0x234);\r\n  else\r\n    phase = (opll->noise & 1) ? _PD(0x34) : _PD(0xd0);\r\n\r\n  return to_linear(slot->wave_table[phase], slot, 0);\r\n}\r\n\r\n#define _MO(x) (-(x) >> 1)\r\n#define _RO(x) (x)\r\n\r\nstatic void update_output(OPLL *opll) {\r\n  int16_t *out;\r\n  int i;\r\n\r\n  update_ampm(opll);\r\n  update_short_noise(opll);\r\n  update_slots(opll);\r\n\r\n  out = opll->ch_out;\r\n\r\n  /* CH1-6 */\r\n  for (i = 0; i < 6; i++) {\r\n    if (!(opll->mask & OPLL_MASK_CH(i))) {\r\n      out[i] = _MO(calc_slot_car(opll, i, calc_slot_mod(opll, i)));\r\n    }\r\n  }\r\n\r\n  /* CH7 */\r\n  if (!opll->rhythm_mode) {\r\n    if (!(opll->mask & OPLL_MASK_CH(6))) {\r\n      out[6] = _MO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6)));\r\n    }\r\n  } else {\r\n    if (!(opll->mask & OPLL_MASK_BD)) {\r\n      out[9] = _RO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6)));\r\n    }\r\n  }\r\n  update_noise(opll, 14);\r\n\r\n  /* CH8 */\r\n  if (!opll->rhythm_mode) {\r\n    if (!(opll->mask & OPLL_MASK_CH(7))) {\r\n      out[7] = _MO(calc_slot_car(opll, 7, calc_slot_mod(opll, 7)));\r\n    }\r\n  } else {\r\n    if (!(opll->mask & OPLL_MASK_HH)) {\r\n      out[10] = _RO(calc_slot_hat(opll));\r\n    }\r\n    if (!(opll->mask & OPLL_MASK_SD)) {\r\n      out[11] = _RO(calc_slot_snare(opll));\r\n    }\r\n  }\r\n  update_noise(opll, 2);\r\n\r\n  /* CH9 */\r\n  if (!opll->rhythm_mode) {\r\n    if (!(opll->mask & OPLL_MASK_CH(8))) {\r\n      out[8] = _MO(calc_slot_car(opll, 8, calc_slot_mod(opll, 8)));\r\n    }\r\n  } else {\r\n    if (!(opll->mask & OPLL_MASK_TOM)) {\r\n      out[12] = _RO(calc_slot_tom(opll));\r\n    }\r\n    if (!(opll->mask & OPLL_MASK_CYM)) {\r\n      out[13] = _RO(calc_slot_cym(opll));\r\n    }\r\n  }\r\n  update_noise(opll, 2);\r\n}\r\n\r\nINLINE static void mix_output(OPLL *opll) {\r\n  int16_t out = 0;\r\n  int i;\r\n  for (i = 0; i < 14; i++) {\r\n    out += opll->ch_out[i];\r\n  }\r\n  if (opll->conv) {\r\n    OPLL_RateConv_putData(opll->conv, 0, out);\r\n  } else {\r\n    opll->mix_out[0] = out;\r\n  }\r\n}\r\n\r\nINLINE static void mix_output_stereo(OPLL *opll) {\r\n  int16_t *out = opll->mix_out;\r\n  int i;\r\n  out[0] = out[1] = 0;\r\n  for (i = 0; i < 14; i++) {\r\n    if (opll->pan[i] & 2)\r\n      out[0] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][0]);\r\n    if (opll->pan[i] & 1)\r\n      out[1] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][1]);\r\n  }\r\n  if (opll->conv) {\r\n    OPLL_RateConv_putData(opll->conv, 0, out[0]);\r\n    OPLL_RateConv_putData(opll->conv, 1, out[1]);\r\n  }\r\n}\r\n\r\n/***********************************************************\r\n\r\n                   External Interfaces\r\n\r\n***********************************************************/\r\n\r\nOPLL *OPLL_new(uint32_t clk, uint32_t rate) {\r\n  OPLL *opll;\r\n  int i;\r\n\r\n  if (!table_initialized) {\r\n    initializeTables();\r\n  }\r\n\r\n  opll = (OPLL *)calloc(1, sizeof(OPLL));\r\n  if (opll == NULL)\r\n    return NULL;\r\n\r\n  for (i = 0; i < 19 * 2; i++)\r\n    memcpy(&opll->patch[i], &null_patch, sizeof(OPLL_PATCH));\r\n\r\n  opll->clk = clk;\r\n  opll->rate = rate;\r\n  opll->mask = 0;\r\n  opll->conv = NULL;\r\n  opll->mix_out[0] = 0;\r\n  opll->mix_out[1] = 0;\r\n\r\n  OPLL_reset(opll);\r\n  OPLL_setChipType(opll, 0);\r\n  OPLL_resetPatch(opll, 0);\r\n  return opll;\r\n}\r\n\r\nvoid OPLL_delete(OPLL *opll) {\r\n  if (opll->conv) {\r\n    OPLL_RateConv_delete(opll->conv);\r\n    opll->conv = NULL;\r\n  }\r\n  free(opll);\r\n}\r\n\r\nstatic void reset_rate_conversion_params(OPLL *opll) {\r\n  const double f_out = opll->rate;\r\n  const double f_inp = opll->clk / 72.0;\r\n\r\n  opll->out_time = 0;\r\n  opll->out_step = f_inp;\r\n  opll->inp_step = f_out;\r\n\r\n  if (opll->conv) {\r\n    OPLL_RateConv_delete(opll->conv);\r\n    opll->conv = NULL;\r\n  }\r\n\r\n  if (floor(f_inp) != f_out && floor(f_inp + 0.5) != f_out) {\r\n    opll->conv = OPLL_RateConv_new(f_inp, f_out, 2);\r\n  }\r\n\r\n  if (opll->conv) {\r\n    OPLL_RateConv_reset(opll->conv);\r\n  }\r\n}\r\n\r\nvoid OPLL_reset(OPLL *opll) {\r\n  int i;\r\n\r\n  if (!opll)\r\n    return;\r\n\r\n  opll->adr = 0;\r\n\r\n  opll->pm_phase = 0;\r\n  opll->am_phase = 0;\r\n\r\n  opll->noise = 0x1;\r\n  opll->mask = 0;\r\n\r\n  opll->rhythm_mode = 0;\r\n  opll->slot_key_status = 0;\r\n  opll->eg_counter = 0;\r\n\r\n  reset_rate_conversion_params(opll);\r\n\r\n  for (i = 0; i < 18; i++)\r\n    reset_slot(&opll->slot[i], i);\r\n\r\n  for (i = 0; i < 9; i++) {\r\n    set_patch(opll, i, 0);\r\n  }\r\n\r\n  for (i = 0; i < 0x40; i++)\r\n    OPLL_writeReg(opll, i, 0);\r\n\r\n  for (i = 0; i < 15; i++) {\r\n    opll->pan[i] = 3;\r\n    opll->pan_fine[i][1] = opll->pan_fine[i][0] = 1.0f;\r\n  }\r\n\r\n  for (i = 0; i < 14; i++) {\r\n    opll->ch_out[i] = 0;\r\n  }\r\n}\r\n\r\nvoid OPLL_forceRefresh(OPLL *opll) {\r\n  int i;\r\n\r\n  if (opll == NULL)\r\n    return;\r\n\r\n  for (i = 0; i < 9; i++) {\r\n    set_patch(opll, i, opll->patch_number[i]);\r\n  }\r\n\r\n  for (i = 0; i < 18; i++) {\r\n    request_update(&opll->slot[i], UPDATE_ALL);\r\n  }\r\n}\r\n\r\nvoid OPLL_setRate(OPLL *opll, uint32_t rate) {\r\n  opll->rate = rate;\r\n  reset_rate_conversion_params(opll);\r\n}\r\n\r\nvoid OPLL_setQuality(OPLL *opll, uint8_t q) {}\r\n\r\nvoid OPLL_setChipType(OPLL *opll, uint8_t type) { opll->chip_type = type; }\r\n\r\nvoid OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t data) {\r\n  int ch, i;\r\n\r\n  if (reg >= 0x40)\r\n    return;\r\n\r\n  /* mirror registers */\r\n  if ((0x19 <= reg && reg <= 0x1f) || (0x29 <= reg && reg <= 0x2f) || (0x39 <= reg && reg <= 0x3f)) {\r\n    reg -= 9;\r\n  }\r\n\r\n  opll->reg[reg] = (uint8_t)data;\r\n\r\n  switch (reg) {\r\n  case 0x00:\r\n    opll->patch[0].AM = (data >> 7) & 1;\r\n    opll->patch[0].PM = (data >> 6) & 1;\r\n    opll->patch[0].EG = (data >> 5) & 1;\r\n    opll->patch[0].KR = (data >> 4) & 1;\r\n    opll->patch[0].ML = (data)&15;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(MOD(opll, i), UPDATE_RKS | UPDATE_EG);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x01:\r\n    opll->patch[1].AM = (data >> 7) & 1;\r\n    opll->patch[1].PM = (data >> 6) & 1;\r\n    opll->patch[1].EG = (data >> 5) & 1;\r\n    opll->patch[1].KR = (data >> 4) & 1;\r\n    opll->patch[1].ML = (data)&15;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(CAR(opll, i), UPDATE_RKS | UPDATE_EG);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x02:\r\n    opll->patch[0].KL = (data >> 6) & 3;\r\n    opll->patch[0].TL = (data)&63;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(MOD(opll, i), UPDATE_TLL);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x03:\r\n    opll->patch[1].KL = (data >> 6) & 3;\r\n    opll->patch[1].WS = (data >> 4) & 1;\r\n    opll->patch[0].WS = (data >> 3) & 1;\r\n    opll->patch[0].FB = (data)&7;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(MOD(opll, i), UPDATE_WS);\r\n        request_update(CAR(opll, i), UPDATE_WS | UPDATE_TLL);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x04:\r\n    opll->patch[0].AR = (data >> 4) & 15;\r\n    opll->patch[0].DR = (data)&15;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(MOD(opll, i), UPDATE_EG);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x05:\r\n    opll->patch[1].AR = (data >> 4) & 15;\r\n    opll->patch[1].DR = (data)&15;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(CAR(opll, i), UPDATE_EG);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x06:\r\n    opll->patch[0].SL = (data >> 4) & 15;\r\n    opll->patch[0].RR = (data)&15;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(MOD(opll, i), UPDATE_EG);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x07:\r\n    opll->patch[1].SL = (data >> 4) & 15;\r\n    opll->patch[1].RR = (data)&15;\r\n    for (i = 0; i < 9; i++) {\r\n      if (opll->patch_number[i] == 0) {\r\n        request_update(CAR(opll, i), UPDATE_EG);\r\n      }\r\n    }\r\n    break;\r\n\r\n  case 0x0e:\r\n    if (opll->chip_type == 1)\r\n      break;\r\n    update_rhythm_mode(opll);\r\n    update_key_status(opll);\r\n    break;\r\n\r\n  case 0x0f:\r\n    opll->test_flag = data;\r\n    break;\r\n\r\n  case 0x10:\r\n  case 0x11:\r\n  case 0x12:\r\n  case 0x13:\r\n  case 0x14:\r\n  case 0x15:\r\n  case 0x16:\r\n  case 0x17:\r\n  case 0x18:\r\n    ch = reg - 0x10;\r\n    set_fnumber(opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));\r\n    break;\r\n\r\n  case 0x20:\r\n  case 0x21:\r\n  case 0x22:\r\n  case 0x23:\r\n  case 0x24:\r\n  case 0x25:\r\n  case 0x26:\r\n  case 0x27:\r\n  case 0x28:\r\n    ch = reg - 0x20;\r\n    set_fnumber(opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);\r\n    set_block(opll, ch, (data >> 1) & 7);\r\n    set_sus_flag(opll, ch, (data >> 5) & 1);\r\n    update_key_status(opll);\r\n    break;\r\n\r\n  case 0x30:\r\n  case 0x31:\r\n  case 0x32:\r\n  case 0x33:\r\n  case 0x34:\r\n  case 0x35:\r\n  case 0x36:\r\n  case 0x37:\r\n  case 0x38:\r\n    if ((opll->reg[0x0e] & 32) && (reg >= 0x36)) {\r\n      switch (reg) {\r\n      case 0x37:\r\n        set_slot_volume(MOD(opll, 7), ((data >> 4) & 15) << 2);\r\n        break;\r\n      case 0x38:\r\n        set_slot_volume(MOD(opll, 8), ((data >> 4) & 15) << 2);\r\n        break;\r\n      default:\r\n        break;\r\n      }\r\n    } else {\r\n      set_patch(opll, reg - 0x30, (data >> 4) & 15);\r\n    }\r\n    set_volume(opll, reg - 0x30, (data & 15) << 2);\r\n    break;\r\n\r\n  default:\r\n    break;\r\n  }\r\n}\r\n\r\nvoid OPLL_writeIO(OPLL *opll, uint32_t adr, uint8_t val) {\r\n  if (adr & 1)\r\n    OPLL_writeReg(opll, opll->adr, val);\r\n  else\r\n    opll->adr = val;\r\n}\r\n\r\nvoid OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan) { opll->pan[ch & 15] = pan; }\r\n\r\nvoid OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]) {\r\n  opll->pan_fine[ch & 15][0] = pan[0];\r\n  opll->pan_fine[ch & 15][1] = pan[1];\r\n}\r\n\r\nvoid OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch) {\r\n  patch[0].AM = (dump[0] >> 7) & 1;\r\n  patch[1].AM = (dump[1] >> 7) & 1;\r\n  patch[0].PM = (dump[0] >> 6) & 1;\r\n  patch[1].PM = (dump[1] >> 6) & 1;\r\n  patch[0].EG = (dump[0] >> 5) & 1;\r\n  patch[1].EG = (dump[1] >> 5) & 1;\r\n  patch[0].KR = (dump[0] >> 4) & 1;\r\n  patch[1].KR = (dump[1] >> 4) & 1;\r\n  patch[0].ML = (dump[0]) & 15;\r\n  patch[1].ML = (dump[1]) & 15;\r\n  patch[0].KL = (dump[2] >> 6) & 3;\r\n  patch[1].KL = (dump[3] >> 6) & 3;\r\n  patch[0].TL = (dump[2]) & 63;\r\n  patch[1].TL = 0;\r\n  patch[0].FB = (dump[3]) & 7;\r\n  patch[1].FB = 0;\r\n  patch[0].WS = (dump[3] >> 3) & 1;\r\n  patch[1].WS = (dump[3] >> 4) & 1;\r\n  patch[0].AR = (dump[4] >> 4) & 15;\r\n  patch[1].AR = (dump[5] >> 4) & 15;\r\n  patch[0].DR = (dump[4]) & 15;\r\n  patch[1].DR = (dump[5]) & 15;\r\n  patch[0].SL = (dump[6] >> 4) & 15;\r\n  patch[1].SL = (dump[7] >> 4) & 15;\r\n  patch[0].RR = (dump[6]) & 15;\r\n  patch[1].RR = (dump[7]) & 15;\r\n}\r\n\r\nvoid OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *patch) {\r\n  OPLL_dumpToPatch(default_inst[type] + num * 8, patch);\r\n}\r\n\r\nvoid OPLL_setPatch(OPLL *opll, const uint8_t *dump) {\r\n  OPLL_PATCH patch[2];\r\n  int i;\r\n  for (i = 0; i < 19; i++) {\r\n    OPLL_dumpToPatch(dump + i * 8, patch);\r\n    memcpy(&opll->patch[i * 2 + 0], &patch[0], sizeof(OPLL_PATCH));\r\n    memcpy(&opll->patch[i * 2 + 1], &patch[1], sizeof(OPLL_PATCH));\r\n  }\r\n}\r\n\r\nvoid OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump) {\r\n  dump[0] = (uint8_t)((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);\r\n  dump[1] = (uint8_t)((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);\r\n  dump[2] = (uint8_t)((patch[0].KL << 6) + patch[0].TL);\r\n  dump[3] = (uint8_t)((patch[1].KL << 6) + (patch[1].WS << 4) + (patch[0].WS << 3) + patch[0].FB);\r\n  dump[4] = (uint8_t)((patch[0].AR << 4) + patch[0].DR);\r\n  dump[5] = (uint8_t)((patch[1].AR << 4) + patch[1].DR);\r\n  dump[6] = (uint8_t)((patch[0].SL << 4) + patch[0].RR);\r\n  dump[7] = (uint8_t)((patch[1].SL << 4) + patch[1].RR);\r\n}\r\n\r\nvoid OPLL_copyPatch(OPLL *opll, int32_t num, OPLL_PATCH *patch) {\r\n  memcpy(&opll->patch[num], patch, sizeof(OPLL_PATCH));\r\n}\r\n\r\nvoid OPLL_resetPatch(OPLL *opll, uint8_t type) {\r\n  int i;\r\n  for (i = 0; i < 19 * 2; i++)\r\n    OPLL_copyPatch(opll, i, &default_patch[type % OPLL_TONE_NUM][i]);\r\n}\r\n\r\nint16_t OPLL_calc(OPLL *opll) {\r\n  while (opll->out_step > opll->out_time) {\r\n    opll->out_time += opll->inp_step;\r\n    update_output(opll);\r\n    mix_output(opll);\r\n  }\r\n  opll->out_time -= opll->out_step;\r\n  if (opll->conv) {\r\n    opll->mix_out[0] = OPLL_RateConv_getData(opll->conv, 0);\r\n  }\r\n  return opll->mix_out[0];\r\n}\r\n\r\nvoid OPLL_calcStereo(OPLL *opll, int32_t out[2]) {\r\n  while (opll->out_step > opll->out_time) {\r\n    opll->out_time += opll->inp_step;\r\n    update_output(opll);\r\n    mix_output_stereo(opll);\r\n  }\r\n  opll->out_time -= opll->out_step;\r\n  if (opll->conv) {\r\n    out[0] = OPLL_RateConv_getData(opll->conv, 0);\r\n    out[1] = OPLL_RateConv_getData(opll->conv, 1);\r\n  } else {\r\n    out[0] = opll->mix_out[0];\r\n    out[1] = opll->mix_out[1];\r\n  }\r\n}\r\n\r\nuint32_t OPLL_setMask(OPLL *opll, uint32_t mask) {\r\n  uint32_t ret;\r\n\r\n  if (opll) {\r\n    ret = opll->mask;\r\n    opll->mask = mask;\r\n    return ret;\r\n  } else\r\n    return 0;\r\n}\r\n\r\nuint32_t OPLL_toggleMask(OPLL *opll, uint32_t mask) {\r\n  uint32_t ret;\r\n\r\n  if (opll) {\r\n    ret = opll->mask;\r\n    opll->mask ^= mask;\r\n    return ret;\r\n  } else\r\n    return 0;\r\n}\r\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/emu2413.h",
    "content": "#ifndef _EMU2413_H_\r\n#define _EMU2413_H_\r\n\r\n#include <stdint.h>\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n#define OPLL_DEBUG 0\r\n\r\nenum OPLL_TONE_ENUM { OPLL_2413_TONE = 0, OPLL_VRC7_TONE = 1, OPLL_281B_TONE = 2 };\r\n\r\n/* voice data */\r\ntypedef struct __OPLL_PATCH {\r\n  uint32_t TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WS;\r\n} OPLL_PATCH;\r\n\r\n/* slot */\r\ntypedef struct __OPLL_SLOT {\r\n  uint8_t number;\r\n\r\n  /* type flags:\r\n   * 000000SM\r\n   *       |+-- M: 0:modulator 1:carrier\r\n   *       +--- S: 0:normal 1:single slot mode (sd, tom, hh or cym)\r\n   */\r\n  uint8_t type;\r\n\r\n  OPLL_PATCH *patch; /* voice parameter */\r\n\r\n  /* slot output */\r\n  int32_t output[2]; /* output value, latest and previous. */\r\n\r\n  /* phase generator (pg) */\r\n  uint16_t *wave_table; /* wave table */\r\n  uint32_t pg_phase;    /* pg phase */\r\n  uint32_t pg_out;      /* pg output, as index of wave table */\r\n  uint8_t pg_keep;      /* if 1, pg_phase is preserved when key-on */\r\n  uint16_t blk_fnum;    /* (block << 9) | f-number */\r\n  uint16_t fnum;        /* f-number (9 bits) */\r\n  uint8_t blk;          /* block (3 bits) */\r\n\r\n  /* envelope generator (eg) */\r\n  uint8_t eg_state;  /* current state */\r\n  int32_t volume;    /* current volume */\r\n  uint8_t key_flag;  /* key-on flag 1:on 0:off */\r\n  uint8_t sus_flag;  /* key-sus option 1:on 0:off */\r\n  uint16_t tll;      /* total level + key scale level*/\r\n  uint8_t rks;       /* key scale offset (rks) for eg speed */\r\n  uint8_t eg_rate_h; /* eg speed rate high 4bits */\r\n  uint8_t eg_rate_l; /* eg speed rate low 2bits */\r\n  uint32_t eg_shift; /* shift for eg global counter, controls envelope speed */\r\n  uint32_t eg_out;   /* eg output */\r\n\r\n  uint32_t update_requests; /* flags to debounce update */\r\n\r\n#if OPLL_DEBUG\r\n  uint8_t last_eg_state;\r\n#endif\r\n} OPLL_SLOT;\r\n\r\n/* mask */\r\n#define OPLL_MASK_CH(x) (1 << (x))\r\n#define OPLL_MASK_HH (1 << (9))\r\n#define OPLL_MASK_CYM (1 << (10))\r\n#define OPLL_MASK_TOM (1 << (11))\r\n#define OPLL_MASK_SD (1 << (12))\r\n#define OPLL_MASK_BD (1 << (13))\r\n#define OPLL_MASK_RHYTHM (OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD)\r\n\r\n/* rate conveter */\r\ntypedef struct __OPLL_RateConv {\r\n  int ch;\r\n  double timer;\r\n  double f_ratio;\r\n  int16_t *sinc_table;\r\n  int16_t **buf;\r\n} OPLL_RateConv;\r\n\r\nOPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch);\r\nvoid OPLL_RateConv_reset(OPLL_RateConv *conv);\r\nvoid OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data);\r\nint16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch);\r\nvoid OPLL_RateConv_delete(OPLL_RateConv *conv);\r\n\r\ntypedef struct __OPLL {\r\n  uint32_t clk;\r\n  uint32_t rate;\r\n\r\n  uint8_t chip_type;\r\n\r\n  uint32_t adr;\r\n\r\n  double inp_step;\r\n  double out_step;\r\n  double out_time;\r\n\r\n  uint8_t reg[0x40];\r\n  uint8_t test_flag;\r\n  uint32_t slot_key_status;\r\n  uint8_t rhythm_mode;\r\n\r\n  uint32_t eg_counter;\r\n\r\n  uint32_t pm_phase;\r\n  int32_t am_phase;\r\n\r\n  uint8_t lfo_am;\r\n\r\n  uint32_t noise;\r\n  uint8_t short_noise;\r\n\r\n  int32_t patch_number[9];\r\n  OPLL_SLOT slot[18];\r\n  OPLL_PATCH patch[19 * 2];\r\n\r\n  uint8_t pan[16];\r\n  float pan_fine[16][2];\r\n\r\n  uint32_t mask;\r\n\r\n  /* channel output */\r\n  /* 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym */\r\n  int16_t ch_out[14];\r\n\r\n  int16_t mix_out[2];\r\n\r\n  OPLL_RateConv *conv;\r\n} OPLL;\r\n\r\nOPLL *OPLL_new(uint32_t clk, uint32_t rate);\r\nvoid OPLL_delete(OPLL *);\r\n\r\nvoid OPLL_reset(OPLL *);\r\nvoid OPLL_resetPatch(OPLL *, uint8_t);\r\n\r\n/**\r\n * Set output wave sampling rate.\r\n * @param rate sampling rate. If clock / 72 (typically 49716 or 49715 at 3.58MHz) is set, the internal rate converter is\r\n * disabled.\r\n */\r\nvoid OPLL_setRate(OPLL *opll, uint32_t rate);\r\n\r\n/**\r\n * Set internal calcuration quality. Currently no effects, just for compatibility.\r\n * >= v1.0.0 always synthesizes internal output at clock/72 Hz.\r\n */\r\nvoid OPLL_setQuality(OPLL *opll, uint8_t q);\r\n\r\n/**\r\n * Set pan pot (extra function - not YM2413 chip feature)\r\n * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved\r\n * @param pan 0:mute 1:right 2:left 3:center\r\n * ```\r\n * pan: 76543210\r\n *            |+- bit 1: enable Left output\r\n *            +-- bit 0: enable Right output\r\n * ```\r\n */\r\nvoid OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan);\r\n\r\n/**\r\n * Set fine-grained panning\r\n * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved\r\n * @param pan output strength of left/right channel.\r\n *            pan[0]: left, pan[1]: right. pan[0]=pan[1]=1.0f for center.\r\n */\r\nvoid OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]);\r\n\r\n/**\r\n * Set chip type. If vrc7 is selected, r#14 is ignored.\r\n * This method not change the current ROM patch set.\r\n * To change ROM patch set, use OPLL_resetPatch.\r\n * @param type 0:YM2413 1:VRC7\r\n */\r\nvoid OPLL_setChipType(OPLL *opll, uint8_t type);\r\n\r\nvoid OPLL_writeIO(OPLL *opll, uint32_t reg, uint8_t val);\r\nvoid OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t val);\r\n\r\n/**\r\n * Calculate one sample\r\n */\r\nint16_t OPLL_calc(OPLL *opll);\r\n\r\n/**\r\n * Calulate stereo sample\r\n */\r\nvoid OPLL_calcStereo(OPLL *opll, int32_t out[2]);\r\n\r\nvoid OPLL_setPatch(OPLL *, const uint8_t *dump);\r\nvoid OPLL_copyPatch(OPLL *, int32_t, OPLL_PATCH *);\r\n\r\n/**\r\n * Force to refresh.\r\n * External program should call this function after updating patch parameters.\r\n */\r\nvoid OPLL_forceRefresh(OPLL *);\r\n\r\nvoid OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch);\r\nvoid OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump);\r\nvoid OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *);\r\n\r\n/**\r\n *  Set channel mask\r\n *  @param mask mask flag: OPLL_MASK_* can be used.\r\n *  - bit 0..8: mask for ch 1 to 9 (OPLL_MASK_CH(i))\r\n *  - bit 9: mask for Hi-Hat (OPLL_MASK_HH)\r\n *  - bit 10: mask for Top-Cym (OPLL_MASK_CYM)\r\n *  - bit 11: mask for Tom (OPLL_MASK_TOM)\r\n *  - bit 12: mask for Snare Drum (OPLL_MASK_SD)\r\n *  - bit 13: mask for Bass Drum (OPLL_MASK_BD)\r\n */\r\nuint32_t OPLL_setMask(OPLL *, uint32_t mask);\r\n\r\n/**\r\n * Toggler channel mask flag\r\n */\r\nuint32_t OPLL_toggleMask(OPLL *, uint32_t mask);\r\n\r\n/* for compatibility */\r\n#define OPLL_set_rate OPLL_setRate\r\n#define OPLL_set_quality OPLL_setQuality\r\n#define OPLL_set_pan OPLL_setPan\r\n#define OPLL_set_pan_fine OPLL_setPanFine\r\n#define OPLL_calc_stereo OPLL_calcStereo\r\n#define OPLL_reset_patch OPLL_resetPatch\r\n#define OPLL_dump2patch OPLL_dumpToPatch\r\n#define OPLL_patch2dump OPLL_patchToDump\r\n#define OPLL_setChipMode OPLL_setChipType\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\r\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/emutypes.h",
    "content": "#ifndef _EMUTYPES_H_\r\n#define _EMUTYPES_H_\r\n\r\n#ifndef INLINE // OMAR (this line)\r\n#if defined(_MSC_VER)\r\n#define INLINE __forceinline\r\n#elif defined(__GNUC__)\r\n#define INLINE __inline__\r\n#elif defined(_MWERKS_)\r\n#define INLINE inline\r\n#else\r\n#define INLINE\r\n#endif\r\n#endif // OMAR (this line)\r\n\r\n#if defined(EMU_DLL_IMPORTS)\r\n#define EMU2149_DLL_IMPORTS\r\n#define EMU2212_DLL_IMPORTS\r\n#define EMU2413_DLL_IMPORTS\r\n#define EMU8950_DLL_IMPORTS\r\n#define EMU76489_DLL_IMPORTS\r\n#endif\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\ntypedef unsigned int e_uint;\r\ntypedef signed int e_int;\r\n\r\ntypedef unsigned char e_uint8 ;\r\ntypedef signed char e_int8 ;\r\n\r\ntypedef unsigned short e_uint16 ;\r\ntypedef signed short e_int16 ;\r\n\r\ntypedef unsigned int e_uint32 ;\r\ntypedef signed int e_int32 ;\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n#endif\r\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/mekaintf.cpp",
    "content": "//\r\n// Meka - MEKAINTF.C\r\n// Interface to EMU2413\r\n//\r\n\r\n#include \"shared.h\"\r\n#include \"emu2413.h\"\r\n#include \"mekaintf.h\"\r\n#include \"sound/fmunit.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Variables\r\n//-----------------------------------------------------------------------------\r\n\r\n// Handler to OPLL EMU2413\r\nOPLL *opll;\r\n\r\n// saSound channel\r\nint   FM_Digital_saChannel;\r\n\r\nt_fm_unit_interface     FM_Digital_Interface =\r\n{\r\n    \"YM-2413 Digital Emulator\",\r\n    \"Mitsutaka Okazaki\",\r\n    FM_Digital_Reset,\r\n    FM_Digital_Write,\r\n    FM_Digital_Mute,\r\n    FM_Digital_Resume,\r\n    FM_Digital_Regenerate\r\n};\r\n\r\nint     FM_Digital_Init()\r\n{\r\n    ConsolePrintf(\"%s \", Msg_Get(MSG_Sound_Init_YM2413_Digital));\r\n\r\n\topll = OPLL_new(Z80_DEFAULT_CPU_CLOCK, Sound.SampleRate);\r\n    if (opll == NULL)\r\n    {\r\n        ConsolePrintf(\"%s\\n\", Msg_Get(MSG_Failed));\r\n        return (MEKA_ERR_FAIL);\r\n    }\r\n\t// FIXME-NEWSOUND: FM init\r\n\t/*\r\n    FM_Digital_saChannel = stream_init (\"YM-2413 #0\", g_sasound.audio_sample_rate, 16, 0, FM_Digital_Update);\r\n    if (FM_Digital_saChannel == -1)\r\n    {\r\n        ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Failed));\r\n        return (MEKA_ERR_FAIL); // FIXME: Error in channel creation\r\n    }\r\n    stream_set_volume (FM_Digital_saChannel, VOLUME_MAX);\r\n\t*/\r\n\r\n    OPLL_reset(opll);\r\n\r\n    ConsolePrintf(\"%s\\n\", Msg_Get(MSG_Ok));\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\nvoid    FM_Digital_Close()\r\n{\r\n    OPLL_delete (opll);\r\n}\r\n\r\n// Active this engine as being the current FM interface to use\r\nvoid    FM_Digital_Active()\r\n{\r\n    FM_Set_Interface(&FM_Digital_Interface, opll->reg);\r\n}\r\n\r\n// Reset emulated YM-2413\r\nvoid    FM_Digital_Reset()\r\n{\r\n    OPLL_reset(opll);\r\n}\r\n\r\n// Port write to the YM-2413\r\nvoid    FM_Digital_Write(int Register, int Value)\r\n{\r\n    OPLL_writeReg(opll, Register, Value);\r\n}\r\n\r\nvoid    FM_Digital_Mute()\r\n{\r\n}\r\n\r\nvoid    FM_Digital_Resume()\r\n{\r\n}\r\n\r\n// Regenerate various data from YM-2413 registers\r\n// This is called after a state loading\r\nvoid    FM_Digital_Regenerate()\r\n{\r\n    // Msg(MSGT_DEBUG, __FUNCTION__);\r\n    for (int i = 0; i < YM2413_REGISTERS; i++)\r\n    {\r\n        FM_Digital_Write(i, FM_Regs[i]);\r\n    }\r\n    OPLL_forceRefresh(opll);\r\n}\r\n\r\n// Update audio stream\r\n// This is periodically called by the sound engine\r\nvoid    FM_Digital_WriteSamples(s16 *buffer, int length)\r\n{\r\n    // Msg(MSGT_USER, \"FM_Digital_WriteSamples(%p, %d)\", buffer, length);\r\n\r\n    // printf(\"\\n[%s]\\n\", __FUNCTION__);\r\n\r\n\twhile (length--)\r\n\t{\r\n\t\tint val = OPLL_calc(opll) * 2;\r\n        val = MAX(MIN(val, 0x7fff), -0x8000);\n\r\n#if SOUND_CHANNEL_COUNT == 1\n\t\t*buffer++ = val;\r\n#elif SOUND_CHANNEL_COUNT == 2\n\t\t*buffer++ = val;\r\n\t\t*buffer++ = val;\r\n#endif\r\n\t}\r\n}\r\n\r\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/mekaintf.h",
    "content": "//\r\n// Meka - MEKAINTF.H\r\n// Interface to EMU2413\r\n//\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nint     FM_Digital_Init();\r\nvoid    FM_Digital_Close();\r\nvoid    FM_Digital_Active();\r\nvoid    FM_Digital_WriteSamples\t(s16 *buffer, int length);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n// Interface (see FMUNIT.C/.H)\r\nvoid    FM_Digital_Reset();\r\nvoid    FM_Digital_Write(int Register, int Value);\r\nvoid    FM_Digital_Mute();\r\nvoid    FM_Digital_Resume();\r\nvoid    FM_Digital_Regenerate();\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n\r\n"
  },
  {
    "path": "meka/srcs/sound/emu2413/sample.cpp",
    "content": "/*============================================================\n\n  Test code for emu2413.c\n\n    Write 2 seconds of the piano tone into temp.wav\n\n  gcc -Wall -lm sample2413.c emu2413.c\n  (The author had tried to compile on Solaris7 with gcc 2.8.1)\n\n=============================================================*/\n#include <stdio.h>\n#include <time.h>\n#include \"emu2413.h\"\n\n/*\n * Standard clock = MSX clock \n */\n#define MSX_CLK 3579545\n\n#define SAMPLERATE 44100\n#define DATALENGTH (SAMPLERATE*8)\n\nstatic void\nWORD (char *buf, e_uint32 data)\n{\n\n  buf[0] = data & 0xff;\n  buf[1] = (data & 0xff00) >> 8;\n\n}\n\nstatic void\nDWORD (char *buf, e_uint32 data)\n{\n\n  buf[0] = data & 0xff;\n  buf[1] = (data & 0xff00) >> 8;\n  buf[2] = (data & 0xff0000) >> 16;\n  buf[3] = (data & 0xff000000) >> 24;\n\n}\n\nstatic void\nchunkID (char *buf, char id[4])\n{\n\n  buf[0] = id[0];\n  buf[1] = id[1];\n  buf[2] = id[2];\n  buf[3] = id[3];\n\n}\n\nint\nmain (void)\n{\n\n  static char wave[DATALENGTH * 2];\n  char filename[16] = \"temp.wav\";\n  char header[46];\n  int i;\n  clock_t start, finish;\n\n  FILE *fp;\n  OPLL *opll;\n\n  /*\n   * Create WAVE header \n   */\n  chunkID (header, \"RIFF\");\n  DWORD (header + 4, DATALENGTH * 2 + 36);\n  chunkID (header + 8, \"WAVE\");\n  chunkID (header + 12, \"fmt \");\n  DWORD (header + 16, 16);\n  WORD (header + 20, 1);        /* WAVE_FORMAT_PCM */\n  WORD (header + 22, 1);        /* channel 1=mono,2=stereo */\n  DWORD (header + 24, SAMPLERATE);      /* samplesPerSec */\n  DWORD (header + 28, 2 * SAMPLERATE);  /* bytesPerSec */\n  WORD (header + 32, 2);        /* blockSize */\n  WORD (header + 34, 16);       /* bitsPerSample */\n  chunkID (header + 36, \"data\");\n  DWORD (header + 40, 2 * DATALENGTH);\n\n  opll = OPLL_new (MSX_CLK, SAMPLERATE);\n  OPLL_reset (opll);\n  OPLL_writeReg (opll, 0x30, 0x30);     /* select PIANO Voice to ch1. */\n  OPLL_writeReg (opll, 0x10, 0x80);     /* set F-Number(L). */\n  OPLL_writeReg (opll, 0x20, 0x15);     /* set BLK & F-Number(H) and\n                                         * keyon. */\n\n  start = clock ();\n\n  i = 0;\n\n  for (i = 0; i < DATALENGTH; i++)\n  {\n    WORD (wave + i * 2, OPLL_calc (opll));\n  }\n\n  finish = clock ();\n  OPLL_delete (opll);\n\n  printf (\"It has been %f sec to calc %d waves.\\n\", (double) (finish - start) / CLOCKS_PER_SEC, DATALENGTH);\n  printf (\"%f times faster than real YM2413.\\n\", ((double) DATALENGTH / SAMPLERATE) / ((double) (finish - start) / CLOCKS_PER_SEC));\n\n  fp = fopen (filename, \"wb\");\n\n  if (fp == NULL)\n    return 1;\n\n  fwrite (header, 46, 1, fp);\n  fwrite (wave, DATALENGTH, 2, fp);\n\n  fclose (fp);\n\n  printf (\"Wrote : %s\\n\", filename);\n\n  return 0;\n}\n"
  },
  {
    "path": "meka/srcs/sound/fmeditor.cpp",
    "content": "// Outdated\r\n// - Based on OPL wrapper\r\n// - Use widget 'id' (made obsolete)\r\n// Could be worked out to be up to date, if someone has the motivation...\r\n\r\n#include \"shared.h\"\r\n\r\n#if 0\r\n\r\n/*\r\nstruct type_apps_bitmap\r\n{\r\n  ALLEGRO_BITMAP *FM_Editor;\r\n};\r\n\r\nstruct type_apps\r\n{\r\n    struct\r\n    {\r\n        bool FM_Editor;\r\n    } active;\r\n    struct type_apps_bitmap  gfx;\r\n    struct\r\n    {\r\n        byte FM_Editor;\r\n    } id;\r\n} apps;\r\n*/\r\n\r\n\r\n/****************************************************************/\r\n/*  FM voice editor version 0.01 for MEKA                       */\r\n/*                               Programmed by Hiromitsu Shioya */\r\n/****************************************************************/\r\n\r\n#include \"shared.h\"\r\n#include \"desktop.h\"\r\n#include \"g_widget.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n#define  FM_EDITOR_SIZE_X    (320)\r\n#define  FM_EDITOR_SIZE_Y    (224)\r\n#define  FM_EDITOR_FONT      (F_MEDIUM)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic int  fontx, fonty;\r\n\r\nstruct t_fmeditor_app\r\n{\r\n  t_gui_box *   box;\r\n  int           current_voice_number;\r\n};\r\n\r\nextern t_fmeditor_app  FM_Editor;\r\n\r\nenum {\r\n  SEL_FMNUM = 0,\r\n  SEL_KSL,\r\n  SEL_MUL,\r\n  SEL_AR,\r\n  SEL_SL,\r\n  SEL_EG,\r\n  SEL_DR,\r\n  SEL_RR,\r\n  SEL_TL,\r\n  SEL_KSR,\r\n  SEL_WV,\r\n  SEL_FBC,\r\n\r\n  SEL_ERROR\r\n};\r\n\r\nchar *fmsheet[] = {\r\n  \"  Instrument #%2d (%s)\",\r\n  /*123456789012345678901234567890*/\r\n  \"                | OP1 | OP2 |\",\r\n  \"  KSL           |  %2d |  %2d | Max 3\",\r\n  \"  MULTIPLE      |  %2d |  %2d | Max 15\",\r\n  \"  ATTACK        |  %2d |  %2d | Max 15\",\r\n  \"  SUSTAIN LEVEL |  %2d |  %2d | Max 15\",\r\n  \"  EG (sustain)  |  %2d |  %2d | 0/1\",\r\n  \"  DECAY         |  %2d |  %2d | Max 15\",\r\n  \"  RELEASE       |  %2d |  %2d | Max 15\",\r\n  \"  TOTAL LEVEL   | %3d | %3d | Max 63\",\r\n  \"  KSR           |  %2d |  %2d | 0/1\",\r\n  \"  WAVE FORM     |  %2d |  %2d | 0/1/2/3\",\r\n  \"  FEEDBACK/CON  |  %2d |  %2d | FB:Max7, CON:0/1\",\r\n  \" Click L:+1 R:-1\",\r\n};\r\n\r\nint param_limit[][2] = {\r\n  {  0,  3 },  {  0,  3 },  /* KSL */\r\n  {  0, 15 },  {  0, 15 },  /* MUL */\r\n  {  0, 15 },  {  0, 15 },  /* AR */\r\n  {  0, 15 },  {  0, 15 },  /* SL */\r\n  {  0,  1 },  {  0,  1 },  /* EG */\r\n  {  0, 15 },  {  0, 15 },  /* DR */\r\n  {  0, 15 },  {  0, 15 },  /* RR */\r\n  {  0, 63 },  {  0, 63 },  /* TL */\r\n  {  0,  1 },  {  0,  1 },  /* KSR */\r\n  {  0,  3 },  {  0,  3 },  /* WV */\r\n  {  0,  7 },  {  0,  1 },  /* FB/CON */\r\n};\r\n\r\nextern FM_OPL_Patch     FM_OPL_Patchs[YM2413_INSTRUMENTS];\r\nextern int              fmVol[YM2413_VOLUME_STEPS];\r\nextern int              vcref[9];\r\n\r\n/************************************************/\r\n// FM Editor Redraw function\r\n/************************************************/\r\nvoid    FM_Editor_Redraw()\r\n{\r\n  int   i, line;\r\n  int   vmax;\r\n  char  mesg[512], **mbase;\r\n  unsigned char *voice;\r\n\r\n  Font_SetCurrent (FM_EDITOR_FONT);\r\n\r\n  mbase = &fmsheet[0];\r\n  line = 0;\r\n\r\n  /**** clear frame buffer ****/\r\n  rectfill (apps.gfx.FM_Editor, 0, 0, FM_EDITOR_SIZE_X - 1, FM_EDITOR_SIZE_Y - 1, COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n  /**** set number/parameters ****/\r\n  sprintf(mesg, *mbase, FM_Editor.current_voice_number, (char *)FM_Instruments_Name[FM_Editor.current_voice_number]);\r\n  Font_Print (-1, apps.gfx.FM_Editor, mesg, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n  mbase++;\r\n  line++;\r\n  Font_Print (-1, apps.gfx.FM_Editor, *mbase, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n  mbase++;\r\n  line++;\r\n\r\n  voice = (unsigned char *)(&FM_OPL_Patchs[FM_Editor.current_voice_number]);\r\n  for (i = 0; i < sizeof (FM_OPL_Patch) / 2; i++ )\r\n    {\r\n    sprintf(mesg, *mbase, *voice, *(voice + 1));\r\n    Font_Print (-1, apps.gfx.FM_Editor, mesg, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n    voice += 2;\r\n    mbase++;\r\n    line++;\r\n  }\r\n  Font_Print (-1, apps.gfx.FM_Editor, *mbase, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n  line += 2;\r\n\r\n  /**** now select FM voice ****/\r\n  if (!(FM_Regs[0x0e] & 0x20))\r\n     {\r\n     sprintf(mesg, \" FM-MODE: 9 voices mode\");\r\n     Font_Print (-1, apps.gfx.FM_Editor, mesg, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n     line++;\r\n     vmax = 9;\r\n     }\r\n  else\r\n     {\r\n     sprintf(mesg, \" FM-MODE: 6 voices & rhythm mode\");\r\n     Font_Print (-1, apps.gfx.FM_Editor, mesg, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n     line++;\r\n     vmax = 6;\r\n     }\r\n  for (i = 0; i < 9; i++)\r\n     {\r\n     if (i < vmax)  sprintf(mesg, \"  Channel #%d = %2d[%02x] \", i, (FM_Regs[0x30 + i]>>4)&0x0f, FM_Regs[0x30 + i]&0x0f);\r\n     else           sprintf(mesg, \"  Channel #%d = %2d[%02x]*\", i, (FM_Regs[0x30 + i]>>4)&0x0f, FM_Regs[0x30 + i]&0x0f);\r\n     Font_Print (-1, apps.gfx.FM_Editor, mesg, 0, line * fonty, COLOR_SKIN_WINDOW_TEXT);\r\n     line++;\r\n     }\r\n}\r\n\r\n/************************************************/\r\n// Callback function for widgets clicks\r\n/************************************************/\r\nvoid    FM_Editor_CallBack (t_widget *w)\r\n{\r\n  int   i, vr, vl;\r\n  signed char *voice = (signed char *)(&FM_OPL_Patchs[FM_Editor.current_voice_number]);\r\n\r\n  vr = (w->id >> 1) - 1;\r\n  switch (vr)\r\n    {\r\n    case -1:\r\n       /**** fm num ****/\r\n       FM_Editor.current_voice_number += 1 - (2 * (w->id & 1));\r\n       if (FM_Editor.current_voice_number < 1)            FM_Editor.current_voice_number = 1;\r\n       else if (FM_Editor.current_voice_number >= 0x10)   FM_Editor.current_voice_number = 0x0f;\r\n       break;\r\n    default:\r\n       *(voice + vr) += 1 - (2 * (w->id & 1));\r\n       if (*(voice + vr) < param_limit[vr][0])       *(voice + vr) = param_limit[vr][0];\r\n       else if (*(voice + vr) > param_limit[vr][1])  *(voice + vr) = param_limit[vr][1];\r\n       // Now update voices setting\r\n       if (!(FM_Regs[0x0e] & 0x20)) vl = 9;\r\n       else                         vl = 6;\r\n       for (i = 0; i < vl; i++)\r\n          {\r\n          if (((FM_Regs[0x30 + i] >> 4) & 0x0f) == FM_Editor.current_voice_number)\r\n             {\r\n             vcref[i] = -1;\r\n             }\r\n          }\r\n       break;\r\n    }\r\n}\r\n\r\n/************************************************/\r\n// Initialize FM Editor Applet\r\n/************************************************/\r\nvoid        FM_Editor_Init()\r\n{\r\n    int     i;\r\n    t_frame frame;\r\n\r\n    FM_Editor.current_voice_number = 1;       /* first voice is \"1\" */\r\n    fonty = Font_Height (FM_EDITOR_FONT);\r\n    fontx = 6; // Arbitrary.. is actual FM_EDITOR_FONT character width\r\n\r\n    apps.id.FM_Editor = gui_box_create (300, 80, FM_EDITOR_SIZE_X - 1, FM_EDITOR_SIZE_Y - 1, Msg_Get(MSG_FM_Editor_BoxTitle));\r\n    FM_Editor.box = gui.box[apps.id.FM_Editor];\r\n    apps.gfx.FM_Editor = al_create_bitmap (FM_EDITOR_SIZE_X, FM_EDITOR_SIZE_Y);\r\n    gui_set_image_box (apps.id.FM_Editor, apps.gfx.FM_Editor);\r\n    FM_Editor.box->update = FM_Editor_Redraw;\r\n    Desktop_Register_Box (\"FMEDITOR\", apps.id.FM_Editor, 0, &apps.active.FM_Editor);\r\n\r\n    frame.pos.x = fontx*8;\r\n    frame.pos.y = fonty*0;\r\n    frame.size.x = fontx*2;\r\n    frame.size.y = fonty*1;\r\n    widget_button_add (apps.id.FM_Editor, &frame, 1, FM_Editor_CallBack);\r\n    widget_button_add (apps.id.FM_Editor, &frame, 2, FM_Editor_CallBack);\r\n\r\n    for (i = 0; i < 11; i++)\r\n    {\r\n        /**** OP1 ****/\r\n        frame.pos.x = fontx*17;\r\n        frame.pos.y = fonty*(i+2);\r\n        frame.size.x = (fontx*5)-1;\r\n        frame.size.y = (fonty*1)-1;\r\n        widget_button_add (apps.id.FM_Editor, &frame, 1, FM_Editor_CallBack);\r\n        widget_button_add (apps.id.FM_Editor, &frame, 2, FM_Editor_CallBack);\r\n        /**** OP2 ****/\r\n        frame.pos.x = fontx*23;\r\n        widget_button_add (apps.id.FM_Editor, &frame, 1, FM_Editor_CallBack);\r\n        widget_button_add (apps.id.FM_Editor, &frame, 2, FM_Editor_CallBack);\r\n    }\r\n\r\n    widget_closebox_add(FM_Editor.box, FM_Editor_Switch);\r\n}\r\n\r\n/************************************************/\r\n// Switch FM Editor Applet\r\n/************************************************/\r\nvoid    FM_Editor_Switch()\r\n{\r\n    apps.active.FM_Editor ^= 1;\r\n    gui_box_show (gui.box[apps.id.FM_Editor], apps.active.FM_Editor, TRUE);\r\n    if (apps.active.FM_Editor)\r\n        Msg(MSGT_USER, Msg_Get(MSG_FM_Editor_Enabled));\r\n    else\r\n        Msg(MSGT_USER, Msg_Get(MSG_FM_Editor_Disabled));\r\n    gui_menu_inverse_check (menus_ID.fm, 3);\r\n}\r\n\r\n/* EOF */\r\n\r\n#endif\r\n"
  },
  {
    "path": "meka/srcs/sound/fmeditor.h",
    "content": "/****************************************************************/\n/*    FM voice editor version 0.01 for MEKA                     */\n/*                              Programmed by Hiromitsu Shioya  */\n/****************************************************************/\n\n#ifndef __FMEDITOR_H__\n#define __FMEDITOR_H__\n\nvoid    FM_Editor_Init();\nvoid    FM_Editor_Switch();\n\n#endif\n\n/* EOF */\n\n"
  },
  {
    "path": "meka/srcs/sound/fmunit.cpp",
    "content": "//\n// Meka - FMUNIT.C\n// FM Unit - Miscellaneous & wrapper to emulators\n//\n\n#include \"shared.h\"\n#include \"fmunit.h\"\n#include \"emu2413/mekaintf.h\"\n\n//-----------------------------------------------------------------------------\n\n// Registers (pointer to current FM emulator register)\nu8 *          FM_Regs = NULL;\n\n// Interface\nvoid                    FM_Null_Interface_Function() { }\nt_fm_unit_interface     FM_Null_Interface =\n{\n  \"FM Null Interface\",\n  \"<none>\",\n  FM_Null_Interface_Function,\n  (void (*)(int, int))FM_Null_Interface_Function,\n  FM_Null_Interface_Function,\n  FM_Null_Interface_Function,\n  FM_Null_Interface_Function\n};\n\nt_fm_unit_interface *   FM_Unit_Current = &FM_Null_Interface;\n\n//-----------------------------------------------------------------------------\n\n// Instruments Name (strings)\nconst char *FM_Instruments_Name[YM2413_INSTRUMENTS] =\n{\n  \"User Voice\",\n  \"Violin\",\n  \"Guitar\",\n  \"Piano\",\n  \"Flute\",\n  \"Clarinet\",\n  \"Oboe\",\n  \"Trumpet\",\n  \"Organ\",\n  \"Horn\",\n  \"Synthesizer\",\n  \"Harpsichord\",\n  \"Vibraphone\",\n  \"Synthetizer bass\",\n  \"Acoustic bass\",\n  \"Electric bass\",\n};\n\n//-----------------------------------------------------------------------------\n\n// Mask of Registers data to save for a state save\nconst u8  FM_Regs_SavingFlags[YM2413_REGISTERS] =\n{\n  // Registers\n  // 00-07: user-definable tone channel - left at 0xff for now\n  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n  // 0E:    rhythm mode control - only bit 5 since rest are unused/keys\n  0,    0,    0,    0,    0,    0,    0x20, 0,\n  // 10-18: tone F-number low bits - want all bits\n  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n  // 19-1F: not needed\n  0,    0,    0,    0,    0,    0,    0,\n  // 20-28: tone F-number high bit, octave set, \"key\" & sustain\n  //      0x3f = all\n  //      0x2f = all but key\n  //      0x1f = all but sustain\n  //      0x0f = all but key and sustain\n  0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,\n  // 29-2F: not needed\n  0,    0,    0,    0,    0,    0,    0,\n  // 30-38: instrument number/volume - want all bits\n  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n  // 39: not needed\n  0\n};\n\n// Active given interface\nvoid    FM_Set_Interface(t_fm_unit_interface *intf, byte *new_fm_regs)\n{\n  if (FM_Unit_Current != NULL)\n    FM_Mute();\n\n  if ((new_fm_regs != FM_Regs) && FM_Regs)\n  {\n    // Msg(MSGT_DEBUG, \"%s: Copying FM registers...\", __FUNCTION__);\n    memcpy (new_fm_regs, FM_Regs, YM2413_REGISTERS);\n  }\n\n  FM_Unit_Current = intf;\n  FM_Regs = new_fm_regs;\n  FM_Regenerate();\n}\n\n// Active the dummy/null FM interface\nvoid    FM_Null_Active()\n{\n  // Create a dummy set of register.\n  static u8 FM_OPL_Regs [YM2413_REGISTERS];\n\n  FM_Set_Interface (&FM_Null_Interface, FM_OPL_Regs);\n}\n\nvoid    FM_Save (FILE *f)\n{\n  fwrite (FM_Regs, YM2413_REGISTERS, 1, f);\n}\n\n// Load FM registers from given file pointer and call emulator Reload function\n// Note: only the registers are saved/loaded currently\n// If this has to change, please pay attention to the fact that MSD loading\n// use this fonction to load old Massage save states.\nvoid    FM_Load (FILE *f)\n{\n  fread (FM_Regs, YM2413_REGISTERS, 1, f);\n  FM_Regenerate();\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sound/fmunit.h",
    "content": "//\n// Meka - FMUNIT.H\n// FM Unit - Miscellaneous & wrapper to emulators\n//\n\n#define YM2413_REGISTERS        (64)    // 64 registers area\n#define YM2413_INSTRUMENTS      (16)    // 16 instruments (0 is user defined)\n#define YM2413_VOLUME_STEPS     (16)    // 16 different volume steps\n#define YM2413_VOLUME_MASK      (0x0F)\n\n//-----------------------------------------------------------------------------\n\n// Registers (pointer to current FM emulator register)\nextern u8 *             FM_Regs;\n\n// Instruments Name (strings)\nextern const char *     FM_Instruments_Name [YM2413_INSTRUMENTS];\n\n// Mask of Registers data to save for a state save\nextern const u8         FM_Regs_SavingFlags [YM2413_REGISTERS];\n\n//-----------------------------------------------------------------------------\n// Interface\n//-----------------------------------------------------------------------------\n\nstruct t_fm_unit_interface\n{\n    const char* desc;\n    const char* author;\n    void (*f_reset)     ();\n    void (*f_write)      (int Register, int Value);\n    void (*f_mute)      ();\n    void (*f_resume)    ();\n    void (*f_regenerate)();\n};\n\nvoid    FM_Set_Interface (t_fm_unit_interface *intf, byte *new_fm_regs);\nvoid    FM_Null_Active  ();\n\nextern t_fm_unit_interface* FM_Unit_Current;\n\n//-----------------------------------------------------------------------------\n// Interface Functions Accesses macros\n//-----------------------------------------------------------------------------\n\n#define FM_Reset()      FM_Unit_Current->f_reset()\n#define FM_Write(R,V)   FM_Unit_Current->f_write(R, V);\n#define FM_Mute()       FM_Unit_Current->f_mute()\n#define FM_Resume()     FM_Unit_Current->f_resume()\n#define FM_Regenerate() FM_Unit_Current->f_regenerate()\n\n//-----------------------------------------------------------------------------\n\nvoid    FM_Save(FILE *f);\nvoid    FM_Load(FILE *f);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sound/psg.cpp",
    "content": "//\r\n// Meka - PSG.H\r\n// PSG Emulation, by Maxim\r\n// Tweaked for MEKA\r\n//\r\n\r\n#include \"shared.h\"\r\n#include \"fskipper.h\"\r\n#include \"psg.h\"\r\n#include <limits.h>\r\n\r\n// #define DEBUG_PSG\r\n\r\n/*\r\n//---- Original Header ----\r\n\r\n  SN76489 emulation\r\n  by Maxim in 2001 and 2002\r\n  converted from my original Delphi implementation\r\n\r\n  I'm a C newbie so I'm sure there are loads of stupid things\r\n  in here which I'll come back to some day and redo\r\n\r\n  Includes:\r\n  - Super-high quality tone channel \"oversampling\" by calculating fractional positions on transitions\r\n  - Noise output pattern reverse engineered from actual SMS output\r\n\r\n*/\r\n\r\n// Constants\r\n#define NoiseInitialState           0x4000\r\n#define NoiseWhiteFeedback_SMSGG    0x0009  // Bits 0 and 3\r\n#define NoiseWhiteFeedback_SGSC     0x0006  // Bits 1 and 2\r\n\r\n#define NoiseWhiteFeedback          NoiseWhiteFeedback_SMSGG\r\n\r\nstatic const unsigned short int PSGVolumeValues[16] =\r\n{\r\n\t// These values are taken from a real SMS2's output\r\n\t/*\r\n    892, 892, 892, 760, 623, 497, 404, 323,\r\n    257, 198, 159, 123,  96,  75,  60,   0\r\n\t*/\r\n\t// These values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1)\r\n\t1516, 1205, 957, 760, 603, 479, 381, 303, 240, 191, 152, 120, 96, 76, 60, 0\r\n};\r\n\r\n// Variables\r\nt_psg           PSG;\r\nstatic int      Active = 0;     // Set to true by SN76489_Init(), if false then all procedures exit immediately\r\n\r\n//------------------------------------------------------------------------------\r\n// PSG_Init()\r\n// Initialize audio system for PSG emulation\r\n//-----------------------------------------------------------------------------\r\nint         PSG_Init()\r\n{\r\n    ConsolePrintf (\"%s \", Msg_Get(MSG_Sound_Init_SN76496));\r\n\r\n    // FIXME-NEWSOUND: PSG\r\n    /*\r\n    PSG_saChannel = stream_init (\"SN76496 #0\", g_sasound.audio_sample_rate, 16, 0, PSG_Update);\r\n    if (PSG_saChannel == -1)\r\n    {\r\n        ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Failed));\r\n        return (MEKA_ERR_FAIL);\r\n    }\r\n    stream_set_volume (PSG_saChannel, VOLUME_MAX);\r\n    */\r\n\r\n    for (int i = 0; i < 4; i++)               // FIXME: to be done in sound.c ?\r\n        PSG.Channels[i].Active = TRUE;\r\n    SN76489_Reset (Z80_DEFAULT_CPU_CLOCK, Sound.SampleRate);\r\n\r\n    ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Ok));\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\n//------------------------------------------------------------------------------\r\n// PSG_Update()\r\n// Update audio stream\r\n// This is periodically called by the sound engine\r\n//-----------------------------------------------------------------------------\r\nvoid        PSG_WriteSamples(s16 *buffer, int length)\r\n{\r\n    s16* buf = buffer;\r\n    for (int length_left = length; length_left > 0; length_left--)\r\n    {\r\n        // Get 1 sample from emulator\r\n        int left, right;\r\n        SN76489_GetValues (&left, &right);\r\n\r\n#if SOUND_CHANNEL_COUNT == 1\r\n\r\n        // Combine to mono\r\n        int value = left + right;\r\n\r\n        value = MAX(MIN(value, 0x7fff), -0x8000);\r\n\r\n        *buf++ = value;\r\n\r\n#elif SOUND_CHANNEL_COUNT == 2\r\n\r\n        *buf++ = MAX(MIN(left*2, 0x7fff), -0x8000);\r\n        *buf++ = MAX(MIN(right*2, 0x7fff), -0x8000);\r\n\r\n#else\r\n\r\n        assert(0);\r\n\r\n#endif\r\n    }\r\n\r\n    // Write buffer to file if logging is activated within MEKA\r\n    if (Sound.LogWav)\r\n    {\r\n        fwrite (buffer, sizeof (short) * SOUND_CHANNEL_COUNT, length, Sound.LogWav);\r\n        Sound.LogWav_SizeData += length * sizeof (short) * SOUND_CHANNEL_COUNT;\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// PSG_Save()\r\n// Save PSG state to file\r\n//-----------------------------------------------------------------------------\r\nvoid        PSG_Save (FILE *f)\r\n{\r\n    byte    b;\r\n    word    w;\r\n    int     i;\r\n\r\n    // PSG Data\r\n    fwrite (PSG.Registers, 8, sizeof (word), f);\r\n    b = PSG.LatchedRegister;\r\n    fwrite (&b,            1, sizeof (byte), f);\r\n    b = PSG.Stereo;\r\n    fwrite (&b,            1, sizeof (byte), f);\r\n    w = PSG.NoiseShiftRegister;\r\n    fwrite (&w,            1, sizeof (word), f);\r\n\r\n    // Implementation Data\r\n    for (i = 0; i < 4; i++)\r\n    {\r\n        fwrite (&PSG.Channels[i].ToneFreqVal,     1, sizeof (signed short int), f);\r\n        fwrite (&PSG.Channels[i].ToneFreqPos,     1, sizeof (signed char),      f);\r\n        fwrite (&PSG.Channels[i].IntermediatePos, 1, sizeof (signed long int),  f);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// PSG_Load()\r\n// Load PSG state from a file\r\n//-----------------------------------------------------------------------------\r\nvoid        PSG_Load (FILE *f, int version)\r\n{\r\n    int     i;\r\n\r\n    // PSG Registers\r\n    fread (PSG.Registers, 8, sizeof (word), f);\r\n    if (version < 0x0B)\r\n    {\r\n        // Legagy Loading\r\n        char dummy_buffer[5];\r\n        fread (dummy_buffer, 4+1, sizeof (char), f);\r\n        PSG.LatchedRegister = 0;\r\n        PSG.Stereo = 0xFF;\r\n        PSG.NoiseShiftRegister = NoiseInitialState;\r\n        for (i = 0; i < 4; i++)\r\n        {\r\n            // Fixup zero frequencies (FIXME: this is implementation dependant!)\r\n            if (i < 3)\r\n                if (PSG.Registers[i * 2] == 0)\r\n                    PSG.Registers[i * 2] = 1;\r\n            // Set counters to 0\r\n            PSG.Channels[i].ToneFreqVal = 0;\r\n            // Set flip-flops to 1\r\n            PSG.Channels[i].ToneFreqPos = 1;\r\n            // Set intermediate positions to do-not-use value\r\n            PSG.Channels[i].IntermediatePos = LONG_MIN;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        byte b;\r\n        word w;\r\n\r\n        // PSG Data\r\n        fread (&b, 1, sizeof (byte), f);\r\n        PSG.LatchedRegister = b;\r\n        fread (&b, 1, sizeof (byte), f);\r\n        PSG.Stereo = b;\r\n        fread (&w, 1, sizeof (word), f);\r\n        PSG.NoiseShiftRegister = w;\r\n        // Implemention Data\r\n        for (i = 0; i < 4; i++)\r\n        {\r\n            fread (&PSG.Channels[i].ToneFreqVal,     1, sizeof (signed short int), f);\r\n            fread (&PSG.Channels[i].ToneFreqPos,     1, sizeof (signed char),      f);\r\n            fread (&PSG.Channels[i].IntermediatePos, 1, sizeof (signed long int),  f);\r\n        }\r\n    }\r\n    PSG_Regenerate();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// PSG_Regenerate()\r\n// Regenerate various PSG data from registers\r\n// This is called after a PSG state loading\r\n//-----------------------------------------------------------------------------\r\nvoid        PSG_Regenerate()\r\n{\r\n    // Set channels volume\r\n    for (int i = 0; i < 4; i++)\r\n        PSG.Channels[i].Volume = PSGVolumeValues[PSG.Registers[i*2+1] & 0x0F];\r\n\r\n    // Set noise signal generator frequency\r\n    PSG.NoiseFreq = 0x10 << (PSG.Registers[6] & 0x3);\r\n}\r\n\r\n// Mute PSG by setting all Volumes to 15\r\nvoid        PSG_Mute()\r\n{\r\n    SN76489_Write (0x9F); // Channel 0 Volume 15\r\n    SN76489_Write (0xBF); // Channel 1 Volume 15\r\n    SN76489_Write (0xDF); // Channel 2 Volume 15\r\n    SN76489_Write (0xFF); // Channel 3 Volume 15\r\n}\r\n\r\n// Initialise and reset emulated PSG, given clock and sampling rate\r\nvoid        SN76489_Reset(const unsigned long PSGClockValue, const unsigned long SamplingRate)\r\n{\r\n    // Probably unnecessarily verbose\r\n    Active = (PSGClockValue > 0);\r\n    if (!Active) return;\r\n\r\n    PSG.SamplingRate = SamplingRate;\r\n    PSG.Clock = 0.0f;\r\n    PSG.dClock = (float)PSGClockValue / (16 * SamplingRate);\r\n\r\n    PSG.LatchedRegister = 0;        // Tone0 is latched on startup\r\n    PSG.Stereo = 0xFF;\r\n\r\n    // Setup default channels parameters\r\n    for (int i = 0; i < 4; i++)\r\n    {\r\n        t_psg_channel*c = &PSG.Channels[i];\r\n\r\n        // Set all frequencies to 1\r\n        PSG.Registers[i * 2 + 0] = 1;\r\n        // Set volumes to off (0xf)\r\n        PSG.Registers[i * 2 + 1] = 0xF;\r\n        c->Volume = 0;\r\n        // Set counters to 0\r\n        c->ToneFreqVal = 0;\r\n        // Set flip-flops to 1\r\n        c->ToneFreqPos = 1;\r\n        // Set intermediate positions to do-not-use value\r\n        c->IntermediatePos = LONG_MIN;\r\n    }\r\n\r\n    // Noise channels default parameters\r\n    PSG.NoiseFreq = 0x10;\r\n    PSG.NoiseShiftRegister = NoiseInitialState;\r\n}\r\n\r\n// Set PSG clock based on master CPU clock\r\nvoid    SN76489_SetClock(const unsigned long PSGClockValue)\r\n{\r\n    PSG.dClock = (float)PSGClockValue / (16 * PSG.SamplingRate);\r\n}\r\n\r\n//------------------------------------------------------------------------------\r\n// SN76489_Write()\r\n// IO Write to PSG\r\n//------------------------------------------------------------------------------\r\nvoid        SN76489_Write(const unsigned char data)\r\n{\r\n    // VGM Logging\r\n    if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\r\n        VGM_Data_Add_PSG (&Sound.LogVGM, (byte)data);\r\n\r\n    if (!Active) return;\r\n\r\n    #ifdef DEBUG_PSG\r\n    {\r\n        char bf[9];\r\n        StrWriteBitfield (data, 8, bf);\r\n        //Msg(MSGT_DEBUG, \"%04X [%d] @ PSG Write %02X / %s (Latched = %d)\", CPU_GetPC, sms.Pages_Reg [1], data, bf, PSG.LatchedRegister);\r\n        Msg(MSGT_DEBUG, \"%04X @ PSG Write %02X / %s (Latched = %d)\", CPU_GetPC, data, bf, PSG.LatchedRegister);\r\n    }\r\n    #endif\r\n\r\n    // Update the output buffer before changing the registers\r\n    SoundStream_RenderUpToCurrentTime(g_psg_stream);\r\n\r\n    if (data & 0x80)\r\n    {\r\n        // Latch/data byte '1cctdddd'\r\n        PSG.LatchedRegister = ((data >> 4) & 0x07);\r\n        // Replace low 4 bits in registers with new data\r\n        PSG.Registers[PSG.LatchedRegister] = (PSG.Registers[PSG.LatchedRegister] & 0x3F0) | (data & 0x0F);\r\n        if (PSG.LatchedRegister & 1)\r\n            PSG.Channels[PSG.LatchedRegister >> 1].Volume = PSGVolumeValues[data & 0x0F];\r\n        #ifdef DEBUG_PSG\r\n            Msg(MSGT_DEBUG, \"%04X @ PSG.Regs[%d] = %04X\", CPU_GetPC, PSG.LatchedRegister, PSG.Registers[PSG.LatchedRegister]);\r\n        #endif\r\n    }\r\n    else\r\n    {\r\n        // Data byte '0-dddddd'\r\n        switch (PSG.LatchedRegister)\r\n        {\r\n        case 0:\r\n        case 2: // Tone Frequency Registers\r\n        case 4: // Replace high 6 bits with data\r\n            PSG.Registers[PSG.LatchedRegister] = (PSG.Registers[PSG.LatchedRegister] & 0x00F) | ((data & 0x3F) << 4);\r\n            break;\r\n        case 6: // Noise Frequency / Settings\r\n            PSG.Registers[PSG.LatchedRegister] = data & 0x0F;\r\n            break;\r\n        case 1:\r\n        case 3:\r\n        case 5:\r\n        case 7: // Volumes\r\n            PSG.Registers[PSG.LatchedRegister] = data & 0x0F;\r\n            PSG.Channels[PSG.LatchedRegister >> 1].Volume = PSGVolumeValues[data & 0x0F];\r\n            break;\r\n        }\r\n        #ifdef DEBUG_PSG\r\n            Msg(MSGT_DEBUG, \"%04X @ PSG.Regs[%d] = %04X\", CPU_GetPC, PSG.LatchedRegister, PSG.Registers[PSG.LatchedRegister]);\r\n        #endif\r\n    }\r\n\r\n    switch (PSG.LatchedRegister)\r\n    {\r\n    case 0:\r\n    case 2:\r\n    case 4: // Tone Channels\r\n        if (PSG.Registers[PSG.LatchedRegister] == 0)\r\n            PSG.Registers[PSG.LatchedRegister] = 1;         // Zero frequency changed to 1 to avoid div/0 // FIXME\r\n        break;\r\n    case 6: // Noise\r\n        PSG.NoiseShiftRegister = NoiseInitialState;        // Reset shift register\r\n        PSG.NoiseFreq = 0x10 << (PSG.Registers[6] & 0x3);  // Set noise signal generator frequency\r\n        break;\r\n    }\r\n\r\n    /*\r\n    Msg(MSGT_DEBUG, \" Now Latched = %d\", PSG.LatchedRegister);\r\n    */\r\n};\r\n\r\n//------------------------------------------------------------------------------\r\n// SN76489_StereoWrite()\r\n// Write to the stereo register (as used on the Game Gear)\r\n//------------------------------------------------------------------------------\r\nvoid    SN76489_StereoWrite(const unsigned char data)\r\n{\r\n    if (!Active) return;\r\n    PSG.Stereo = data;\r\n};\r\n\r\n//------------------------------------------------------------------------------\r\n// SN76489_GetValues()\r\n// Write synthetised values for left and right channels to given addresses\r\n// result_right can be NULL if stereo is unwanted\r\n// FIXME: This may not be the task of the synthetiser to take care of Stereo\r\n//------------------------------------------------------------------------------\r\nvoid    SN76489_GetValues(int *result_left, int *result_right)\r\n{\r\n    signed short int Channels[4]; // Value of each channel, before stereo is applied\r\n\r\n    if (!Active) return;\r\n\r\n    // Tone channels\r\n    t_psg_channel* c = &PSG.Channels[0];\r\n    for (int i = 0; i <= 2; i++, c++)\r\n    {\r\n        if (c->Active == FALSE)\r\n        {\r\n            Channels[i] = 0;\r\n            continue;\r\n        }\r\n        if (c->IntermediatePos != LONG_MIN)\r\n            Channels[i] = (c->Volume * c->IntermediatePos) >> 16;\r\n        else\r\n            Channels[i] = c->Volume * c->ToneFreqPos;\r\n    }\r\n    // Noise channel\r\n    if (c->Active == FALSE)\r\n        Channels[3] = 0;\r\n    else\r\n        Channels[3] = (short)(2 * c->Volume * (PSG.NoiseShiftRegister & 0x1));\r\n\r\n    // Mix and output result\r\n    if (result_right == NULL)\r\n    {\r\n        *result_left = Channels[0] + Channels[1] + Channels[2] + Channels[3];\r\n    }\r\n    else\r\n    {\r\n        int mix = 0;\r\n        if (PSG.Stereo & 0x10)     mix += Channels[0];\r\n        if (PSG.Stereo & 0x20)     mix += Channels[1];\r\n        if (PSG.Stereo & 0x40)     mix += Channels[2];\r\n        if (PSG.Stereo & 0x80)     mix += Channels[3];\r\n        *result_left = mix;\r\n        if (((PSG.Stereo & 0xF0) >> 4) == (PSG.Stereo & 0x0F))\r\n        {\r\n            *result_right = mix;\r\n        }\r\n        else\r\n        {\r\n            mix = 0;\r\n            if (PSG.Stereo & 0x01)  mix += Channels[0];\r\n            if (PSG.Stereo & 0x02)  mix += Channels[1];\r\n            if (PSG.Stereo & 0x04)  mix += Channels[2];\r\n            if (PSG.Stereo & 0x08)  mix += Channels[3];\r\n            *result_right = mix;\r\n        }\r\n    }\r\n\r\n    // Update Clock\r\n    PSG.Clock += PSG.dClock;\r\n    PSG.NumClocksForSample = PSG.Clock;           // Truncates\r\n    PSG.Clock -= PSG.NumClocksForSample;          // Remove integer part\r\n\r\n    // Decrement tone channel counters\r\n    for (int i = 0; i <= 2; i++)\r\n        PSG.Channels[i].ToneFreqVal -= PSG.NumClocksForSample;\r\n\r\n    // Noise channel: match to tone2 or decrement its counter\r\n    if (PSG.NoiseFreq == 0x80)\r\n        PSG.Channels[3].ToneFreqVal = PSG.Channels[2].ToneFreqVal;\r\n    else\r\n        PSG.Channels[3].ToneFreqVal -= PSG.NumClocksForSample;\r\n\r\n    // Value below which PSG does not output\r\n#define PSG_CUTOFF 0x6\r\n\r\n    // Tone channels:\r\n    c = &PSG.Channels[0];\r\n    for (int i = 0; i <= 2; i++, c++)\r\n    {\r\n        if (c->ToneFreqVal <= 0)  // If it gets below 0...\r\n        {\r\n            int ToneFreq = PSG.Registers[i * 2 + 0];\r\n\r\n            // FIXME [Omar] This is because asynchronous calls of this while PSG is being\r\n            // acessed on the main thread sometimes screw up this.\r\n            if (ToneFreq == 0)\r\n                ToneFreq = 1;\r\n\r\n            if (ToneFreq > PSG_CUTOFF)\r\n            {\r\n                // Calculate how much of the sample is + and how much is -\r\n                // Go to floating point and include the clock fraction for extreme accuracy :D\r\n                // Store as long int, maybe it's faster? I'm not very good at this\r\n                c->IntermediatePos = (long)\r\n                    (\r\n                    (PSG.NumClocksForSample - PSG.Clock + 2 * c->ToneFreqVal)\r\n                    * c->ToneFreqPos / (PSG.NumClocksForSample + PSG.Clock)\r\n                    * 65636\r\n                    );\r\n                c->ToneFreqPos = -c->ToneFreqPos;   // Flip the flip-flop\r\n            }\r\n            else\r\n            {\r\n                c->ToneFreqPos = 1;                 // Stuck value\r\n                c->IntermediatePos = LONG_MIN;\r\n            };\r\n            c->ToneFreqVal += ToneFreq * (PSG.NumClocksForSample / ToneFreq+1);\r\n        }\r\n        else\r\n        {\r\n            c->IntermediatePos = LONG_MIN;\r\n        }\r\n    };\r\n\r\n    // Noise channel\r\n    if (c->ToneFreqVal <= 0)              // If it gets below 0...\r\n    {\r\n        c->ToneFreqPos = -c->ToneFreqPos;  // Flip the flip-flop\r\n        if (PSG.NoiseFreq != 0x80)         // If not matching tone2, decrement counter\r\n            c->ToneFreqVal += PSG.NoiseFreq * (PSG.NumClocksForSample / PSG.NoiseFreq+1);\r\n        if (c->ToneFreqPos == 1)\r\n        {\r\n            // Only once per cycle...\r\n            // General method:\r\n            /*\r\n            int Feedback = 0;\r\n            if (PSG.Registers[6] & 0x04)\r\n            { // For white noise:\r\n            int i;            // Calculate the XOR of the tapped bits for feedback\r\n            unsigned short int tapped = PSG.NoiseShiftRegister & NoiseWhiteFeedback;\r\n            for (i = 0; i < 16; i++)\r\n            Feedback += (tapped >> i) & 1;\r\n            Feedback &= 1;\r\n            }\r\n            else\r\n            {\r\n            Feedback = PSG.NoiseShiftRegister & 1; // For periodic: feedback=output\r\n            PSG.NoiseShiftRegister = (PSG.NoiseShiftRegister >> 1) | (Feedback << 15);\r\n            }\r\n            */\r\n\r\n            // SMS-only method, probably a bit faster:\r\n            int Feedback = 0;\r\n            if (PSG.Registers[6] & 0x04)  // White Noise\r\n                Feedback = ((PSG.NoiseShiftRegister & 0x9) && ((PSG.NoiseShiftRegister & 0x9) ^ 0x9));\r\n            else    // Periodic Noise\r\n                Feedback = PSG.NoiseShiftRegister & 1;    // For periodic: feedback=output\r\n            PSG.NoiseShiftRegister = (PSG.NoiseShiftRegister >> 1) | (Feedback << 15);\r\n        }\r\n    };\r\n};\r\n\r\n"
  },
  {
    "path": "meka/srcs/sound/psg.h",
    "content": "//\n// Meka - PSG.H\n// PSG Emulation, by Maxim\n// Tweaked for MEKA\n//\n\n//-----------------------------------------------------------------------------\n\nint     PSG_Init();\nvoid    PSG_WriteSamples(s16 *buffer, int length);\nvoid    PSG_Reset();\nvoid    PSG_Save(FILE *f);\nvoid    PSG_Load(FILE *f, int version);\nvoid    PSG_Regenerate();\nvoid    PSG_Mute();\n\n//-----------------------------------------------------------------------------\n\nstruct t_psg_channel\n{\n    signed short int    ToneFreqVal;            // Frequency register values (counters)\n    signed       char   ToneFreqPos;            // Frequency channel flip-flops\n    signed long  int    IntermediatePos;        // Intermediate values used at boundaries between + and -\n  unsigned short int  Volume;                 // Current channel volume (0-900+...)\n                 int    Active;                 // Set to 0 to mute\n};\n\nstruct t_psg\n{\n  t_psg_channel         Channels[4];            //\n  unsigned short int  Registers[8];           //\n                 int    LatchedRegister;        //\n  unsigned       char   Stereo;                 //\n  unsigned short int    NoiseShiftRegister;     //\n    signed short int  NoiseFreq;              // regenerate\n                 float  Clock;\n                 float  dClock;\n  unsigned       int    NumClocksForSample;\n                 int    SamplingRate;           // fixed\n};\n\nextern t_psg            PSG;\n\n//-----------------------------------------------------------------------------\n\nvoid    SN76489_Reset           (const unsigned long PSGClockValue, const unsigned long SamplingRate);\nvoid    SN76489_SetClock        (const unsigned long PSGClockValue);\nvoid    SN76489_Write           (const unsigned char data);\nvoid    SN76489_StereoWrite     (const unsigned char data);\nvoid    SN76489_GetValues       (int *left, int *right);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sound/s_misc.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - S_MISC.C\r\n// Sound Miscellaneous - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"psg.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void     Sound_Volume_Menu_Handler(t_menu_event *event);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nint     Sound_Rate_Default_Table[] =\r\n{\r\n    22050,\r\n    44100,\r\n    -1\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    FM_Disable()\r\n{\r\n    Sound.FM_Enabled = FALSE;\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_FM_Disabled));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Must_Reset));\r\n    gui_menu_uncheck_range (menus_ID.fm, 0, 1);\r\n    gui_menu_check (menus_ID.fm, 1);\r\n}\r\n\r\nvoid    FM_Enable()\r\n{\r\n    Sound.FM_Enabled = TRUE;\r\n    Msg(MSGT_USER, \"%s\", Msg_Get(MSG_FM_Enabled));\r\n    Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Must_Reset));\r\n    gui_menu_uncheck_range (menus_ID.fm, 0, 1);\r\n    gui_menu_check (menus_ID.fm, 0);\r\n}\r\n\r\n// SOUND->VOLUME menu ---------------------------------------------------------\r\n\r\nvoid    Sound_Volume_Menu_Init(int menu_id)\r\n{\r\n    const int master_volume_100 = (float)Sound.MasterVolume * ((float)100 / 128);\r\n    for (int i = 0; i <= 100; i += 20)\r\n    {\r\n        char buffer[256];\r\n        if (i == 0)\r\n            snprintf(buffer, countof(buffer), \"%s\", Msg_Get(MSG_Menu_Sound_Volume_Mute));\r\n        else\r\n            snprintf(buffer, countof(buffer), Msg_Get(MSG_Menu_Sound_Volume_Value), i);\r\n        menu_add_item(menu_id, buffer, NULL, Is_Checked(i - 9 < master_volume_100 && i + 9 > master_volume_100),\r\n            (t_menu_callback)Sound_Volume_Menu_Handler, (void *)(int)((float)i * ((float)128 / 100)));\r\n    }\r\n}\r\n\r\nvoid    Sound_Volume_Menu_Handler(t_menu_event *event)\r\n{\r\n    const int volume = (long int)event->user_data;\r\n\r\n    Sound_SetMasterVolume(volume);\r\n    Msg(MSGT_USER /*_BOX*/, Msg_Get(MSG_Sound_Volume_Changed), volume);\r\n    gui_menu_uncheck_all (menus_ID.volume);\r\n    gui_menu_check (menus_ID.volume, event->menu_item_idx);\r\n}\r\n\r\n// SOUND->CHANNELS menu -------------------------------------------------------\r\n\r\nvoid    Sound_Channels_Menu_Handler(t_menu_event *event)\r\n{\r\n    const int channel_idx = (long int)event->user_data;\r\n\r\n    PSG.Channels[channel_idx].Active ^= 1;\r\n    gui_menu_toggle_check (menus_ID.channels, channel_idx);\r\n}\r\n\r\n"
  },
  {
    "path": "meka/srcs/sound/s_misc.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - S_MISC.C\r\n// Sound Miscellaneous - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifndef __S_MISC_H__\r\n#define __S_MISC_H__\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nextern int  Sound_Rate_Default_Table[];\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    FM_Disable();\r\nvoid    FM_Enable();\r\n\r\nvoid    Sound_Volume_Menu_Init          (int menu_id);\r\n\r\nvoid    Sound_Channels_Menu_Handler     (t_menu_event *event);\r\n\r\n#endif /* __S_MISC_H__ */\r\n\r\n"
  },
  {
    "path": "meka/srcs/sound/sound.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - sound.c\r\n// Sound Engine - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"fmunit.h\"\r\n#include \"psg.h\"\r\n#include \"emu2413/mekaintf.h\"\r\n#include \"sound_logging.h\"\r\n#include \"desktop.h\"\r\n#include \"g_widget.h\"\r\n#include \"tvtype.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// FORWARD DECLARATIONS\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic bool Sound_InitEmulators();\r\n\r\n//-----------------------------------------------------------------------------\r\n// DATA\r\n//-----------------------------------------------------------------------------\r\n\r\nenum t_sound_chip\r\n{\r\n    SOUND_CHIP_PSG,\r\n    SOUND_CHIP_FM,\r\n};\r\n\r\nstruct t_sound_stream\r\n{\r\n    t_sound_chip            chip;\r\n    ALLEGRO_EVENT_QUEUE *   event_queue;\r\n    ALLEGRO_AUDIO_STREAM *  audio_stream;\r\n    s16 *                   audio_buffer;\r\n    int                     audio_buffer_size;\r\n    int                     audio_buffer_wpos;  // write position for chip emulator \r\n    int                     audio_buffer_rpos;  // read position for audio system\r\n    void                    (*sample_writer)(s16*,int);\r\n\r\n    // Counters\r\n    double                  samples_leftover;\r\n    int                     samples_rendered0;\r\n    int                     samples_rendered1;\r\n    s64                     last_rendered_cycle_counter;\r\n};\r\n\r\nt_sound         Sound;\r\nt_sound_stream* g_psg_stream = NULL;\r\nt_sound_stream* g_ym2413_stream = NULL;\r\n\r\nstruct t_app_sound_debug\r\n{\r\n    t_gui_box*  box;\r\n    bool        active;\r\n};\r\n\r\nstatic t_app_sound_debug    SoundDebugApp;\r\n\r\n//-----------------------------------------------------------------------------\r\n// FUNCTIONS\r\n//-----------------------------------------------------------------------------\r\n\r\n// Initialize sound structure with its default settings\r\nvoid    Sound_Init_Config()\r\n{\r\n    // General\r\n    Sound.Enabled       = TRUE;\r\n    Sound.Initialized   = FALSE;\r\n    Sound.SampleRate    = 44100;                  // 44100 Hz by default\r\n    Sound.Paused        = 0;\r\n    Sound.MasterVolume  = 128;\r\n    Sound.CycleCounter  = 0;\r\n\r\n    // Sound Logging\r\n    Sound_Log_Init();\r\n}\r\n\r\n// Initialize actual sound engine ---------------------------------------------\r\nint     Sound_Init()\r\n{\r\n    // Temporarily set fake/null FM interface\r\n    // This is to avoid crashing when using FM registers (savestates...) if sound is disabled.\r\n    FM_Null_Active();\r\n\r\n    // Skip if there is no need to initialize sound now\r\n    // FIXME: Does MEKA works properly with no soundcard, is the machine updating registters properly and saving good savestates ?\r\n    if (Sound.Enabled == FALSE)\r\n        return (MEKA_ERR_OK);\r\n\r\n    // Print Sound initialization message\r\n    ConsolePrintf (\"%s\\n\", Msg_Get(MSG_Sound_Init));\r\n    ConsolePrintf (Msg_Get(MSG_Sound_Init_Soundcard), Sound.SampleRate);\r\n\r\n    if (!al_install_audio())\r\n    {\r\n        Quit_Msg(\"%s\", Msg_Get(MSG_Sound_Init_Error_Audio));\r\n        return (MEKA_ERR_FAIL);\r\n    }\r\n    if (!al_reserve_samples(0))\r\n    {\r\n        Quit_Msg(\"%s\", Msg_Get(MSG_Sound_Init_Error_Audio));\r\n        return (MEKA_ERR_FAIL);\r\n    }\r\n    ConsolePrintf (\"\\n\");\r\n\r\n    // Initialize Sound card\r\n    // Start in pause mode, to avoid sound update on startup (could crash, before everything is initialized)\r\n    Sound.Paused = TRUE;\r\n\r\n    // Initialize Sound emulators\r\n    if (!Sound_InitEmulators())\r\n    {\r\n        Quit_Msg(\"%s\", Msg_Get(MSG_Sound_Init_Error_Audio));\r\n        return (MEKA_ERR_FAIL);\r\n    }\r\n\r\n    Sound_UpdateClockSpeed();\r\n\r\n    Sound.Initialized = TRUE;\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\n/* static void SawSampleWrite(s16* buf, int len)\r\n{\r\n    static int val = 0;\r\n    static int pitch = 0x10000;\r\n    for (int i = 0; i < ken; i++) \r\n    {\r\n        buf[i] = ((val >> 16) & 0xff)*100;\r\n        val += pitch;\r\n        pitch++;\r\n    }\r\n}*/\r\n\r\nstatic bool Sound_InitEmulators()\r\n{\r\n    PSG_Init();\r\n    g_psg_stream = SoundStream_Create(PSG_WriteSamples);\r\n    if (!g_psg_stream)\r\n        return false;\r\n\r\n    FM_Digital_Init();\r\n    FM_Digital_Active();\r\n    g_ym2413_stream = SoundStream_Create(FM_Digital_WriteSamples);\r\n    if (!g_ym2413_stream)\r\n        return false;\r\n\r\n    return true;\r\n}\r\n\r\nvoid    Sound_Close()\r\n{\r\n    FM_Digital_Close();\r\n\r\n    if (!Sound.Initialized)\r\n        return;\r\n\r\n    Sound_Log_Close();\r\n    SoundStream_Destroy(g_psg_stream);\r\n    SoundStream_Destroy(g_ym2413_stream);\r\n    al_uninstall_audio();\r\n    Sound.Initialized = FALSE;\r\n}\r\n\r\nvoid    Sound_UpdateClockSpeed()\r\n{\r\n    const double throttle_scale = 1.0f;//(double)fskipper.Throttled_Speed / (double)g_machine.TV->screen_frequency;\r\n    //Sound.CpuClock = g_machine.TV->CPU_clock;\r\n    Sound.CpuClock = CPU_GetIPeriod() * g_machine.TV->screen_lines * g_machine.TV->screen_frequency;\r\n    SN76489_SetClock((double)Sound.CpuClock * throttle_scale);\r\n    // FIXME-NEWSOUND: FM?\r\n}\r\n\r\nvoid    Sound_Update()\r\n{\r\n    if (!Sound.Enabled)\r\n        return;\r\n\r\n    static int frame_count = 0;\r\n    if ((frame_count++ % 60) == 0)\r\n    {\r\n        if (SoundDebugApp.active)\r\n            Msg(MSGT_DEBUG, \"Tick, samples rendered %d %d\", g_psg_stream->samples_rendered0, g_psg_stream->samples_rendered1);\r\n        g_psg_stream->samples_rendered0 = 0;\r\n        g_psg_stream->samples_rendered1 = 0;\r\n    }\r\n    SoundStream_Update(g_psg_stream);\r\n    SoundStream_Update(g_ym2413_stream);\r\n}\r\n\r\nvoid    Sound_Playback_Start()\r\n{\r\n    Sound.Paused = TRUE;\r\n    Sound_Playback_Resume();\r\n}\r\n\r\nvoid    Sound_Playback_Stop()\r\n{\r\n    Sound.Paused = FALSE;\r\n    Sound_Playback_Mute();\r\n}\r\n\r\n// Mute sound playback\r\n// Increase 'Sound.Paused' counter and mute sound on >= 1\r\nvoid    Sound_Playback_Mute()\r\n{\r\n    if (Sound.Paused == 0)\r\n    {\r\n        FM_Mute();\r\n    }\r\n    Sound.Paused++;\r\n}\r\n\r\n// Resume sound playback\r\n// Decrease Sound.Paused counter and resume sound on zero\r\nvoid    Sound_Playback_Resume()\r\n{\r\n    Sound.Paused--;\r\n    if (Sound.Paused == 0)\r\n    {\r\n        FM_Resume();\r\n    }\r\n}\r\n\r\n// Change Master Volume (0-128)\r\nvoid    Sound_SetMasterVolume(int volume)\r\n{\r\n    Sound.MasterVolume = volume;\r\n    // FIXME-NEWSOUND: Master volume\r\n}\r\n\r\nvoid Sound_ResetCycleCounter()\r\n{\r\n    Sound.CycleCounter = 0;\r\n    Sound_UpdateClockSpeed();\r\n    if (g_psg_stream)\r\n        g_psg_stream->last_rendered_cycle_counter = 0;\r\n    if (g_ym2413_stream)\r\n        g_ym2413_stream->last_rendered_cycle_counter = 0;\r\n}\r\n\r\ns64 Sound_GetElapsedCycleCounter()\r\n{\r\n    // Calculate current CPU time\r\n    const int icount = CPU_GetICount(); // - Sound_Update_Count;\r\n    const int iperiod = CPU_GetIPeriod();\r\n\r\n    // iperiod : 228\r\n    // iperiod : 228.. 227.. 226.. [..] .. 3.. 2.. 1.. 0..\r\n    // Cycle elapsed in the period : iperiod-icount\r\n    // Cycle left in the period    : icount\r\n    return Sound.CycleCounter + (iperiod - icount);\r\n}\r\n\r\ndouble Sound_ConvertSamplesToCycles(double samples_count)\r\n{\r\n    return samples_count * (double)Sound.CpuClock / (double)Sound.SampleRate;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nt_sound_stream* SoundStream_Create(void (*sample_writer)(s16*,int))\r\n{\r\n    t_sound_stream* stream = new t_sound_stream();\r\n    stream->event_queue = al_create_event_queue();\r\n\r\n#if SOUND_CHANNEL_COUNT == 1\r\n    const ALLEGRO_CHANNEL_CONF channelConf = ALLEGRO_CHANNEL_CONF_1;\r\n#elif SOUND_CHANNEL_COUNT == 2\r\n    const ALLEGRO_CHANNEL_CONF channelConf = ALLEGRO_CHANNEL_CONF_2;\r\n#else\r\n    assert(0);\r\n#endif\r\n\r\n    stream->audio_stream = al_create_audio_stream(SOUND_BUFFERS_COUNT, SOUND_BUFFERS_SAMPLE_COUNT, Sound.SampleRate, ALLEGRO_AUDIO_DEPTH_INT16, channelConf);\r\n    if (!stream->audio_stream)\r\n    {\r\n        delete stream;\r\n        return NULL;\r\n    }\r\n    if (!al_attach_audio_stream_to_mixer(stream->audio_stream, al_get_default_mixer()))\r\n    {\r\n        delete stream;\r\n        return NULL;\r\n    }\r\n    al_register_event_source(stream->event_queue, al_get_audio_stream_event_source(stream->audio_stream));\r\n\r\n    stream->audio_buffer_size = SOUND_BUFFERS_SAMPLE_COUNT*SOUND_BUFFERS_COUNT*SOUND_CHANNEL_COUNT;\r\n    stream->audio_buffer = new s16[stream->audio_buffer_size];\r\n    stream->audio_buffer_wpos = 0;\r\n    stream->audio_buffer_rpos = 0;\r\n    stream->sample_writer = sample_writer;\r\n\r\n    stream->samples_leftover = 0.0f;\r\n    stream->samples_rendered0 = 0;\r\n    stream->samples_rendered1 = 0;\r\n    stream->last_rendered_cycle_counter = 0;\r\n\r\n    return stream;\r\n}\r\n\r\nvoid SoundStream_Destroy(t_sound_stream* stream)\r\n{\r\n    al_destroy_audio_stream(stream->audio_stream);\r\n    delete [] stream->audio_buffer;\r\n    al_destroy_event_queue(stream->event_queue);\r\n    delete stream;\r\n}\r\n\r\nvoid SoundStream_Update(t_sound_stream* stream)\r\n{\r\n    ALLEGRO_EVENT sound_event;\r\n    while (al_get_next_event(stream->event_queue, &sound_event))\r\n    {\r\n        if (sound_event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT)\r\n        {\r\n            s16* buf = (s16*)al_get_audio_stream_fragment(stream->audio_stream);\r\n            if (!buf)\r\n                continue;\r\n\r\n            // Need to catch up?\r\n            if (SoundStream_CountReadableSamples(stream) < SOUND_BUFFERS_SAMPLE_COUNT)\r\n            {\r\n                SoundStream_RenderSamples(stream, SOUND_BUFFERS_SAMPLE_COUNT);\r\n                /*Msg(MSGT_DEBUG, \"Sound catchup by %d samples\", SOUND_BUFFERS_SIZE);\r\n                Msg(MSGT_DEBUG, \"%lld -> %lld, %lld + %.2f = %lld\",\r\n                    stream->last_rendered_cycle_counter, Sound_GetElapsedCycleCounter(),\r\n                    stream->last_rendered_cycle_counter, (float)Sound_ConvertSamplesToCycles(SOUND_BUFFERS_SIZE),\r\n                    (s64)(stream->last_rendered_cycle_counter + (float)Sound_ConvertSamplesToCycles(SOUND_BUFFERS_SIZE)) );\r\n                    */\r\n                stream->last_rendered_cycle_counter = Sound_GetElapsedCycleCounter();\r\n                //stream->last_rendered_cycle_counter += Sound_ConvertSamplesToCycles(SOUND_BUFFERS_SIZE);\r\n            }\r\n\r\n            SoundStream_PopSamples(stream, buf, SOUND_BUFFERS_SAMPLE_COUNT);\r\n\r\n            if (!al_set_audio_stream_fragment(stream->audio_stream, buf))\r\n                Msg(MSGT_DEBUG, \"Error in al_set_audio_stream_fragment()\");\r\n        }\r\n    }\r\n}\r\n\r\nvoid SoundStream_RenderSamples(t_sound_stream* stream, int samples_count)\r\n{\r\n    //Msg(MSGT_DEBUG, \"RenderSamples() %d\", samples_count);\r\n    if (samples_count <= 0)\r\n    {\r\n        Msg(MSGT_DEBUG, \"RenderSamples %d\", samples_count);\r\n        return;\r\n    }\r\n\r\n    stream->samples_rendered0 += samples_count;\r\n\r\n    // We render the number of samples Allegro wants - this may end up crossing the end of the buffer,\r\n    // so we may need to do it in two chunks.\r\n    s16* wbuf1;\r\n    s16* wbuf2;\r\n    int wbuf1_samples_count;\r\n    int wbuf2_samples_count;\r\n    if (SoundStream_PushSamplesRequestBufs(stream, samples_count, &wbuf1, &wbuf1_samples_count, &wbuf2, &wbuf2_samples_count))\r\n    {\r\n        if (wbuf1)\r\n            stream->sample_writer(wbuf1, wbuf1_samples_count);\r\n        if (wbuf2 && wbuf2_samples_count > 0)\r\n            stream->sample_writer(wbuf2, wbuf2_samples_count);\r\n        stream->samples_rendered1 += wbuf1_samples_count + wbuf2_samples_count;\r\n    }\r\n}\r\n\r\nvoid SoundStream_RenderUpToCurrentTime(t_sound_stream* stream)\r\n{\r\n    if (!Sound.Enabled)\r\n        return;\r\n\r\n    s64 current_cycle = Sound_GetElapsedCycleCounter();\r\n    s64 elapsed_cycles = current_cycle - stream->last_rendered_cycle_counter;\r\n\r\n    //elapsed_cycles = MIN(elapsed_cycles, 10000000);   // FIXME-NEWSOUND: how to handle pause, etc?\r\n\r\n    // Convert elapsed cycles in 'frames' unit\r\n    const int cpu_clock = Sound.CpuClock;\r\n    const double elapsed_emulated_seconds = (double)((double)elapsed_cycles / (double)cpu_clock);\r\n\r\n    const double samples_to_render = stream->samples_leftover + (double)Sound.SampleRate * elapsed_emulated_seconds;\r\n    if ((int)samples_to_render > 0)\r\n    {\r\n        //Msg(MSGT_DEBUG, \"RenderUpToCurrent() %d cycles -> %.2f samples\", (int)elapsed_cycles, (float)samples_to_render);\r\n        SoundStream_RenderSamples(stream, (int)samples_to_render);\r\n\r\n        {\r\n            //samples_to_render = samplerate * (elapsed_cycles / cpu_clock);\r\n            //samples_to_render / (elapsed_cycles / cpu_clock) = samplerate;\r\n            //(samples_to_render * cpu_clock) / elapsed_cycles = samplerate;\r\n            //(samples_to_render * cpu_clock) = samplerate * elapsed_cycles;\r\n            //(samples_to_render * cpu_clock) / samplerate = elapsed_cycles;\r\n\r\n            //cycle = (rate / samples_to_render) * clock;\r\n            //const float recalc_elapsed_cycles = Sound_ConvertSamplesToCycles((int)samples_to_render);\r\n            //Msg(MSGT_DEBUG, \"Elapsed %d <> %.2f\", (int)elapsed_cycles, recalc_elapsed_cycles);\r\n        }\r\n\r\n        stream->last_rendered_cycle_counter = current_cycle;\r\n        stream->samples_leftover = (double)samples_to_render - (int)samples_to_render;\r\n    }\r\n}\r\n\r\nint SoundStream_CountReadableSamples(const t_sound_stream* stream)\r\n{\r\n    if (stream->audio_buffer_rpos == stream->audio_buffer_wpos)\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    // Circular buffer\r\n    if (stream->audio_buffer_rpos < stream->audio_buffer_wpos)\r\n    {\r\n        // Have not wrapped\r\n        return (stream->audio_buffer_wpos - stream->audio_buffer_rpos) / SOUND_CHANNEL_COUNT;\r\n    }\r\n    // Have wrapped\r\n    return ((stream->audio_buffer_size - stream->audio_buffer_rpos) + stream->audio_buffer_wpos) / SOUND_CHANNEL_COUNT;\r\n}\r\n\r\nint SoundStream_CountWritableSamples(const t_sound_stream* stream)\r\n{\r\n    return stream->audio_buffer_size / SOUND_CHANNEL_COUNT - SoundStream_CountReadableSamples(stream);\r\n}\r\n\r\nbool SoundStream_PushSamplesRequestBufs(t_sound_stream* stream, int samples_count, s16** wbuf1, int* wbuf1_sample_count, s16** wbuf2, int* wbuf2_sample_count)\r\n{\r\n    *wbuf1 = *wbuf2 = NULL;\r\n    *wbuf1_sample_count = *wbuf2_sample_count = 0;\r\n\r\n    s16* buf_begin = &stream->audio_buffer[0];\r\n    s16* buf_end = &stream->audio_buffer[stream->audio_buffer_size];\r\n\r\n    int writable_samples = SoundStream_CountWritableSamples(stream);\r\n    if (writable_samples < samples_count)\r\n    {\r\n        Msg(MSGT_DEBUG, \"PushSamplesRequestBufs(): overflow %d > %d\", samples_count, writable_samples);\r\n        return false;\r\n    }\r\n\r\n    if (stream->audio_buffer_wpos >= stream->audio_buffer_rpos)\r\n    {\r\n        // Provide writable buffer for wpos->end section\r\n        const int samples_to_write = MIN(samples_count, (stream->audio_buffer_size - stream->audio_buffer_wpos) / SOUND_CHANNEL_COUNT);\r\n        if (samples_to_write < 0)\r\n            assert(0);\r\n        *wbuf1 = &stream->audio_buffer[stream->audio_buffer_wpos];\r\n        *wbuf1_sample_count = samples_to_write;\r\n        if (*wbuf1 && (*wbuf1 < buf_begin || *wbuf1+*wbuf1_sample_count*SOUND_CHANNEL_COUNT > buf_end))\r\n            assert(0);\r\n        samples_count -= samples_to_write;\r\n        stream->audio_buffer_wpos = (stream->audio_buffer_wpos + samples_to_write*SOUND_CHANNEL_COUNT) % stream->audio_buffer_size;\r\n    }\r\n    if (stream->audio_buffer_wpos < stream->audio_buffer_rpos && samples_count > 0)\r\n    {\r\n        // Provide writable buffer for wpos->rpos section\r\n        const int samples_to_write = MIN(samples_count, (stream->audio_buffer_rpos - stream->audio_buffer_wpos) / SOUND_CHANNEL_COUNT);\r\n        if (samples_to_write < 0)\r\n            assert(0);\r\n        *wbuf2 = &stream->audio_buffer[stream->audio_buffer_wpos];\r\n        *wbuf2_sample_count = samples_to_write;\r\n        if (*wbuf2 && (*wbuf2 < buf_begin || *wbuf2+*wbuf2_sample_count*SOUND_CHANNEL_COUNT > buf_end))\r\n            assert(0);\r\n        samples_count -= samples_to_write;\r\n        stream->audio_buffer_wpos = (stream->audio_buffer_wpos + samples_to_write*SOUND_CHANNEL_COUNT) % stream->audio_buffer_size;\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nint SoundStream_PopSamples(t_sound_stream* stream, s16* buf, int samples_wanted)\r\n{\r\n    //Msg(MSGT_DEBUG, \"PopSamples() %d\", samples_wanted);\r\n\r\n    const int samples_avail = SoundStream_CountReadableSamples(stream);\r\n    if (samples_avail < samples_wanted)\r\n    {\r\n        Msg(MSGT_DEBUG, \"PopSamples(): underrun %d < %d available\", samples_avail, samples_wanted);\r\n        return 0;\r\n    }\r\n    //const s16* buf_start = buf;\r\n    //const s16* buf_end = buf + samples_wanted;\r\n\r\n    int samples_read = 0;\r\n    while (samples_wanted > 0)\r\n    {\r\n        if (stream->audio_buffer_rpos == stream->audio_buffer_wpos)\r\n        {\r\n            Msg(MSGT_DEBUG, \"SoundStream_PopSamples(): underrun in loop\");\r\n            break;\r\n        }\r\n\r\n        int samples_avail_contiguous;\r\n        if (stream->audio_buffer_rpos < stream->audio_buffer_wpos)\r\n        {\r\n            // Read rpos->wpos\r\n            samples_avail_contiguous = (stream->audio_buffer_wpos - stream->audio_buffer_rpos) / SOUND_CHANNEL_COUNT;\r\n        }\r\n        else\r\n        {\r\n            // Read rpos->end\r\n            samples_avail_contiguous = (stream->audio_buffer_size - stream->audio_buffer_rpos) / SOUND_CHANNEL_COUNT;\r\n        }\r\n\r\n        const int samples_to_read = MIN(samples_wanted, samples_avail_contiguous);\r\n        memcpy(&buf[samples_read*SOUND_CHANNEL_COUNT], &stream->audio_buffer[stream->audio_buffer_rpos], samples_to_read * sizeof(s16) * SOUND_CHANNEL_COUNT);\r\n        samples_read += samples_to_read;\r\n        samples_wanted -= samples_to_read;\r\n        stream->audio_buffer_rpos = (stream->audio_buffer_rpos + samples_to_read * SOUND_CHANNEL_COUNT) % stream->audio_buffer_size;\r\n    }\r\n//    memset(buf, 0, 1024*2*SOUND_CHANNEL_COUNT);\r\n\r\n    return samples_read;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid SoundDebugApp_Init()\r\n{\r\n    t_app_sound_debug* app = &SoundDebugApp;\r\n\r\n    t_frame frame;\r\n    frame.pos.x = 150;\r\n    frame.pos.y = 500;\r\n    frame.size.x = 350;\r\n    frame.size.y = 70;\r\n    app->active = false;\r\n    app->box = gui_box_new(&frame, \"Sound Debug\");\r\n    app->box->user_data = app;\r\n    app->box->update = SoundDebugApp_Update;\r\n    widget_closebox_add(app->box, (t_widget_callback)SoundDebugApp_Switch);\r\n    Desktop_Register_Box(\"SOUND_DEBUG\", app->box, 0, &app->active);\r\n}\r\n\r\nvoid SoundDebugApp_InstallMenuItems(int menu_parent)\r\n{\r\n    t_app_sound_debug* app = &SoundDebugApp;\r\n    menu_add_item(menu_parent, \"Sound Debug..\", NULL, MENU_ITEM_FLAG_ACTIVE | Is_Checked(app->active), (t_menu_callback)SoundDebugApp_Switch, app);\r\n}\r\n\r\nstatic void SoundDebugApp_Printf(int* px, int* py, const char* format, ...)\r\n{\r\n    t_app_sound_debug* app = &SoundDebugApp;\r\n\r\n    char buf[256];\r\n    va_list args;\r\n    va_start(args, format);\r\n    vsnprintf(buf, countof(buf), format, args);\r\n    va_end(args);\r\n    \r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    Font_Print(FONTID_MEDIUM, buf, *px, *py, COLOR_SKIN_WINDOW_TEXT);\r\n    *py += Font_Height(FONTID_MEDIUM);\r\n}\r\n\r\nvoid SoundDebugApp_Update()\r\n{\r\n    t_app_sound_debug* app = &SoundDebugApp;\r\n    if (!app->active)\r\n        return;\r\n\r\n    al_set_target_bitmap(app->box->gfx_buffer);\r\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\r\n\r\n    if (!Sound.Enabled)\r\n        return;\r\n\r\n    int x = 4;\r\n    int y = 0;\r\n\r\n    static const char* stars64 = \"****************************************************************\";\r\n\r\n    t_sound_stream* stream = g_psg_stream;\r\n    int samples;\r\n\r\n    samples = SoundStream_CountReadableSamples(stream);\r\n    SoundDebugApp_Printf(&x, &y, \"ReadableSamples: %-6d [%-32s]\", samples, stars64+(64-MIN(32,samples/1024)));\r\n\r\n    samples = SoundStream_CountWritableSamples(stream);\r\n    SoundDebugApp_Printf(&x, &y, \"WritableSamples: %-6d [%-32s]\", samples, stars64+(64-MIN(32,samples/1024)));\r\n}\r\n\r\n// Called from closebox widget and menu handler\r\nvoid SoundDebugApp_Switch()\r\n{\r\n    t_app_sound_debug *app = &SoundDebugApp;\r\n    app->active ^= 1;\r\n    gui_box_show(app->box, app->active, TRUE);\r\n    gui_menu_toggle_check (menus_ID.sound, 4);  // FIXME-UGLY\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/sound/sound.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - sound.h\r\n// Sound Engine - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// DEFINITIONS\r\n//-----------------------------------------------------------------------------\r\n\r\n#define SOUND_BUFFERS_COUNT         (4)\r\n#define SOUND_BUFFERS_SAMPLE_COUNT  (1024)\r\n#define SOUND_CHANNEL_COUNT         (2)\r\n\r\n#define SOUND_DEBUG_APPLET          (1)\r\n\r\n//-----------------------------------------------------------------------------\r\n// INCLUDES\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"vgm.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// DATA\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_sound\r\n{\r\n    // General\r\n    bool        Enabled;\r\n    bool        Initialized;\r\n    int         SampleRate;                 // In Hz\r\n    int         Paused;                     // Paused stack. Sounds play only when this is zero\r\n    int         MasterVolume;               // Master Volume (0-128)\r\n\r\n    // FM Emulation\r\n    bool        FM_Enabled;                 // FM Emulation enabled (emulated machine)\r\n\r\n    // Logging\r\n    FILE *      LogWav;\r\n    int         LogWav_SizeData;\r\n    char *      LogWav_FileName_Template;\r\n    int         LogWav_ID;\r\n    t_vgm       LogVGM;\r\n    int         LogVGM_Logging_Accuracy;\r\n    char *      LogVGM_FileName_Template;\r\n    int         LogVGM_ID;\r\n\r\n    int         CpuClock;\r\n    s64         CycleCounter;               // Number of cycle elapsed since last sound sync.\r\n};\r\n\r\nstruct t_sound_stream;\r\n\r\nextern t_sound          Sound;\r\nextern t_sound_stream*  g_psg_stream;\r\nextern t_sound_stream*  g_ym2413_stream;\r\n\r\n//-----------------------------------------------------------------------------\r\n// FUNCTIONS\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid            Sound_Init_Config();\r\nint             Sound_Init();\r\nvoid            Sound_Close();\r\nvoid            Sound_UpdateClockSpeed();\r\nvoid            Sound_Update();\r\nvoid            Sound_SetMasterVolume(int volume);\r\nvoid            Sound_ResetCycleCounter();\r\n\r\ns64             Sound_GetElapsedCycleCounter();\r\ndouble          Sound_ConvertSamplesToCycles(double samples_count);\r\n\r\nvoid            Sound_Playback_Start();\r\nvoid            Sound_Playback_Stop();\r\nvoid            Sound_Playback_Mute();\r\nvoid            Sound_Playback_Resume();\r\n\r\nt_sound_stream* SoundStream_Create(void (*sample_writer)(s16*,int));\r\nvoid            SoundStream_Destroy(t_sound_stream* stream);\r\nvoid            SoundStream_Update(t_sound_stream* stream);\r\nvoid            SoundStream_RenderSamples(t_sound_stream* stream, int samples_count);\r\nvoid            SoundStream_RenderUpToCurrentTime(t_sound_stream* stream);\r\nint             SoundStream_CountReadableSamples(const t_sound_stream* stream);\r\nint             SoundStream_CountWritableSamples(const t_sound_stream* stream);\r\nbool            SoundStream_PushSamplesRequestBufs(t_sound_stream* stream, int samples_count, s16** wbuf1, int* wbuf1_sample_count, s16** buf2, int* wbuf2_sample_count);\r\nint             SoundStream_PopSamples(t_sound_stream* stream, s16* buf, int samples_wanted);\r\n\r\nvoid            SoundDebugApp_Init();\r\nvoid            SoundDebugApp_InstallMenuItems(int menu_parent);\r\nvoid            SoundDebugApp_Update();\r\nvoid            SoundDebugApp_Switch();\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/sound/sound_logging.cpp",
    "content": "//\n// Meka - sound_logging.c\n// Sound Logging\n//\n\n#include \"shared.h\"\n#include \"sound_logging.h\"\n#include \"vmachine.h\"\n#include \"wav.h\"\n\nvoid    Sound_Log_Init()\n{\n    Sound.LogWav                   = NULL;\n    Sound.LogWav_SizeData          = 0;\n    Sound.LogWav_FileName_Template = strdup(\"%s-%02d.wav\");\n    Sound.LogWav_ID                = 0;\n    Sound.LogVGM.Logging           = VGM_LOGGING_NO;\n    Sound.LogVGM_Logging_Accuracy  = VGM_LOGGING_ACCURACY_FRAME;\n    Sound.LogVGM_FileName_Template = strdup(\"%s-%02d.vgm\");\n    Sound.LogVGM_ID                = 0;\n}\n\nvoid    Sound_Log_Close()\n{\n    if (Sound.LogWav != NULL)\n        Sound_LogWAV_Stop();\n    if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\n        Sound_LogVGM_Stop();\n}\n\nvoid    Sound_Log_Init_Game()\n{\n    Sound.LogWav_ID = Sound.LogVGM_ID = 1; // Reset counter for a new game\n}\n\nvoid    Sound_Log_FileName_Get(char *result, const char *filename_template, int *id)\n{\n    char   s1 [FILENAME_LEN];\n    char   s2 [FILENAME_LEN];\n\n    // Create Directory if necessary --------------------------------------------\n    if (!al_filename_exists(g_env.Paths.MusicDirectory))\n        al_make_directory(g_env.Paths.MusicDirectory);\n\n    // Create second template ----------------------------------------------------\n    const char * game_name;\n    if ((g_machine_flags & MACHINE_RUN) == MACHINE_RUN) // If a game is loaded & runnnig\n    {\n        strcpy(s1, g_env.Paths.MediaImageFile);\n        StrPath_RemoveDirectory (s1);\n        StrPath_RemoveExtension (s1);\n        game_name = s1;\n    }\n    else\n    {\n        game_name = \"meka\";\n    }\n    sprintf(s2, \"%%s/%s\", filename_template);\n\n    do\n    {\n        sprintf(result, s2, g_env.Paths.MusicDirectory, game_name, *id);\n        (*id) ++;\n    }\n    while (al_filename_exists(result) != 0 && *id < SOUND_LOG_ID_MAX);\n}\n\nvoid    Sound_LogWAV_Start()\n{\n    if (Sound.LogWav != NULL)\n        Sound_LogWAV_Stop();\n    if (Sound.LogWav == NULL)\n    { // Start Logging\n        char FileName[FILENAME_LEN];\n        Sound_Log_FileName_Get (FileName, Sound.LogWav_FileName_Template, &Sound.LogWav_ID);\n        if (Sound.LogWav_ID >= SOUND_LOG_ID_MAX)\n        {\n            Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Sound_Dumping_Error_File_1));\n            return;\n        }\n        Sound.LogWav = WAV_Start(FileName);\n        StrPath_RemoveDirectory (FileName);\n        if (Sound.LogWav == NULL)\n        {\n            Msg(MSGT_USER, Msg_Get(MSG_Sound_Dumping_Error_File_2), FileName);\n            return;\n        }\n        else\n        {\n            Sound.LogWav_SizeData = 0;\n            Msg(MSGT_USER, Msg_Get(MSG_Sound_Dumping_Start), FileName);\n            gui_menu_active_range (TRUE, menus_ID.sound_log, 4, 4);\n        }\n    }\n}\n\nvoid    Sound_LogWAV_Stop()\n{\n    if (Sound.LogWav != NULL)\n    {\n        WAV_Close(Sound.LogWav, Sound.LogWav_SizeData);\n        Sound.LogWav = NULL;\n        Msg(MSGT_USER, Msg_Get(MSG_Sound_Dumping_Stop),\n            (double)Sound.LogWav_SizeData / ((16 / 8) * SOUND_CHANNEL_COUNT * Sound.SampleRate));\n        gui_menu_active_range (FALSE, menus_ID.sound_log, 4, 4);\n    }\n}\n\nvoid    Sound_LogVGM_Start()\n{\n    char   FileName[FILENAME_LEN];\n\n    if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\n        Sound_LogVGM_Stop();\n\n    // Start Logging\n    Sound_Log_FileName_Get(FileName, Sound.LogVGM_FileName_Template, &Sound.LogVGM_ID);\n    if (Sound.LogVGM_ID >= SOUND_LOG_ID_MAX)\n    {\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Sound_Dumping_Error_File_1));\n        return;\n    }\n    if (VGM_Start(&Sound.LogVGM, FileName, Sound.LogVGM_Logging_Accuracy) != MEKA_ERR_OK)\n    {\n        StrPath_RemoveDirectory (FileName);\n        Msg(MSGT_USER, Msg_Get(MSG_Sound_Dumping_Error_File_2), FileName);\n        return;\n    }\n    else\n    {\n        StrPath_RemoveDirectory (FileName);\n        Msg(MSGT_USER, Msg_Get(MSG_Sound_Dumping_Start), FileName);\n        gui_menu_active_range (TRUE, menus_ID.sound_log, 1, 1);\n    }\n}\n\nvoid    Sound_LogVGM_Stop()\n{\n    if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\n    {\n        VGM_Close(&Sound.LogVGM);\n        Msg(MSGT_USER, Msg_Get(MSG_Sound_Dumping_Stop),\n            (double)Sound.LogVGM.vgm_header.total_samples / 44100);\n        gui_menu_active_range (FALSE, menus_ID.sound_log, 1, 1);\n    }\n}\n\nvoid    Sound_LogVGM_Accuracy_Switch()\n{\n    if (Sound.LogVGM_Logging_Accuracy == VGM_LOGGING_ACCURACY_SAMPLE)\n    {\n        Sound.LogVGM_Logging_Accuracy = VGM_LOGGING_ACCURACY_FRAME;\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Sound_Dumping_VGM_Acc_Frame));\n    }\n    else\n    {\n        Sound.LogVGM_Logging_Accuracy = VGM_LOGGING_ACCURACY_SAMPLE;\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Sound_Dumping_VGM_Acc_Sample));\n    }\n    gui_menu_toggle_check (menus_ID.sound_log, 2);\n    if (Sound.LogVGM.Logging != VGM_LOGGING_NO)\n    {\n        Msg(MSGT_USER_LOG, \"%s\", Msg_Get(MSG_Sound_Dumping_VGM_Acc_Change));\n    }\n}\n"
  },
  {
    "path": "meka/srcs/sound/sound_logging.h",
    "content": "//\n// Meka - sound_logging.h\n// Sound Logging\n//\n\nvoid    Sound_Log_Init();\nvoid    Sound_Log_Close();\n\n#define SOUND_LOG_ID_MAX (9999) /* Security measure for not going in infinite loop with short file name */\nvoid    Sound_Log_Init_Game();\n\nvoid    Sound_LogWAV_Start();\nvoid    Sound_LogWAV_Stop();\n\nvoid    Sound_LogVGM_Start();\nvoid    Sound_LogVGM_Stop();\nvoid    Sound_LogVGM_Accuracy_Switch();\n"
  },
  {
    "path": "meka/srcs/sound/vgm.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - VGM.C\n// VGM File Creation\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"db.h\"\n#include \"fmunit.h\"\n#include \"psg.h\"\n#include \"tvtype.h\"\n\n//-----------------------------------------------------------------------------\n\nvoid            VGM_Header_Init(t_vgm_header *h)\n{\n    assert(sizeof(t_vgm_header) == 64);\n    memcpy(h->magic, VGM_MAGIC, sizeof (h->magic));\n    h->eof_offset           = 0;                            // Unknown as of yet\n    h->version_number       = VGM_VERSION;                  // VGM Version\n    // FIXME: PSG?\n    h->sn76489_clock        = g_machine.TV->CPU_clock;    // CPU Clock\n    h->ym2413_clock         = 0;                            // Will be set back if VGM_FM_Used==TRUE\n    h->gd3_offset           = 0;                            // Unknown as of yet\n    h->total_samples        = 0;\n    h->loop_offset          = 0;\n    h->loop_samples         = 0;\n    h->rate                 = g_machine.TV->screen_frequency;\n    if (g_driver->snd == SND_SN76489)\n    {\n        h->sn76489_feedback     = 0x0009;\n        h->sn76489_shift_width  = 16;\n    }\n    else if (g_driver->snd == SND_SN76489AN)\n    {\n        h->sn76489_feedback     = 0x0003;   // 2005/11/12: VGM specs are incorrect, says 0x0006\n        h->sn76489_shift_width  = 15;\n    }\n    else\n    {\n        assert(0);\n        h->sn76489_feedback     = 0;\n        h->sn76489_shift_width  = 0;\n    }\n    h->_reserved            = 0;\n    h->ym2612_clock         = 0;\n    h->ym2151_clock         = 0;\n    for (int i = 0; i != VGM_PADDING_SIZE; i++)\n        h->_padding[i] = 0;\n}\n\nint             VGM_Start(t_vgm *VGM, const char *FileName, int Logging_Accuracy)\n{\n    int         i;\n\n    VGM->Logging = Logging_Accuracy;\n    VGM->File = fopen(FileName, \"wb\");\n    if (VGM->File  == NULL)\n        return (MEKA_ERR_FILE_WRITE);\n    VGM_Header_Init(&VGM->vgm_header);\n    GD3_Header_Init(&VGM->gd3_header);\n    fwrite (&VGM->vgm_header, sizeof (VGM->vgm_header), 1, VGM->File);\n\n    VGM->DataSize = 0;\n    VGM->Cycles_Counter = 0;\n    VGM_Update_Timing (VGM);\n\n    // Initialize PSG State\n    // Channel 0\n    VGM_Data_Add_PSG (VGM, 0x90 | (PSG.Registers[1] & 0x0F));\n    VGM_Data_Add_PSG (VGM, 0x80 | (PSG.Registers[0] & 0x0F));\n    VGM_Data_Add_PSG (VGM, (PSG.Registers[0] >> 4) & 0x3F);\n    // Channel 1\n    VGM_Data_Add_PSG (VGM, 0xB0 | (PSG.Registers[3] & 0x0F));\n    VGM_Data_Add_PSG (VGM, 0xA0 | (PSG.Registers[2] & 0x0F));\n    VGM_Data_Add_PSG (VGM, (PSG.Registers[2] >> 4) & 0x3F);\n    // Channel 2\n    VGM_Data_Add_PSG (VGM, 0xD0 | (PSG.Registers[5] & 0x0F));\n    VGM_Data_Add_PSG (VGM, 0xC0 | (PSG.Registers[4] & 0x0F));\n    VGM_Data_Add_PSG (VGM, (PSG.Registers[4] >> 4) & 0x3F);\n    // Channel 3 (Noise)\n    VGM_Data_Add_PSG (VGM, 0xF0 | (PSG.Registers[7] & 0x0F));\n    VGM_Data_Add_PSG (VGM, 0xE0 | (PSG.Registers[6] & 0x0F));\n\n    // Initialize FM State\n    VGM->FM_Used = FALSE;\n    for (i = 0; i < YM2413_REGISTERS; i++)\n        if (FM_Regs[i] != 0x00) // FIXME\n        {\n            VGM->FM_Used = TRUE;\n            break;\n        }\n    if (VGM->FM_Used)\n        for (i = 0; i < YM2413_REGISTERS; i++)\n            if (FM_Regs_SavingFlags[i] != 0)\n                VGM_Data_Add_FM (VGM, ((FM_Regs[i] & FM_Regs_SavingFlags[i]) << 8) | i);\n\n    return (MEKA_ERR_OK);\n}\n\nvoid            VGM_Close(t_vgm *VGM)\n{\n    // Add end of file marker\n    VGM_Data_Add_Byte (VGM, VGM_CMD_EOF);\n\n    // Calculate final EOF_Relative\n    VGM->vgm_header.eof_offset = sizeof (VGM->vgm_header) - 4 + VGM->DataSize;\n\n    // Write GD3, increment EOF_Relative\n    VGM->vgm_header.eof_offset += GD3_Header_Write(&VGM->gd3_header, VGM->File);\n    GD3_Header_Close(&VGM->gd3_header);\n\n    // Calculate final GD3_Relative\n    VGM->vgm_header.gd3_offset = sizeof (VGM->vgm_header) - 0x14 + VGM->DataSize;   // 0x14 must be offsetof(gd3_offset)\n\n    // Enable YM-2413 in header is enabled\n    if (VGM->FM_Used)\n        VGM->vgm_header.ym2413_clock = VGM->vgm_header.sn76489_clock;\n\n    // Rewrite header with updated N_Samples & EOF_Relative\n    fseek (VGM->File, 0, SEEK_SET);\n    fwrite (&VGM->vgm_header, sizeof (VGM->vgm_header), 1, VGM->File);\n    fclose (VGM->File);\n\n    // Clean out\n    VGM->Logging = VGM_LOGGING_NO;\n    VGM->File = NULL;\n}\n\n//-----------------------------------------------------------------------------\n\nvoid            VGM_Update_Timing (t_vgm *VGM)\n{\n    VGM->Samples_per_Frame = (g_machine.TV->id == TVTYPE_NTSC) ? 735 : 882;\n    VGM->Cycles_per_Frame  = /*VGM->Header.PSG_Speed / 60*/ g_machine.TV_lines * opt.Cur_IPeriod;\n    VGM->Samples_per_Cycle = (double)VGM->Samples_per_Frame / VGM->Cycles_per_Frame;\n    VGM->Cycles_per_Sample = (double)VGM->Cycles_per_Frame / VGM->Samples_per_Frame;\n}\n\nvoid            VGM_NewFrame(t_vgm *VGM)\n{\n    if (VGM->Logging == VGM_LOGGING_ACCURACY_FRAME)\n    {\n        byte b;\n\n        if (g_machine.TV->id == TVTYPE_NTSC)\n        {\n            b = VGM_CMD_WAIT_735;\n            VGM->vgm_header.total_samples += 735;\n        }\n        else\n        {\n            b = VGM_CMD_WAIT_882;\n            VGM->vgm_header.total_samples += 882;\n        }\n        VGM_Data_Add_Byte(VGM, b);\n    }\n    else\n    {\n        VGM->Cycles_Counter += VGM->Cycles_per_Frame;\n    }\n}\n\nINLINE void     VGM_Wait_Samples(t_vgm *VGM)\n{\n    int CurCycle = ((tsms.VDP_Line + 1) * CPU_GetIPeriod()) - CPU_GetICount();\n    double Waitd = ((double)(CurCycle + VGM->Cycles_Counter)) * VGM->Samples_per_Cycle;\n    int Wait = Waitd;\n    // Msg(0, \"[%i] %i + %i * %.12f = Waiting %i samples..\", tsms.VDP_Line, CurCycle, VGM->Cycles_Counter, VGM->Samples_per_Cycle, Wait);\n    VGM_Data_Add_Wait(VGM, Wait);\n    // VGM->Cycles_Counter = -CurCycle;\n    VGM->Cycles_Counter -= ((double)Wait * VGM->Cycles_per_Sample);\n}\n\n//-----------------------------------------------------------------------------\n\nvoid            VGM_Data_Add_GG_Stereo(t_vgm *VGM, byte Data)\n{\n    static char    buf[2] = { VGM_CMD_GG_STEREO, 0x00 };\n\n    if (VGM->Logging == VGM_LOGGING_ACCURACY_SAMPLE)\n        VGM_Wait_Samples (VGM);\n\n    buf[1] = Data;\n    fwrite (buf, 2, sizeof (char), VGM->File);\n    VGM->DataSize += 2;\n}\n\nvoid            VGM_Data_Add_Byte(t_vgm *VGM, byte Data)\n{\n    // if (VGM->Logging == VGM_LOGGING_ACCURACY_SAMPLE)\n    //    VGM_Wait_Samples (VGM);\n\n    fwrite (&Data, 1, sizeof (byte), VGM->File);\n    VGM->DataSize += 1;\n}\n\nvoid            VGM_Data_Add_PSG(t_vgm *VGM, byte Data)\n{\n    static char    buf[2] = { VGM_CMD_PSG, 0x00 };\n\n    if (VGM->Logging == VGM_LOGGING_ACCURACY_SAMPLE)\n        VGM_Wait_Samples (VGM);\n\n    buf[1] = Data;\n    fwrite (buf, 2, sizeof (byte), VGM->File);\n    VGM->DataSize += 2;\n}\n\nvoid            VGM_Data_Add_FM(t_vgm *VGM, int RegData)\n{\n    static char    buf[3] = { VGM_CMD_YM2413, 0x00, 0x00 };\n\n    if (VGM->Logging == VGM_LOGGING_ACCURACY_SAMPLE)\n        VGM_Wait_Samples (VGM);\n\n    *(word *)&buf[1] = RegData;\n    fwrite (buf, 3, sizeof (byte), VGM->File);\n    VGM->DataSize += 3;\n    VGM->FM_Used = TRUE;\n}\n\nvoid            VGM_Data_Add_Wait(t_vgm *VGM, int Samples)\n{\n    static char    buf[3] = { VGM_CMD_WAIT, 0x00, 0x00 };\n\n    if (Samples <= 0)\n        return;\n    VGM->vgm_header.total_samples += Samples;\n    if (Samples > 0xFFFF)\n    {\n        *(word *)&buf[1] = 0xFFFF;\n        do\n        {\n            fwrite (buf, 3, sizeof (byte), VGM->File);\n            VGM->DataSize += 3;\n            Samples -= 0xFFFF;\n        }\n        while (Samples > 0xFFFF);\n    }\n    *(word *)&buf[1] = Samples;\n    fwrite (buf, 3, sizeof (byte), VGM->File);\n    VGM->DataSize += 3;\n}\n\n//-----------------------------------------------------------------------------\n// GD3\n//-----------------------------------------------------------------------------\n\nvoid            GD3_Header_Init(t_gd3_header *h)\n{\n    const char *name;\n\n    memcpy(h->magic, GD3_MAGIC, 4);\n    h->version = GD3_VERSION;\n    h->data_length = 0;            // Unknown as of yet\n    h->strings[GD3_S_NAME_TRACK_ENG]  = StrDupToU16 (\"\");\n    h->strings[GD3_S_NAME_TRACK_JAP]  = StrDupToU16 (\"\");\n\n    // English name\n    name = DB.current_entry ? DB_Entry_GetCurrentName (DB.current_entry) : \"\";\n    h->strings[GD3_S_NAME_GAME_ENG]   = StrDupToU16 (name);\n\n    // Japanese name\n    if (DB.current_entry)\n    {\n        const t_db_name *dbname = DB_Entry_GetNameByCountry(DB.current_entry, DB_COUNTRY_JP);\n        name = dbname ? dbname->name : \"\";\n    }\n    else\n    {\n        name = \"\";\n    }\n    h->strings[GD3_S_NAME_GAME_JAP]   = StrDupToU16 (name);\n\n    // System, Author, Date, File author (filled if MEKA is registered), Notes\n    h->strings[GD3_S_NAME_SYSTEM_ENG] = StrDupToU16 (g_driver->full_name);\n    h->strings[GD3_S_NAME_SYSTEM_JAP] = StrDupToU16 (\"\");\n    h->strings[GD3_S_NAME_AUTHOR_ENG] = StrDupToU16 (\"\");\n    h->strings[GD3_S_NAME_AUTHOR_JAP] = StrDupToU16 (\"\");\n    h->strings[GD3_S_DATE]            = StrDupToU16 (\"\");\n    h->strings[GD3_S_FILE_AUTHOR]     = StrDupToU16 (\"\"); //registered.is ? registered.user_name_only : \"\");\n    h->strings[GD3_S_NOTES]           = StrDupToU16 (\"\");\n}\n\nvoid            GD3_Header_Close(t_gd3_header *h)\n{\n    int         i;\n\n    for (i = 0; i != GD3_S_MAX; i++)\n        free (h->strings[i]);\n}\n\n// Write GD3 header to given Stdio file\nint             GD3_Header_Write(t_gd3_header *h, FILE *f)\n{\n    int         i;\n\n    // Calculate Data Length\n    int Len = 0;\n    for (i = 0; i != GD3_S_MAX; i++)\n        Len += (StrLenU16 (h->strings[i]) + 1) * 2;\n    h->data_length = Len;\n\n    // Create buffer with all strings\n    char* Buf = (char*)Memory_Alloc (Len);\n    int Pos = 0;\n    for (i = 0; i < GD3_S_MAX; i++)\n    {\n        StrCpyU16 ((word *)(Buf + Pos), h->strings[i]);\n        Pos += StrLenU16 (h->strings[i]) * 2;\n        *(word *)(Buf + Pos) = 0x0000;\n        Pos += 2;\n    }\n\n    // Asserting that Pos == Len\n    if (Pos != Len)\n        Quit_Msg(\"Fatal Error in sound/vgm.c::GD3_Header_Write(), Pos != Len\");\n\n    // Write data\n    fwrite (h, sizeof (h->magic) + sizeof (h->version) + sizeof (h->data_length), 1, f);\n    fwrite (Buf, Len, 1, f);\n    free (Buf);\n\n    return (sizeof (h->magic) + sizeof (h->version) + sizeof (h->data_length) + Len);\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sound/vgm.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - VGM.H\n// VGM File Creation\n//-----------------------------------------------------------------------------\n\n// VGM 1.10 -------------------------------------------------------------------\n#define VGM_MAGIC                       \"Vgm \"\n#define VGM_VERSION                     ((int)0x00000110)\n//#define VGM_PSG_SPEED                 (CPU_CLOCK)\n//#define VGM_FM_SPEED                  (CPU_CLOCK)\n#define VGM_PADDING_SIZE                (12)\n\n// VGM commands\n#define VGM_CMD_GG_STEREO               (0x4F)\n#define VGM_CMD_PSG                     (0x50)\n#define VGM_CMD_YM2413                  (0x51)\n#define VGM_CMD_WAIT                    (0x61)\n#define VGM_CMD_WAIT_735                (0x62)\n#define VGM_CMD_WAIT_882                (0x63)\n#define VGM_CMD_EOF                     (0x66)\n\n// VGM logging values\n#define VGM_LOGGING_NO                  (0)\n#define VGM_LOGGING_ACCURACY_FRAME      (1)\n#define VGM_LOGGING_ACCURACY_SAMPLE     (2)\n\n// VGM buffer (unused as of yet)\n// #define VGM_BUFFER_SIZE              (131072) // 128 Kb\n\nstruct t_vgm_header\n{\n    char        magic[4];\n    int         eof_offset;\n    int         version_number;\n    int         sn76489_clock;\n    int         ym2413_clock;\n    int         gd3_offset;\n    int         total_samples;\n    int         loop_offset;\n    int         loop_samples;\n\n    int         rate;                       // VGM 1.01\n\n    u16         sn76489_feedback;           // VGM 1.10\n    u8          sn76489_shift_width;        // VGM 1.10\n    u8          _reserved;                  // VGM 1.10\n    u32         ym2612_clock;               // VGM 1.10\n    u32         ym2151_clock;               // VGM 1.10\n    char        _padding[VGM_PADDING_SIZE];\n};\n\n// GD3 1.00 -------------------------------------------------------------------\n#define GD3_MAGIC                       \"Gd3 \"\n#define GD3_VERSION                     ((int)0x00000100)\n\n#define GD3_S_NAME_TRACK_ENG            (0)\n#define GD3_S_NAME_TRACK_JAP            (1)\n#define GD3_S_NAME_GAME_ENG             (2)\n#define GD3_S_NAME_GAME_JAP             (3)\n#define GD3_S_NAME_SYSTEM_ENG           (4)\n#define GD3_S_NAME_SYSTEM_JAP           (5)\n#define GD3_S_NAME_AUTHOR_ENG           (6)\n#define GD3_S_NAME_AUTHOR_JAP           (7)\n#define GD3_S_DATE                      (8)\n#define GD3_S_FILE_AUTHOR               (9)\n#define GD3_S_NOTES                     (10)\n#define GD3_S_MAX                       (11)\n\nstruct t_gd3_header\n{\n    char            magic[4];\n    int             version;\n    int             data_length;\n    u16 *           strings[GD3_S_MAX];\n};\n\nstruct t_vgm\n{\n    int             Logging;                // Currently logging / & type\n    FILE *          File;                   // File\n    int             DataSize;               // Size for all VGM data (not just a single buffer)\n    int             FM_Used;                // FM is used ?\n    t_vgm_header    vgm_header;             // VGM Header\n    t_gd3_header    gd3_header;             // GD3 Header\n    int             Samples_per_Frame;      //\n    int             Cycles_per_Frame;       //\n    int             Cycles_Counter;         //\n    double          Samples_per_Cycle;      //\n    double          Cycles_per_Sample;      //\n};\n\nint             VGM_Start(t_vgm *VGM, const char *filename, int logging_accuracy);\nvoid            VGM_Close(t_vgm *VGM);\n\nvoid            VGM_Update_Timing(t_vgm *VGM);\nvoid            VGM_NewFrame(t_vgm *VGM);\n\nvoid            VGM_Data_Add_GG_Stereo(t_vgm *VGM, byte data);\nvoid            VGM_Data_Add_Byte(t_vgm *VGM, byte data);\nvoid            VGM_Data_Add_PSG(t_vgm *VGM, byte data);\nvoid            VGM_Data_Add_FM(t_vgm *VGM, int reg_data);\nvoid            VGM_Data_Add_Wait(t_vgm *VGM, int samples);\n\nvoid            GD3_Header_Init(t_gd3_header *h);\nvoid            GD3_Header_Close(t_gd3_header *h);\nint             GD3_Header_Write(t_gd3_header *h, FILE *f);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/sound/wav.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - wav.c\n// WAV File Creation - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#ifndef WAVE_FORMAT_PCM\n#define WAVE_FORMAT_PCM (0x0001)\n#endif\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_wav_format\n{\n word           Category;\n word           Channels;\n dword          Samples_per_Second;\n dword          Avg_Bytes_per_Second;\n word           Block_Align;\n word           Bits_per_Sample; // PCM only\n};\n\nstruct t_wav_header\n{\n char           RIFF_Tag[4];\n dword          RIFF_Len;\n char           WAVE_Tag[4];\n char           Format_Tag[4];\n dword          Format_Len;\n t_wav_format   Format;\n char           Data_Tag[4];\n int            Data_Len;\n};\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    WAV_Header_Init(t_wav_header *h, int Samples_per_Second, int Bits_per_Sample, int Channels)\n{\n    memcpy(h->RIFF_Tag, \"RIFF\", 4);\n    h->RIFF_Len = 0; // Unknown as of yet\n    memcpy(h->WAVE_Tag, \"WAVE\", 4);\n    memcpy(h->Format_Tag, \"fmt \", 4);\n    h->Format_Len = sizeof (t_wav_format);\n    h->Format.Category = WAVE_FORMAT_PCM;\n    h->Format.Channels = Channels;\n    h->Format.Samples_per_Second = Samples_per_Second; // Get the *current* rate, which is not updated if user change it with menu, only on restart -> OK\n    h->Format.Bits_per_Sample = Bits_per_Sample; // Always 16 in MEKA\n    h->Format.Avg_Bytes_per_Second = h->Format.Channels * h->Format.Samples_per_Second * (h->Format.Bits_per_Sample / 8); // See comment below\n    h->Format.Block_Align = h->Format.Channels * (h->Format.Bits_per_Sample / 8); // It's 2 in this situation, but theorically should be rounded up to the next whole number\n    memcpy(h->Data_Tag, \"data\", 4);\n    h->Data_Len = 0; // Unknown as of yet\n}\n\nFILE*   WAV_Start(char *FileName)\n{\n    FILE* f = fopen(FileName, \"wb\");\n    if (f == NULL)\n        return (NULL);\n\n    t_wav_header h;\n    WAV_Header_Init(&h, Sound.SampleRate, 16, SOUND_CHANNEL_COUNT);\n    fwrite (&h, sizeof (h), 1, f);\n    // ..\n    return (f);\n}\n\nvoid    WAV_Close(FILE *f, int SizeData)\n{\n    t_wav_header h;\n\n    h.RIFF_Len = (4) + (8+16) + (8 + SizeData);\n    int Offset = (int)((char *)&h.RIFF_Len - (char *)&h);\n    fseek (f, Offset, SEEK_SET);\n    fwrite (&h.RIFF_Len, sizeof (h.RIFF_Len), 1, f);\n\n    h.Data_Len = (SizeData);\n    Offset = (int)((char *)&h.Data_Len - (char *)&h);\n    fseek (f, Offset, SEEK_SET);\n    fwrite (&h.Data_Len, sizeof (h.Data_Len), 1, f);\n\n    fclose(f);\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/sound/wav.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - wav.c\n// WAV File Creation - Headers\n//-----------------------------------------------------------------------------\n\nFILE    *WAV_Start(char *FileName);\nvoid     WAV_Close(FILE *f, int SizeData);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/sportpad.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sportpad.c\n// Sports Pad Emulation - Code\n//-----------------------------------------------------------------------------\n// TO DO:\n//   Real Sports Pad should be carefully tested to see their reaction,\n//   actual human-reachable speed, etc...\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"sportpad.h\"\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/sportpad.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - sportpad.h\n// Sports Pad Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/system.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - system.h\r\n// Base definitions, system and libraries includes, etc..\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Architecture\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef _WIN32\r\n#define ARCH_WIN32    (1)\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// STL\r\n//-----------------------------------------------------------------------------\r\n\r\n#define _HAS_EXCEPTIONS 0\r\n#define _STATIC_CPPLIB\r\n#define _DISABLE_DEPRECATE_STATIC_CPPLIB\r\n#include <vector>\r\n#include <map>\r\n#include <algorithm>\r\n\r\n//-----------------------------------------------------------------------------\r\n// System Includes\r\n//-----------------------------------------------------------------------------\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#ifndef ARCH_MACOSX\r\n  #include <malloc.h>\r\n#endif // ARCH_MACOSX\r\n#include <math.h>\r\n#include <string.h>\r\n#include <float.h>\r\n#include <sys/stat.h>\r\n#include <ctype.h>\r\n#include <assert.h>\r\n#ifndef ARCH_WIN32\r\n  #include <dirent.h>\r\n#endif\r\n#ifdef ARCH_WIN32\r\n  #define stricmp _stricmp\r\n    #define ALLEGRO_BITMAP WINDOWS_BITMAP\r\n    #define NOMINMAX\r\n    #define WIN32_LEAN_AND_MEAN\r\n    #include <windows.h>\r\n    #include <crtdbg.h>\r\n    #undef ALLEGRO_BITMAP\r\n    #undef RGB\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Allegro Library\r\n//-----------------------------------------------------------------------------\r\n\r\n#include <allegro5/allegro.h>\r\n#include <allegro5/allegro_font.h>\r\n#include <allegro5/allegro_primitives.h>\r\n#include <allegro5/allegro_audio.h>\r\n#include <allegro5/allegro_ttf.h>\r\n#ifdef ARCH_WIN32\r\n#include <allegro5/allegro_windows.h>\r\n#endif\r\n#include \"allegro4to5.h\"\r\n\r\n#define MIN(x,y)     (((x) < (y)) ? (x) : (y))\r\n#define MAX(x,y)     (((x) > (y)) ? (x) : (y))\r\n\r\n//-----------------------------------------------------------------------------\r\n// Basic Types\r\n//-----------------------------------------------------------------------------\r\n\r\n#define BYTE_TYPE_DEFINED // for z80marat/z80.h\r\n#define WORD_TYPE_DEFINED // for z80marat/z80.h\r\n\r\n// Obsolete, avoid use\r\ntypedef unsigned char       byte;\r\ntypedef unsigned short      word;\r\ntypedef unsigned long       dword;\r\n\r\ntypedef unsigned char       u8;\r\ntypedef   signed char       s8;\r\ntypedef unsigned short      u16;\r\ntypedef   signed short      s16;\r\ntypedef unsigned int        u32;\r\ntypedef   signed int        s32;\r\ntypedef unsigned long long  u64;\r\ntypedef   signed long long  s64;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Inlining\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifndef INLINE\r\n    #ifdef ARCH_WIN32\r\n        #define INLINE __inline\r\n    #else\r\n        #define INLINE inline\r\n    #endif\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Format function attributes\r\n//-----------------------------------------------------------------------------\r\n// FIXME: this is for GCC only. Is there an equivalent for Visual C++ ?\r\n//-----------------------------------------------------------------------------\r\n\r\n#if !defined(ARCH_WIN32) && !defined(ARCH_MACOSX)\r\n    #define FORMAT_PRINTF(START)  __attribute ((format (printf, START, (START)+1)))\r\n#else\r\n    #define FORMAT_PRINTF(START)\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Miscellaneous\r\n//-----------------------------------------------------------------------------\r\n\r\n#undef FALSE\r\n#define FALSE (0)\r\n\r\n#undef TRUE\r\n#define TRUE (1)\r\n\r\n#ifdef ARCH_WIN32\r\n  #define snprintf      _snprintf\r\n#else\r\n#endif\r\n#if defined(ARCH_UNIX) || defined(ARCH_MACOSX)\r\n  #define stricmp strcasecmp\r\n  #define strnicmp strncasecmp\r\n#endif\r\n\r\n// countof(): provide number of elements in an array\r\n// The simple version is:\r\n//   #define countof(array) (sizeof(array) / sizeof(array[0]))\r\n// This more complicated version ensure that an array (not a pointer) is actually provided as the parameter\r\n// From http://blogs.msdn.com/the1/archive/2004/05/07/128242.aspx\r\n//template <typename T, size_t N>\r\n//char (&_ArraySizeHelper(T (&array)[N])) [N];\r\n//#define countof(array) (sizeof(_ArraySizeHelper(array)))\r\n#define countof(array)  (sizeof(array) / sizeof(array[0]))\r\n\r\n#define MATH_PI   (3.14159265f)\r\n\r\n//-----------------------------------------------------------------------------\r\n// Warning Disable\r\n//-----------------------------------------------------------------------------\r\n// Now compiling at warning level 4, so a few can be omitted.\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifdef ARCH_WIN32\r\n#pragma warning (disable: 4100) // 'unreferenced formal parameter'\r\n#pragma warning (disable: 4127) // 'conditional expression is constant'\r\n#pragma warning (disable: 4996) // ''_snprintf': This function or variable may be unsafe'\r\n//#define _CRT_SECURE_NO_WARNINGS\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/textbox.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - textbox.c\n// Text Box Applet - Code\n//-----------------------------------------------------------------------------\n// FIXME: this could be merged into message.c someday, and made obsolete.\n// It was previously the full messages applet, now that there is a widget\n// for that, it is getting useless.\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"desktop.h\"\n#include \"g_widget.h\"\n#include \"textbox.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_app_messages  TB_Message;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TB_Message_Init_Values(void)\n{\n    t_app_messages *app = &TB_Message;  // Global instance\n\n    app->active           = FALSE;\n    app->log_file         = NULL;\n    app->log_filename     = NULL;\n    app->box              = NULL;\n    app->widget_textbox   = NULL;\n}\n\nstatic void TB_Message_Layout(t_app_messages *app, bool setup)\n{\n    al_set_target_bitmap(app->box->gfx_buffer);\n    al_clear_to_color(COLOR_SKIN_WINDOW_BACKGROUND);\n\n    // Add closebox widget\n    if (setup)\n        widget_closebox_add(app->box, (t_widget_callback)TB_Message_Switch);\n\n    // Create textbox widget\n    t_frame frame;\n    frame.pos.x = 4;\n    frame.pos.y = 2;\n    frame.size.x = app->box->frame.size.x - (4*2);\n    frame.size.y = app->box->frame.size.y - (2*2);\n    if (setup)\n        app->widget_textbox = widget_textbox_add(app->box, &frame, (t_font_id)g_config.font_messages);\n    else\n        app->widget_textbox->frame = frame;\n}\n\nvoid        TB_Message_Init()\n{\n    t_app_messages *app = &TB_Message;  // Global instance\n    t_font_id font_id = (t_font_id)g_config.font_messages;\n\n    app->active = true;\n\n    // Create box\n    t_frame frame;\n    frame.pos.x  = 16;\n    frame.pos.y  = 626;\n    frame.size.x = (48 * Font_Height(font_id)) + (4*2); // 4*2=padding\n    frame.size.y = (8 * Font_Height(font_id)) + (2*2); // 2*2=padding\n    app->box = gui_box_new(&frame, Msg_Get(MSG_Message_BoxTitle));\n    app->box->flags |= GUI_BOX_FLAGS_ALLOW_RESIZE;\n\n    // Register to desktop\n    Desktop_Register_Box(\"MESSAGES\", app->box, true, &app->active);\n\n    // Layout\n    TB_Message_Layout(app, true);\n\n    // Open log file\n    if (app->log_filename != NULL)\n    {\n        app->log_file = fopen(app->log_filename, \"a+t\");\n        if (app->log_file)\n            fprintf(app->log_file, Msg_Get(MSG_Log_Session_Start), meka_date_getf());\n    }\n}\n\nvoid    TB_Message_Update()\n{\n    t_app_messages *app = &TB_Message;  // Global instance\n\n    // Skip update if not active\n    if (!app->active)\n        return;\n\n    // If skin has changed, redraw everything\n    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)\n    {\n        TB_Message_Layout(app, FALSE);\n        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;\n    }\n}\n\nvoid    TB_Message_Switch(void)\n{\n    t_app_messages *app = &TB_Message;  // Global instance\n\n    if (app->active ^= 1)\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Message_Enabled));\n    else\n        Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Message_Disabled));\n    gui_box_show (app->box, app->active, TRUE);\n    gui_menu_toggle_check (menus_ID.tools, 0);\n}\n\nvoid    TB_Message_Print (const char *line)\n{\n    t_app_messages *app = &TB_Message;  // Global instance\n\n    widget_textbox_print_scroll(app->widget_textbox, TRUE, line);\n    if (app->log_file)\n       fprintf(app->log_file, \"%s\\n\", line);\n}\n\nvoid    TB_Message_Destroy (void)\n{\n    t_app_messages *app = &TB_Message;  // Global instance\n\n    // FIXME: widgets are not meant to be destroyed yet\n    // ...\n    if (app->log_file)\n    {\n        fclose (app->log_file);\n        app->log_file = NULL;\n    }\n    if (app->log_filename)\n    {\n        free (app->log_filename);\n        app->log_filename = NULL;\n    }\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/textbox.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - textbox.h\r\n// Text Box Applet - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifndef _MEKA_TEXTBOX_H_\r\n#define _MEKA_TEXTBOX_H_\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_app_messages\r\n{\r\n    bool        active;\r\n    char *      log_filename;\r\n    FILE *      log_file;\r\n    t_gui_box * box;\r\n    t_widget *  widget_textbox;\r\n};\r\n\r\nextern t_app_messages  TB_Message;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    TB_Message_Init_Values  (void);\r\nvoid    TB_Message_Init         (void);\r\nvoid    TB_Message_Update       (void);\r\nvoid    TB_Message_Switch       (void);\r\nvoid    TB_Message_Destroy      (void);\r\nvoid    TB_Message_Print        (const char *line);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n#endif // _MEKA_TEXTBOX_H_\r\n\r\n\r\n"
  },
  {
    "path": "meka/srcs/tools.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - tools.c\r\n// Various helpers - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <time.h>\r\n#include <stdio.h>\r\n#ifdef ARCH_WIN32\r\n #include <Windows.h>\r\n #include <Winbase.h>\r\n #pragma warning (disable: 4996) // ''_snprintf': This function or variable may be unsafe'\r\n // #include \"shared.h\"\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Path Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    StrPath_RemoveExtension(char* buf)\r\n{\r\n    // Assume single dotted extension\r\n    char *p = strrchr(buf, '.');\r\n    if (p != NULL)\r\n        *p = EOSTR;\r\n}\r\n\r\nvoid    StrPath_GetExtension(char* buf)\r\n{\r\n    const char *p = strrchr (buf, '.');\r\n    if (p == NULL)\r\n        return;\r\n\r\n    char tmp[FILENAME_LEN];\r\n    strcpy(tmp, p + 1);\r\n    strcpy(buf, tmp);\r\n}\r\n\r\nvoid    StrPath_RemoveDirectory(char* buf)\r\n{\r\n    char tmp[FILENAME_LEN];\r\n\r\n    const char* p = strrchr(buf, '/');\r\n\r\n#ifdef ARCH_WIN32\r\n    const char *p2 = strrchr(buf, '\\\\');\r\n    if (p2 != NULL && p2 > p)\r\n        p = p2;\r\n#endif\r\n\r\n    if (p != NULL)\r\n    {\r\n        p++;\r\n        strcpy(tmp, p);\r\n        strcpy(buf, tmp);\r\n    }\r\n}\r\n\r\n// Extract filename from 'src' and copy it to location 'dst'\r\nvoid    StrPath_RemoveDirectory(char *dst, const char *src)\r\n{\r\n    const char* p = strrchr(src, '/');\r\n\r\n#ifdef ARCH_WIN32\r\n    const char *p2 = strrchr(src, '\\\\');\r\n    if (p2 != NULL && p2 > p)\r\n        p = p2;\r\n#endif\r\n\r\n    p = (p ? p + 1 : src);\r\n    strcpy(dst, p);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Time Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nchar *  meka_date_getf()\r\n{\r\n    time_t t;\r\n    time (&t);\r\n    return (ctime (&t));\r\n}\r\n\r\nchar *  meka_time_getf(char* str)\r\n{\r\n#ifdef ARCH_WIN32\r\n    SYSTEMTIME t;\r\n    GetLocalTime (&t);\r\n    sprintf(str, \"%02i:%02i:%02i\", t.wHour, t.wMinute, t.wSecond);\r\n#else\r\n    time_t t = time(NULL);\r\n    struct tm tm = *localtime(&t);\r\n    sprintf(str, \"%02i:%02i:%02i\", tm.tm_hour, tm.tm_min, tm.tm_sec);\r\n#endif\r\n    return (str);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/tools.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - tools.h\r\n// Various tools - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Path Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    StrPath_GetExtension(char* buf);\r\nvoid    StrPath_RemoveExtension(char* buf);\r\n\r\n// Extract filename from 'src' and copy it to location 'dst'\r\nvoid    StrPath_RemoveDirectory(char* buf);\r\nvoid    StrPath_RemoveDirectory(char* dst, const char* src);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Time Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nchar *  meka_date_getf(void);\r\nchar *  meka_time_getf(char* str);\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/tvoekaki.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - tvoekaki.c\n// TV Oekaki / Graphic Table Emulation - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"mappers.h\"\n#include \"tvoekaki.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nt_tvoekaki  TVOekaki;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TVOekaki_Init()\n{\n    TVOekaki.X = TVOekaki.Y = 0;\n    TVOekaki.Infos = TVOEKAKI_BIT_AXIS | TVOEKAKI_BIT_ON_BOARD;\n}\n\n// Terebi Oekaki update function\n// This is supposed to work with an analog mouse\n// Fullscreen mode should be enabled to work properly\n// Need to rename variable to something mouse independant :-)\nvoid    TVOekaki_Update(int device_x, int device_y, int device_b_field)\n{\n    int    nmouse_b = device_b_field;\n    static int lmouse_b = 0;\n\n    TVOekaki.X = device_x;\n    TVOekaki.Y = device_y;\n\n    // Those values were experimentally found\n    // Apparently the real board doesn't allow going to the far sides\n\n    TVOekaki.X -= 5;\n    if (TVOekaki.X < 0) TVOekaki.X = 0;\n    if (TVOekaki.X > (g_driver->x_res - 1) - 4) TVOekaki.X = (g_driver->x_res - 1) - 4;\n\n    TVOekaki.Y -= 4;\n    if (TVOekaki.Y < 0) TVOekaki.Y = 0;\n    if (TVOekaki.Y > (g_driver->y_res - 1)) TVOekaki.Y = (g_driver->y_res - 1);\n    TVOekaki.Y += 8 * 4;\n\n    if (nmouse_b & 1)\n        TVOekaki.Infos |= (TVOEKAKI_BIT_PRESSED);\n    else\n        TVOekaki.Infos &= (~TVOEKAKI_BIT_PRESSED);\n\n    if ((nmouse_b & 2) != 0 && (lmouse_b & 2) == 0)\n    {\n        TVOekaki.Infos ^= (TVOEKAKI_BIT_ON_BOARD);\n    }\n\n    lmouse_b = nmouse_b;\n}\n\n// [MAPPER: TV OEKAKI] READ BYTE ----------------------------------------------\n// FIXME: since the TV Oekaki ROM is 0x8000 bytes, removing the Read handler\n// should be possible. The update() and write() functions will then directly\n// poke in the memory space.\nREAD_FUNC (Read_Mapper_TVOekaki)\n{\n    switch (Addr)\n    {\n    case 0x8000: // Pen Pressure, Pen Position Ready\n        // Bit 0: Pen Pressure (0: pressed, 1: unpressed)\n        // Bit 7: Pen Position Ready (0: ready, 1: still reading)\n        return (TVOEKAKI_PRESSED ? 0x00 : 0x01);\n    case 0xA000:\n        if (TVOEKAKI_NOT_ON_BOARD)\n            return (0x00);\n        if (TVOEKAKI_AXIS_X)\n            return (TVOekaki.X);\n        return (TVOekaki.Y);\n    }\n    return (Mem_Pages [Addr >> 13] [Addr]);\n}\n\n// [MAPPER: TV OEKAKI] WRITE BYTE --------------------------------------------\nWRITE_FUNC (Write_Mapper_TVOekaki)\n{\n switch (Addr)\n   {\n   case 0x6000: // Pen Axis Choice\n        // Bit 0: Pen Axis Choice (0: X, 1: Y)\n        if (Value & 1)\n           TVOekaki.Infos &= (~TVOEKAKI_BIT_AXIS);\n        else\n           TVOekaki.Infos |= (TVOEKAKI_BIT_AXIS);\n        break;\n   case 0xA000:\n        break;\n   }\n switch (Addr >> 13)\n   {\n   // RAM [0xC000] = [0xE000] -----------------------------------------------\n   case 6: Mem_Pages [6] [Addr & 0xEFFF] = Mem_Pages [6] [Addr | 0x1000] = Value; return;\n   case 7: Mem_Pages [7] [Addr & 0xEFFF] = Mem_Pages [7] [Addr | 0x1000] = Value; return;\n   }\n\n Write_Error (Addr, Value);\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/tvoekaki.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - tvoekaki.h\n// TV Oekaki / Graphic Table Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TVOekaki_Init();\nvoid    TVOekaki_Update(int device_x, int device_y, int device_b_field);\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define TVOEKAKI_BIT_AXIS      (1)\n#define TVOEKAKI_BIT_PRESSED   (2)\n#define TVOEKAKI_BIT_ON_BOARD  (4)\n\n#define TVOEKAKI_AXIS_X        ((TVOekaki.Infos & TVOEKAKI_BIT_AXIS) == 0)\n#define TVOEKAKI_AXIS_Y        ((TVOekaki.Infos & TVOEKAKI_BIT_AXIS) != 0)\n#define TVOEKAKI_PRESSED       ((TVOekaki.Infos & TVOEKAKI_BIT_PRESSED) != 0)\n#define TVOEKAKI_NOT_PRESSED   ((TVOekaki.Infos & TVOEKAKI_BIT_PRESSED) == 0)\n#define TVOEKAKI_ON_BOARD      ((TVOekaki.Infos & TVOEKAKI_BIT_ON_BOARD) != 0)\n#define TVOEKAKI_NOT_ON_BOARD  ((TVOekaki.Infos & TVOEKAKI_BIT_ON_BOARD) == 0)\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_tvoekaki\n{\n    int     X, Y;\n    u8      Infos;\n};\n\nextern t_tvoekaki  TVOekaki;\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/tvtype.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - tvtype.c\r\n// TV Types emulation (NTSC/PAL/SECAM) - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"tvtype.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_tv_type * TV_Type_User = NULL;\r\n\r\nt_tv_type TV_Type_Table [] =\r\n{\r\n    { TVTYPE_NTSC,      \"NTSC\",       262,  60,  3579540 }, // 262 lines @ 60 Hz, 3.579540 MHz\r\n    { TVTYPE_PAL_SECAM, \"PAL/SECAM\",  313,  50,  3546893 }  // 313 lines @ 50 Hz, 3.546893 MHz\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    TVType_Init_Values()\r\n{\r\n    TV_Type_User = &TV_Type_Table[TVTYPE_NTSC];\r\n    g_machine.TV = TV_Type_User;\r\n    g_machine.TV_lines = TV_Type_User->screen_lines;\r\n    TVType_Update_Values();\r\n}\r\n\r\nvoid    TVType_Update_Values()\r\n{\r\n    // FIXME: Update VGM stuff\r\n}\r\n\r\nvoid    TVType_Set(int tv_type, bool verbose)\r\n{\r\n    TV_Type_User = &TV_Type_Table[tv_type];\r\n    g_machine.TV = TV_Type_User;\r\n    g_machine.TV_lines = TV_Type_User->screen_lines;\r\n\r\n    // FIXME: CPU_Clock_Current is not taken into account for IPeriod in CPU emulation\r\n\r\n    // 262 * 228 = 59736, * 60 = 3584160\r\n    // 313 * 228 = 71364, * 50 = 3568200\r\n\r\n    // SN76489_SetClock(opt.TV_Lines_Current * opt.Cur_IPeriod); // 59736 for NTSC\r\n    // SN76489_SetClock(g_machine.TV->CPU_clock);\r\n    Sound_UpdateClockSpeed();\r\n\r\n    if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_SAMPLE)\r\n        VGM_Update_Timing (&Sound.LogVGM);\r\n\r\n    if (verbose)\r\n    {\r\n        // Print message & and update GUI checks\r\n        Msg(MSGT_USER, Msg_Get(MSG_TVType_Set), TV_Type_User->name);\r\n        Msg(MSGT_USER_LOG, Msg_Get(MSG_TVType_Info_Speed), TV_Type_User->screen_frequency);\r\n        gui_menu_uncheck_all (menus_ID.tvtype);\r\n        gui_menu_check (menus_ID.tvtype, tv_type);\r\n        // Note that GUI checks are NOT updated if verbose mode is not set.\r\n        // The reason is the parameters in MEKA.NAM can force a TV type, but we don't\r\n        // want the user to be notified by that (unless he manually reoverride it).\r\n    }\r\n}\r\n\r\nvoid    TVType_Set_NTSC (void)\r\n{\r\n    TVType_Set (TVTYPE_NTSC, TRUE);\r\n}\r\n\r\nvoid    TVType_Set_PAL_SECAM (void)\r\n{\r\n    TVType_Set (TVTYPE_PAL_SECAM, TRUE);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/tvtype.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - tvtype.h\n// TV Types emulation (NTSC/PAL/SECAM) - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Definitions\n//-----------------------------------------------------------------------------\n\n#define TVTYPE_NTSC       (0)\n#define TVTYPE_PAL_SECAM  (1)\n#define TVTYPE_AUTO       (2) // AUTO must not be 0 or 1 because the values are used for menu ticks positionning\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TVType_Init_Values();\nvoid    TVType_Update_Values();\n\nvoid    TVType_Set(int tv_type, bool verbose);\nvoid    TVType_Set_NTSC();\nvoid    TVType_Set_PAL_SECAM();\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_tv_type\n{\n    int     id;\n    const char *  name;\n    int     screen_lines;\n    int     screen_frequency;  // in Hz\n    int     CPU_clock;\n};\n\nextern t_tv_type        TV_Type_Table[];\nextern t_tv_type *      TV_Type_User;\n// Note: TV Type for emulation is pointed by 'g_machine.TV_Type'\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/unzip.cpp",
    "content": "/*\r\n** unzip.c -- IO on .zip files using zlib\r\n** Version 0.15 beta, Mar 19th, 1998,\r\n** Read unzip.h for more info\r\n*/\r\n\r\n#include \"shared.h\"\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n#include \"zlib.h\"\r\n#include \"unzip.h\"\r\n#ifdef ARCH_WIN32\r\n#pragma warning (disable: 4996) // ''_snprintf': This function or variable may be unsafe'\r\n#endif\r\n\r\n#ifdef STDC\r\n//#  include <stddef.h>\r\n#  include <string.h>\r\n#  include <stdlib.h>\r\n#endif\r\n#ifdef NO_ERRNO_H\r\n// OMAR: errno is unused anyway\r\n//    extern int errno;\r\n#else\r\n#   include <errno.h>\r\n#endif\r\n\r\n\r\n#ifndef local\r\n#  define local static\r\n#endif\r\n/* compile with -Dlocal if your debugger can't find static symbols */\r\n\r\n\r\n\r\n#if !defined(ARCH_UNIX) && !defined(CASESENSITIVITYDEFAULT_YES) && \\\r\n                      !defined(CASESENSITIVITYDEFAULT_NO)\r\n#define CASESENSITIVITYDEFAULT_NO\r\n#endif\r\n\r\n\r\n#ifndef UNZ_BUFSIZE\r\n#define UNZ_BUFSIZE (16384)\r\n#endif\r\n\r\n#ifndef UNZ_MAXFILENAMEINZIP\r\n#define UNZ_MAXFILENAMEINZIP (256)\r\n#endif\r\n\r\n#ifndef ALLOC\r\n# define ALLOC(size) (malloc(size))\r\n#endif\r\n#ifndef TRYFREE\r\n# define TRYFREE(p) {if (p) free(p);}\r\n#endif\r\n\r\n#define SIZECENTRALDIRITEM (0x2e)\r\n#define SIZEZIPLOCALHEADER (0x1e)\r\n\r\n/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */\r\n\r\n#ifndef SEEK_CUR\r\n#define SEEK_CUR    1\r\n#endif\r\n\r\n#ifndef SEEK_END\r\n#define SEEK_END    2\r\n#endif\r\n\r\n#ifndef SEEK_SET\r\n#define SEEK_SET    0\r\n#endif\r\n\r\n// Unused in code\r\n// const char unz_copyright[] =\r\n//    \" unzip 0.15 Copyright 1998 Gilles Vollant \";\r\n\r\n/* unz_file_info_interntal contain internal info about a file in zipfile*/\r\ntypedef struct unz_file_info_internal_s\r\n{\r\n    uLong offset_curfile;/* relative offset of local header 4 bytes */\r\n} unz_file_info_internal;\r\n\r\n\r\n/* file_in_zip_read_info_s contain internal information about a file in zipfile,\r\n    when reading and decompress it */\r\ntypedef struct\r\n{\r\n    char  *read_buffer;         /* internal buffer for compressed data */\r\n    z_stream stream;            /* zLib stream structure for inflate */\r\n\r\n    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/\r\n    uLong stream_initialised;   /* flag set if stream structure is initialised*/\r\n\r\n    uLong offset_local_extrafield;/* offset of the local extra field */\r\n    uInt  size_local_extrafield;/* size of the local extra field */\r\n    uLong pos_local_extrafield;   /* position in the local extra field in read*/\r\n\r\n    uLong crc32;                /* crc32 of all data uncompressed */\r\n    uLong crc32_wait;           /* crc32 we must obtain after decompress all */\r\n    uLong rest_read_compressed; /* number of byte to be decompressed */\r\n    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/\r\n    FILE* file;                 /* io structore of the zipfile */\r\n    uLong compression_method;   /* compression method (0==store) */\r\n    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r\n} file_in_zip_read_info_s;\r\n\r\n\r\n/* unz_s contain internal information about the zipfile\r\n*/\r\ntypedef struct\r\n{\r\n    FILE* file;                 /* io structore of the zipfile */\r\n    unz_global_info gi;       /* public global information */\r\n    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r\n    uLong num_file;             /* number of the current file in the zipfile*/\r\n    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/\r\n    uLong current_file_ok;      /* flag about the usability of the current file*/\r\n    uLong central_pos;          /* position of the beginning of the central dir*/\r\n\r\n    uLong size_central_dir;     /* size of the central directory  */\r\n    uLong offset_central_dir;   /* offset of start of central directory with\r\n                                   respect to the starting disk number */\r\n\r\n    unz_file_info cur_file_info; /* public info about the current file in zip*/\r\n    unz_file_info_internal cur_file_info_internal; /* private info about it*/\r\n    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current\r\n                                        file if we are decompressing it */\r\n} unz_s;\r\n\r\n\r\n/* ===========================================================================\r\n     Read a byte from a gz_stream; update next_in and avail_in. Return EOF\r\n   for end of file.\r\n   IN assertion: the stream s has been sucessfully opened for reading.\r\n*/\r\n\r\n\r\nlocal int unzlocal_getByte(FILE *fin, int *pi)\r\n{\r\n    unsigned char c;\r\n    int err = fread(&c, 1, 1, fin);\r\n    if (err==1)\r\n    {\r\n        *pi = (int)c;\r\n        return UNZ_OK;\r\n    }\r\n    else\r\n    {\r\n        if (ferror(fin))\r\n            return UNZ_ERRNO;\r\n        else\r\n            return UNZ_EOF;\r\n    }\r\n}\r\n\r\n\r\n/* ===========================================================================\r\n   Reads a long in LSB order from the given gz_stream. Sets\r\n*/\r\nlocal int unzlocal_getShort (FILE * fin, uLong *pX)\r\n{\r\n    uLong x ;\r\n    int i;\r\n    int err;\r\n\r\n    err = unzlocal_getByte(fin,&i);\r\n    x = (uLong)i;\r\n\r\n    if (err==UNZ_OK)\r\n        err = unzlocal_getByte(fin,&i);\r\n    x += ((uLong)i)<<8;\r\n\r\n    if (err==UNZ_OK)\r\n        *pX = x;\r\n    else\r\n        *pX = 0;\r\n    return err;\r\n}\r\n\r\nlocal int unzlocal_getLong (FILE *fin, uLong *pX)\r\n{\r\n    uLong x ;\r\n    int i;\r\n    int err;\r\n\r\n    err = unzlocal_getByte(fin,&i);\r\n    x = (uLong)i;\r\n\r\n    if (err==UNZ_OK)\r\n        err = unzlocal_getByte(fin,&i);\r\n    x += ((uLong)i)<<8;\r\n\r\n    if (err==UNZ_OK)\r\n        err = unzlocal_getByte(fin,&i);\r\n    x += ((uLong)i)<<16;\r\n\r\n    if (err==UNZ_OK)\r\n        err = unzlocal_getByte(fin,&i);\r\n    x += ((uLong)i)<<24;\r\n\r\n    if (err==UNZ_OK)\r\n        *pX = x;\r\n    else\r\n        *pX = 0;\r\n    return err;\r\n}\r\n\r\n\r\n/* My own strcmpi / strcasecmp */\r\nlocal int strcmpcasenosensitive_internal (const char *fileName1, const char *fileName2)\r\n{\r\n    for (;;)\r\n    {\r\n        char c1=*(fileName1++);\r\n        char c2=*(fileName2++);\r\n        if ((c1>='a') && (c1<='z'))\r\n            c1 -= 0x20;\r\n        if ((c2>='a') && (c2<='z'))\r\n            c2 -= 0x20;\r\n        if (c1=='\\0')\r\n            return ((c2=='\\0') ? 0 : -1);\r\n        if (c2=='\\0')\r\n            return 1;\r\n        if (c1<c2)\r\n            return -1;\r\n        if (c1>c2)\r\n            return 1;\r\n    }\r\n}\r\n\r\n\r\n#ifdef  CASESENSITIVITYDEFAULT_NO\r\n#define CASESENSITIVITYDEFAULTVALUE 2\r\n#else\r\n#define CASESENSITIVITYDEFAULTVALUE 1\r\n#endif\r\n\r\n#ifndef STRCMPCASENOSENTIVEFUNCTION\r\n#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal\r\n#endif\r\n\r\n/*\r\n   Compare two filename (fileName1,fileName2).\r\n   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\r\n   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\r\n                                                                or strcasecmp)\r\n   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\r\n        (like 1 on Unix, 2 on Windows)\r\n\r\n*/\r\nextern int ZEXPORT unzStringFileNameCompare (const char* fileName1,const char* fileName2, int iCaseSensitivity)\r\n{\r\n    if (iCaseSensitivity==0)\r\n        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;\r\n\r\n    if (iCaseSensitivity==1)\r\n        return strcmp(fileName1,fileName2);\r\n\r\n    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);\r\n}\r\n\r\n#define BUFREADCOMMENT (0x400)\r\n\r\n/*\r\n  Locate the Central directory of a zipfile (at the end, just before\r\n    the global comment)\r\n*/\r\nlocal uLong unzlocal_SearchCentralDir(FILE *fin)\r\n{\r\n    unsigned char* buf;\r\n    uLong uSizeFile;\r\n    uLong uBackRead;\r\n    uLong uMaxBack=0xffff; /* maximum size of global comment */\r\n    uLong uPosFound=0;\r\n\r\n    if (fseek(fin,0,SEEK_END) != 0)\r\n        return 0;\r\n\r\n\r\n    uSizeFile = ftell( fin );\r\n\r\n    if (uMaxBack>uSizeFile)\r\n        uMaxBack = uSizeFile;\r\n\r\n    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\r\n    if (buf==NULL)\r\n        return 0;\r\n\r\n    uBackRead = 4;\r\n    while (uBackRead<uMaxBack)\r\n    {\r\n        uLong uReadSize,uReadPos ;\r\n        int i;\r\n        if (uBackRead+BUFREADCOMMENT>uMaxBack)\r\n            uBackRead = uMaxBack;\r\n        else\r\n            uBackRead+=BUFREADCOMMENT;\r\n        uReadPos = uSizeFile-uBackRead ;\r\n\r\n        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\r\n                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);\r\n        if (fseek(fin,uReadPos,SEEK_SET)!=0)\r\n            break;\r\n\r\n        if (fread(buf,(uInt)uReadSize,1,fin)!=1)\r\n            break;\r\n\r\n                for (i=(int)uReadSize-3; (i--)>0;)\r\n            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\r\n                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))\r\n            {\r\n                uPosFound = uReadPos+i;\r\n                break;\r\n            }\r\n\r\n        if (uPosFound!=0)\r\n            break;\r\n    }\r\n    TRYFREE(buf);\r\n    return uPosFound;\r\n}\r\n\r\n/*\r\n  Open a Zip file. path contain the full pathname (by example,\r\n     on a Windows NT computer \"c:\\\\test\\\\zlib109.zip\" or on an Unix computer\r\n     \"zlib/zlib109.zip\".\r\n     If the zipfile cannot be opened (file don't exist or in not valid), the\r\n       return value is NULL.\r\n     Else, the return value is a unzFile Handle, usable with other function\r\n       of this unzip package.\r\n*/\r\nextern unzFile ZEXPORT unzOpen (const char *path)\r\n{\r\n    unz_s us;\r\n    unz_s *s;\r\n    uLong central_pos,uL;\r\n    FILE * fin ;\r\n\r\n    uLong number_disk;          /* number of the current dist, used for\r\n                                   spaning ZIP, unsupported, always 0*/\r\n    uLong number_disk_with_CD;  /* number the the disk with central dir, used\r\n                                   for spaning ZIP, unsupported, always 0*/\r\n    uLong number_entry_CD;      /* total number of entries in\r\n                                   the central dir\r\n                                   (same than number_entry on nospan) */\r\n\r\n    int err=UNZ_OK;\r\n\r\n//    if (unz_copyright[0]!=' ')\r\n//        return NULL;\r\n\r\n    fin=fopen(path,\"rb\");\r\n    if (fin==NULL)\r\n        return NULL;\r\n\r\n    central_pos = unzlocal_SearchCentralDir(fin);\r\n    if (central_pos==0)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (fseek(fin,central_pos,SEEK_SET)!=0)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* the signature, already checked */\r\n    if (unzlocal_getLong(fin,&uL)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* number of this disk */\r\n    if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* number of the disk with the start of the central directory */\r\n    if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* total number of entries in the central dir on this disk */\r\n    if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* total number of entries in the central dir */\r\n    if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if ((number_entry_CD!=us.gi.number_entry) ||\r\n        (number_disk_with_CD!=0) ||\r\n        (number_disk!=0))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    /* size of the central directory */\r\n    if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* offset of start of central directory with respect to the\r\n          starting disk number */\r\n    if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    /* zipfile comment length */\r\n    if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&\r\n        (err==UNZ_OK))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    if (err!=UNZ_OK)\r\n    {\r\n        fclose(fin);\r\n        return NULL;\r\n    }\r\n\r\n    us.file=fin;\r\n    us.byte_before_the_zipfile = central_pos -\r\n                            (us.offset_central_dir+us.size_central_dir);\r\n    us.central_pos = central_pos;\r\n    us.pfile_in_zip_read = NULL;\r\n\r\n\r\n    s=(unz_s*)ALLOC(sizeof(unz_s));\r\n    *s=us;\r\n    unzGoToFirstFile((unzFile)s);\r\n    return (unzFile)s;\r\n}\r\n\r\n\r\n/*\r\n  Close a ZipFile opened with unzipOpen.\r\n  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),\r\n    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\r\n  return UNZ_OK if there is no problem. */\r\nextern int ZEXPORT unzClose (unzFile file)\r\n{\r\n    unz_s* s;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n\r\n    if (s->pfile_in_zip_read!=NULL)\r\n        unzCloseCurrentFile(file);\r\n\r\n    fclose(s->file);\r\n    TRYFREE(s);\r\n    return UNZ_OK;\r\n}\r\n\r\n\r\n/*\r\n  Write info about the ZipFile in the *pglobal_info structure.\r\n  No preparation of the structure is needed\r\n  return UNZ_OK if there is no problem. */\r\nextern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info)\r\n{\r\n    unz_s* s;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    *pglobal_info=s->gi;\r\n    return UNZ_OK;\r\n}\r\n\r\n\r\n/*\r\n   Translate date/time from Dos format to tm_unz (readable more easilty)\r\n*/\r\nlocal void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)\r\n{\r\n    uLong uDate;\r\n    uDate = (uLong)(ulDosDate>>16);\r\n    ptm->tm_mday = (uInt)(uDate&0x1f) ;\r\n    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;\r\n    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;\r\n\r\n    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);\r\n    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;\r\n    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;\r\n}\r\n\r\n/*\r\n  Get Info about the current file in the zipfile, with internal only info\r\n*/\r\nlocal int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,\r\n                                                  unz_file_info *pfile_info,\r\n                                                  unz_file_info_internal\r\n                                                  *pfile_info_internal,\r\n                                                  char *szFileName,\r\n                                                  uLong fileNameBufferSize,\r\n                                                  void *extraField,\r\n                                                  uLong extraFieldBufferSize,\r\n                                                  char *szComment,\r\n                                                  uLong commentBufferSize));\r\n\r\nlocal int unzlocal_GetCurrentFileInfoInternal (unzFile file,\r\n                                              unz_file_info *pfile_info,\r\n                                              unz_file_info_internal *pfile_info_internal,\r\n                                              char *szFileName, uLong fileNameBufferSize,\r\n                                              void *extraField, uLong extraFieldBufferSize,\r\n                                              char *szComment,  uLong commentBufferSize)\r\n{\r\n    unz_s* s;\r\n    unz_file_info file_info;\r\n    unz_file_info_internal file_info_internal;\r\n    int err=UNZ_OK;\r\n    uLong uMagic;\r\n    long lSeek=0;\r\n\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)\r\n        err=UNZ_ERRNO;\r\n\r\n\r\n    /* we check the magic */\r\n    if (err==UNZ_OK)\r\n                {\r\n        if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)\r\n            err=UNZ_ERRNO;\r\n        else if (uMagic!=0x02014b50)\r\n            err=UNZ_BADZIPFILE;\r\n                }\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);\r\n\r\n    if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    lSeek+=file_info.size_filename;\r\n    if ((err==UNZ_OK) && (szFileName!=NULL))\r\n    {\r\n        uLong uSizeRead ;\r\n        if (file_info.size_filename<fileNameBufferSize)\r\n        {\r\n            *(szFileName+file_info.size_filename)='\\0';\r\n            uSizeRead = file_info.size_filename;\r\n        }\r\n        else\r\n            uSizeRead = fileNameBufferSize;\r\n\r\n        if ((file_info.size_filename>0) && (fileNameBufferSize>0))\r\n            if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)\r\n                err=UNZ_ERRNO;\r\n        lSeek -= uSizeRead;\r\n    }\r\n\r\n\r\n    if ((err==UNZ_OK) && (extraField!=NULL))\r\n    {\r\n        uLong uSizeRead ;\r\n        if (file_info.size_file_extra<extraFieldBufferSize)\r\n            uSizeRead = file_info.size_file_extra;\r\n        else\r\n            uSizeRead = extraFieldBufferSize;\r\n\r\n        if (lSeek!=0)\r\n                        {\r\n                        if (fseek(s->file,lSeek,SEEK_CUR)==0)\r\n                lSeek=0;\r\n            else\r\n                err=UNZ_ERRNO;\r\n                        }\r\n        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))\r\n            if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)\r\n                err=UNZ_ERRNO;\r\n        lSeek += file_info.size_file_extra - uSizeRead;\r\n    }\r\n    else\r\n        lSeek+=file_info.size_file_extra;\r\n\r\n\r\n    if ((err==UNZ_OK) && (szComment!=NULL))\r\n    {\r\n        uLong uSizeRead ;\r\n        if (file_info.size_file_comment<commentBufferSize)\r\n        {\r\n            *(szComment+file_info.size_file_comment)='\\0';\r\n            uSizeRead = file_info.size_file_comment;\r\n        }\r\n        else\r\n            uSizeRead = commentBufferSize;\r\n\r\n        if (lSeek!=0)\r\n                        {\r\n                        if (fseek(s->file,lSeek,SEEK_CUR)==0)\r\n                lSeek=0;\r\n            else\r\n                err=UNZ_ERRNO;\r\n                        }\r\n        if ((file_info.size_file_comment>0) && (commentBufferSize>0))\r\n            if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)\r\n                err=UNZ_ERRNO;\r\n        lSeek+=file_info.size_file_comment - uSizeRead;\r\n    }\r\n    else\r\n        lSeek+=file_info.size_file_comment;\r\n\r\n    if ((err==UNZ_OK) && (pfile_info!=NULL))\r\n        *pfile_info=file_info;\r\n\r\n    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))\r\n        *pfile_info_internal=file_info_internal;\r\n\r\n    return err;\r\n}\r\n\r\n\r\n\r\n/*\r\n  Write info about the ZipFile in the *pglobal_info structure.\r\n  No preparation of the structure is needed\r\n  return UNZ_OK if there is no problem.\r\n*/\r\nextern int ZEXPORT unzGetCurrentFileInfo (      unzFile file,\r\n                                                unz_file_info *pfile_info,\r\n                                                char *szFileName, uLong fileNameBufferSize,\r\n                                                void *extraField, uLong extraFieldBufferSize,\r\n                                                char *szComment,  uLong commentBufferSize)\r\n{\r\n    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,\r\n                                                szFileName,fileNameBufferSize,\r\n                                                extraField,extraFieldBufferSize,\r\n                                                szComment,commentBufferSize);\r\n}\r\n\r\n/*\r\n  Set the current file of the zipfile to the first file.\r\n  return UNZ_OK if there is no problem\r\n*/\r\nextern int ZEXPORT unzGoToFirstFile (unzFile file)\r\n{\r\n    int err=UNZ_OK;\r\n    unz_s* s;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    s->pos_in_central_dir=s->offset_central_dir;\r\n    s->num_file=0;\r\n    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r\n                                             &s->cur_file_info_internal,\r\n                                             NULL,0,NULL,0,NULL,0);\r\n    s->current_file_ok = (err == UNZ_OK);\r\n    return err;\r\n}\r\n\r\n\r\n/*\r\n  Set the current file of the zipfile to the next file.\r\n  return UNZ_OK if there is no problem\r\n  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\r\n*/\r\nextern int ZEXPORT unzGoToNextFile (unzFile file)\r\n{\r\n    unz_s* s;\r\n    int err;\r\n\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    if (!s->current_file_ok)\r\n        return UNZ_END_OF_LIST_OF_FILE;\r\n    if (s->num_file+1==s->gi.number_entry)\r\n        return UNZ_END_OF_LIST_OF_FILE;\r\n\r\n    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +\r\n            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;\r\n    s->num_file++;\r\n    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r\n                                               &s->cur_file_info_internal,\r\n                                               NULL,0,NULL,0,NULL,0);\r\n    s->current_file_ok = (err == UNZ_OK);\r\n    return err;\r\n}\r\n\r\n\r\n/*\r\n  Try locate the file szFileName in the zipfile.\r\n  For the iCaseSensitivity signification, see unzipStringFileNameCompare\r\n\r\n  return value :\r\n  UNZ_OK if the file is found. It becomes the current file.\r\n  UNZ_END_OF_LIST_OF_FILE if the file is not found\r\n*/\r\nextern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)\r\n{\r\n    unz_s* s;\r\n    int err;\r\n\r\n\r\n    uLong num_fileSaved;\r\n    uLong pos_in_central_dirSaved;\r\n\r\n\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n\r\n    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)\r\n        return UNZ_PARAMERROR;\r\n\r\n    s=(unz_s*)file;\r\n    if (!s->current_file_ok)\r\n        return UNZ_END_OF_LIST_OF_FILE;\r\n\r\n    num_fileSaved = s->num_file;\r\n    pos_in_central_dirSaved = s->pos_in_central_dir;\r\n\r\n    err = unzGoToFirstFile(file);\r\n\r\n    while (err == UNZ_OK)\r\n    {\r\n        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];\r\n        unzGetCurrentFileInfo(file,NULL,\r\n                                szCurrentFileName,sizeof(szCurrentFileName)-1,\r\n                                NULL,0,NULL,0);\r\n        if (unzStringFileNameCompare(szCurrentFileName,\r\n                                        szFileName,iCaseSensitivity)==0)\r\n            return UNZ_OK;\r\n        err = unzGoToNextFile(file);\r\n    }\r\n\r\n    s->num_file = num_fileSaved ;\r\n    s->pos_in_central_dir = pos_in_central_dirSaved ;\r\n    return err;\r\n}\r\n\r\n\r\n/*\r\n  Read the local header of the current zipfile\r\n  Check the coherency of the local header and info in the end of central\r\n        directory about this file\r\n  store in *piSizeVar the size of extra info in local header\r\n        (filename and size of extra field data)\r\n*/\r\nlocal int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s, uInt *piSizeVar,\r\n                                                    uLong *poffset_local_extrafield,\r\n                                                    uInt *psize_local_extrafield)\r\n{\r\n    uLong uMagic,uData,uFlags;\r\n    uLong size_filename;\r\n    uLong size_extra_field;\r\n    int err=UNZ_OK;\r\n\r\n    *piSizeVar = 0;\r\n    *poffset_local_extrafield = 0;\r\n    *psize_local_extrafield = 0;\r\n\r\n    if (fseek(s->file,s->cur_file_info_internal.offset_curfile +\r\n                                s->byte_before_the_zipfile,SEEK_SET)!=0)\r\n        return UNZ_ERRNO;\r\n\r\n\r\n    if (err==UNZ_OK)\r\n                {\r\n                if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)\r\n            err=UNZ_ERRNO;\r\n        else if (uMagic!=0x04034b50)\r\n            err=UNZ_BADZIPFILE;\r\n                }\r\n\r\n    if (unzlocal_getShort(s->file,&uData) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n/*\r\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))\r\n        err=UNZ_BADZIPFILE;\r\n*/\r\n    if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getShort(s->file,&uData) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&\r\n                         (s->cur_file_info.compression_method!=Z_DEFLATED))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */\r\n        err=UNZ_ERRNO;\r\n\r\n    if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */\r\n        err=UNZ_ERRNO;\r\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&\r\n                              ((uFlags & 8)==0))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */\r\n        err=UNZ_ERRNO;\r\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&\r\n                              ((uFlags & 8)==0))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */\r\n        err=UNZ_ERRNO;\r\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&\r\n                              ((uFlags & 8)==0))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n\r\n    if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))\r\n        err=UNZ_BADZIPFILE;\r\n\r\n    *piSizeVar += (uInt)size_filename;\r\n\r\n    if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)\r\n        err=UNZ_ERRNO;\r\n    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +\r\n                                    SIZEZIPLOCALHEADER + size_filename;\r\n    *psize_local_extrafield = (uInt)size_extra_field;\r\n\r\n    *piSizeVar += (uInt)size_extra_field;\r\n\r\n    return err;\r\n}\r\n\r\n/*\r\n  Open for reading data the current file in the zipfile.\r\n  If there is no error and the file is opened, the return value is UNZ_OK.\r\n*/\r\nextern int ZEXPORT unzOpenCurrentFile (unzFile file)\r\n{\r\n    int err=UNZ_OK;\r\n    int Store;\r\n    uInt iSizeVar;\r\n    unz_s* s;\r\n    file_in_zip_read_info_s* pfile_in_zip_read_info;\r\n    uLong offset_local_extrafield;  /* offset of the local extra field */\r\n    uInt  size_local_extrafield;    /* size of the local extra field */\r\n\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    if (!s->current_file_ok)\r\n        return UNZ_PARAMERROR;\r\n\r\n    if (s->pfile_in_zip_read != NULL)\r\n        unzCloseCurrentFile(file);\r\n\r\n    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,\r\n                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)\r\n        return UNZ_BADZIPFILE;\r\n\r\n    pfile_in_zip_read_info = (file_in_zip_read_info_s*)\r\n                                        ALLOC(sizeof(file_in_zip_read_info_s));\r\n    if (pfile_in_zip_read_info==NULL)\r\n        return UNZ_INTERNALERROR;\r\n\r\n    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);\r\n    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;\r\n    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;\r\n    pfile_in_zip_read_info->pos_local_extrafield=0;\r\n\r\n    if (pfile_in_zip_read_info->read_buffer==NULL)\r\n    {\r\n        TRYFREE(pfile_in_zip_read_info);\r\n        return UNZ_INTERNALERROR;\r\n    }\r\n\r\n    pfile_in_zip_read_info->stream_initialised=0;\r\n\r\n    if ((s->cur_file_info.compression_method!=0) &&\r\n        (s->cur_file_info.compression_method!=Z_DEFLATED))\r\n        err=UNZ_BADZIPFILE;\r\n    Store = s->cur_file_info.compression_method==0;\r\n\r\n    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;\r\n    pfile_in_zip_read_info->crc32=0;\r\n    pfile_in_zip_read_info->compression_method =\r\n            s->cur_file_info.compression_method;\r\n    pfile_in_zip_read_info->file=s->file;\r\n    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;\r\n\r\n    pfile_in_zip_read_info->stream.total_out = 0;\r\n\r\n    if (!Store)\r\n    {\r\n      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;\r\n      pfile_in_zip_read_info->stream.zfree = (free_func)0;\r\n      pfile_in_zip_read_info->stream.opaque = (voidpf)0;\r\n\r\n      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);\r\n      if (err == Z_OK)\r\n        pfile_in_zip_read_info->stream_initialised=1;\r\n        /* windowBits is passed < 0 to tell that there is no zlib header.\r\n         * Note that in this case inflate *requires* an extra \"dummy\" byte\r\n         * after the compressed stream in order to complete decompression and\r\n         * return Z_STREAM_END.\r\n         * In unzip, i don't wait absolutely Z_STREAM_END because I known the\r\n         * size of both compressed and uncompressed data\r\n         */\r\n    }\r\n    pfile_in_zip_read_info->rest_read_compressed =\r\n            s->cur_file_info.compressed_size ;\r\n    pfile_in_zip_read_info->rest_read_uncompressed =\r\n            s->cur_file_info.uncompressed_size ;\r\n\r\n\r\n    pfile_in_zip_read_info->pos_in_zipfile =\r\n            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +\r\n              iSizeVar;\r\n\r\n    pfile_in_zip_read_info->stream.avail_in = (uInt)0;\r\n\r\n\r\n    s->pfile_in_zip_read = pfile_in_zip_read_info;\r\n    return UNZ_OK;\r\n}\r\n\r\n\r\n/*\r\n  Read bytes from the current file.\r\n  buf contain buffer where data must be copied\r\n  len the size of buf.\r\n\r\n  return the number of byte copied if somes bytes are copied\r\n  return 0 if the end of file was reached\r\n  return <0 with error code if there is an error\r\n    (UNZ_ERRNO for IO error, or zLib error for uncompress error)\r\n*/\r\nextern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)\r\n{\r\n    int err=UNZ_OK;\r\n    uInt iRead = 0;\r\n    unz_s* s;\r\n    file_in_zip_read_info_s* pfile_in_zip_read_info;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\r\n\r\n    if (pfile_in_zip_read_info==NULL)\r\n        return UNZ_PARAMERROR;\r\n\r\n\r\n    if ((pfile_in_zip_read_info->read_buffer == NULL))\r\n        return UNZ_END_OF_LIST_OF_FILE;\r\n    if (len==0)\r\n        return 0;\r\n\r\n    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;\r\n\r\n    pfile_in_zip_read_info->stream.avail_out = (uInt)len;\r\n\r\n    if (len>pfile_in_zip_read_info->rest_read_uncompressed)\r\n        pfile_in_zip_read_info->stream.avail_out =\r\n          (uInt)pfile_in_zip_read_info->rest_read_uncompressed;\r\n\r\n    while (pfile_in_zip_read_info->stream.avail_out>0)\r\n    {\r\n        if ((pfile_in_zip_read_info->stream.avail_in==0) &&\r\n            (pfile_in_zip_read_info->rest_read_compressed>0))\r\n        {\r\n            uInt uReadThis = UNZ_BUFSIZE;\r\n            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)\r\n                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;\r\n            if (uReadThis == 0)\r\n                return UNZ_EOF;\r\n            if (fseek(pfile_in_zip_read_info->file,\r\n                      pfile_in_zip_read_info->pos_in_zipfile +\r\n                         pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)\r\n                return UNZ_ERRNO;\r\n            if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,\r\n                         pfile_in_zip_read_info->file)!=1)\r\n                return UNZ_ERRNO;\r\n            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;\r\n\r\n            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;\r\n\r\n            pfile_in_zip_read_info->stream.next_in =\r\n                (Bytef*)pfile_in_zip_read_info->read_buffer;\r\n            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;\r\n        }\r\n\r\n        if (pfile_in_zip_read_info->compression_method==0)\r\n        {\r\n            uInt uDoCopy,i ;\r\n            if (pfile_in_zip_read_info->stream.avail_out <\r\n                            pfile_in_zip_read_info->stream.avail_in)\r\n                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;\r\n            else\r\n                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;\r\n\r\n            for (i=0;i<uDoCopy;i++)\r\n                *(pfile_in_zip_read_info->stream.next_out+i) =\r\n                        *(pfile_in_zip_read_info->stream.next_in+i);\r\n\r\n            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,\r\n                                pfile_in_zip_read_info->stream.next_out,\r\n                                uDoCopy);\r\n            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;\r\n            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;\r\n            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;\r\n            pfile_in_zip_read_info->stream.next_out += uDoCopy;\r\n            pfile_in_zip_read_info->stream.next_in += uDoCopy;\r\n            pfile_in_zip_read_info->stream.total_out += uDoCopy;\r\n            iRead += uDoCopy;\r\n        }\r\n        else\r\n        {\r\n            uLong uTotalOutBefore,uTotalOutAfter;\r\n            const Bytef *bufBefore;\r\n            uLong uOutThis;\r\n            int flush=Z_SYNC_FLUSH;\r\n\r\n            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;\r\n            bufBefore = pfile_in_zip_read_info->stream.next_out;\r\n\r\n            /*\r\n            if ((pfile_in_zip_read_info->rest_read_uncompressed ==\r\n                     pfile_in_zip_read_info->stream.avail_out) &&\r\n                (pfile_in_zip_read_info->rest_read_compressed == 0))\r\n                flush = Z_FINISH;\r\n            */\r\n            err=inflate(&pfile_in_zip_read_info->stream,flush);\r\n\r\n            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;\r\n            uOutThis = uTotalOutAfter-uTotalOutBefore;\r\n\r\n            pfile_in_zip_read_info->crc32 =\r\n                crc32(pfile_in_zip_read_info->crc32,bufBefore,\r\n                        (uInt)(uOutThis));\r\n\r\n            pfile_in_zip_read_info->rest_read_uncompressed -=\r\n                uOutThis;\r\n\r\n            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);\r\n\r\n            if (err==Z_STREAM_END)\r\n                return (iRead==0) ? UNZ_EOF : iRead;\r\n            if (err!=Z_OK)\r\n                break;\r\n        }\r\n    }\r\n\r\n    if (err==Z_OK)\r\n        return iRead;\r\n    return err;\r\n}\r\n\r\n\r\n/*\r\n  Give the current position in uncompressed data\r\n*/\r\nextern z_off_t ZEXPORT unztell (unzFile file)\r\n{\r\n    unz_s* s;\r\n    file_in_zip_read_info_s* pfile_in_zip_read_info;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\r\n\r\n    if (pfile_in_zip_read_info==NULL)\r\n        return UNZ_PARAMERROR;\r\n\r\n    return (z_off_t)pfile_in_zip_read_info->stream.total_out;\r\n}\r\n\r\n\r\n/*\r\n  return 1 if the end of file was reached, 0 elsewhere\r\n*/\r\nextern int ZEXPORT unzeof (unzFile file)\r\n{\r\n    unz_s* s;\r\n    file_in_zip_read_info_s* pfile_in_zip_read_info;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\r\n\r\n    if (pfile_in_zip_read_info==NULL)\r\n        return UNZ_PARAMERROR;\r\n\r\n    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)\r\n        return 1;\r\n    else\r\n        return 0;\r\n}\r\n\r\n\r\n\r\n/*\r\n  Read extra field from the current file (opened by unzOpenCurrentFile)\r\n  This is the local-header version of the extra field (sometimes, there is\r\n    more info in the local-header version than in the central-header)\r\n\r\n  if buf==NULL, it return the size of the local extra field that can be read\r\n\r\n  if buf!=NULL, len is the size of the buffer, the extra header is copied in\r\n    buf.\r\n  the return value is the number of bytes copied in buf, or (if <0)\r\n    the error code\r\n*/\r\nextern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf,unsigned len)\r\n{\r\n    unz_s* s;\r\n    file_in_zip_read_info_s* pfile_in_zip_read_info;\r\n    uInt read_now;\r\n    uLong size_to_read;\r\n\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\r\n\r\n    if (pfile_in_zip_read_info==NULL)\r\n        return UNZ_PARAMERROR;\r\n\r\n    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -\r\n                pfile_in_zip_read_info->pos_local_extrafield);\r\n\r\n    if (buf==NULL)\r\n        return (int)size_to_read;\r\n\r\n    if (len>size_to_read)\r\n        read_now = (uInt)size_to_read;\r\n    else\r\n        read_now = (uInt)len ;\r\n\r\n    if (read_now==0)\r\n        return 0;\r\n\r\n    if (fseek(pfile_in_zip_read_info->file,\r\n              pfile_in_zip_read_info->offset_local_extrafield +\r\n              pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)\r\n        return UNZ_ERRNO;\r\n\r\n    if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)\r\n        return UNZ_ERRNO;\r\n\r\n    return (int)read_now;\r\n}\r\n\r\n/*\r\n  Close the file in zip opened with unzipOpenCurrentFile\r\n  Return UNZ_CRCERROR if all the file was read but the CRC is not good\r\n*/\r\nextern int ZEXPORT unzCloseCurrentFile (unzFile file)\r\n{\r\n    int err=UNZ_OK;\r\n\r\n    unz_s* s;\r\n    file_in_zip_read_info_s* pfile_in_zip_read_info;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\r\n\r\n    if (pfile_in_zip_read_info==NULL)\r\n        return UNZ_PARAMERROR;\r\n\r\n\r\n    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)\r\n    {\r\n        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)\r\n            err=UNZ_CRCERROR;\r\n    }\r\n\r\n\r\n    TRYFREE(pfile_in_zip_read_info->read_buffer);\r\n    pfile_in_zip_read_info->read_buffer = NULL;\r\n    if (pfile_in_zip_read_info->stream_initialised)\r\n        inflateEnd(&pfile_in_zip_read_info->stream);\r\n\r\n    pfile_in_zip_read_info->stream_initialised = 0;\r\n    TRYFREE(pfile_in_zip_read_info);\r\n\r\n    s->pfile_in_zip_read=NULL;\r\n\r\n    return err;\r\n}\r\n\r\n\r\n/*\r\n  Get the global comment string of the ZipFile, in the szComment buffer.\r\n  uSizeBuf is the size of the szComment buffer.\r\n  return the number of byte copied or an error code <0\r\n*/\r\nextern int ZEXPORT unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)\r\n{\r\n/*        int err=UNZ_OK; */\r\n    unz_s* s;\r\n    uLong uReadThis ;\r\n    if (file==NULL)\r\n        return UNZ_PARAMERROR;\r\n    s=(unz_s*)file;\r\n\r\n    uReadThis = uSizeBuf;\r\n    if (uReadThis>s->gi.size_comment)\r\n        uReadThis = s->gi.size_comment;\r\n\r\n    if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)\r\n        return UNZ_ERRNO;\r\n\r\n    if (uReadThis>0)\r\n    {\r\n      *szComment='\\0';\r\n      if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)\r\n        return UNZ_ERRNO;\r\n    }\r\n\r\n    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))\r\n        *(szComment+s->gi.size_comment)='\\0';\r\n    return (int)uReadThis;\r\n}\r\n"
  },
  {
    "path": "meka/srcs/unzip.h",
    "content": "/* unzip.h -- IO for uncompress .zip files using zlib\n   Version 0.15 beta, Mar 19th, 1998,\n\n   Copyright (C) 1998 Gilles Vollant\n\n   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g\n     WinZip, InfoZip tools and compatible.\n   Encryption and multi volume ZipFile (span) are not supported.\n   Old compressions used by old PKZip 1.x are not supported\n\n   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE\n   CAN CHANGE IN FUTURE VERSION !!\n   I WAIT FEEDBACK at mail info@winimage.com\n   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution\n\n   Condition of use and distribution are the same than zlib :\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n*/\n\n/* for more info about .ZIP format, see\n      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip\n   PkWare has also a specification at :\n      ftp://ftp.pkware.com/probdesc.zip */\n\n#ifndef _unz_H\n#define _unz_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef _ZLIB_H\n#include \"zlib.h\"\n#endif\n\n// Newer versions of ZLIB uses _Z_OF\n#ifndef OF\n#define OF _Z_OF\n#endif\n\n#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)\n/* like the STRICT of WIN32, we define a pointer that cannot be converted\n    from (void*) without cast */\ntypedef struct TagunzFile__ { int unused; } unzFile__;\ntypedef unzFile__ *unzFile;\n#else\ntypedef voidp unzFile;\n#endif\n\n\n#define UNZ_OK                                  (0)\n#define UNZ_END_OF_LIST_OF_FILE (-100)\n#define UNZ_ERRNO               (Z_ERRNO)\n#define UNZ_EOF                 (0)\n#define UNZ_PARAMERROR                  (-102)\n#define UNZ_BADZIPFILE                  (-103)\n#define UNZ_INTERNALERROR               (-104)\n#define UNZ_CRCERROR                    (-105)\n\n/* tm_unz contain date/time info */\ntypedef struct tm_unz_s\n{\n  uInt tm_sec;            /* seconds after the minute - [0,59] */\n  uInt tm_min;            /* minutes after the hour - [0,59] */\n  uInt tm_hour;           /* hours since midnight - [0,23] */\n  uInt tm_mday;           /* day of the month - [1,31] */\n  uInt tm_mon;            /* months since January - [0,11] */\n  uInt tm_year;           /* years - [1980..2044] */\n} tm_unz;\n\n/* unz_global_info structure contain global data about the ZIPfile\n   These data comes from the end of central dir */\ntypedef struct unz_global_info_s\n{\n  uLong number_entry;         /* total number of entries in\n               the central dir on this disk */\n  uLong size_comment;         /* size of the global comment of the zipfile */\n} unz_global_info;\n\n\n/* unz_file_info contain information about a file in the zipfile */\ntypedef struct unz_file_info_s\n{\n    uLong version;              /* version made by                 2 bytes */\n    uLong version_needed;       /* version needed to extract       2 bytes */\n    uLong flag;                 /* general purpose bit flag        2 bytes */\n    uLong compression_method;   /* compression method              2 bytes */\n    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */\n    uLong crc;                  /* crc-32                          4 bytes */\n    uLong compressed_size;      /* compressed size                 4 bytes */\n    uLong uncompressed_size;    /* uncompressed size               4 bytes */\n    uLong size_filename;        /* filename length                 2 bytes */\n    uLong size_file_extra;      /* extra field length              2 bytes */\n    uLong size_file_comment;    /* file comment length             2 bytes */\n\n    uLong disk_num_start;       /* disk number start               2 bytes */\n    uLong internal_fa;          /* internal file attributes        2 bytes */\n    uLong external_fa;          /* external file attributes        4 bytes */\n\n    tm_unz tmu_date;\n} unz_file_info;\n\nextern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,\n                         const char* fileName2,\n                         int iCaseSensitivity));\n/*\n   Compare two filename (fileName1,fileName2).\n   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\n   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\n                or strcasecmp)\n   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\n  (like 1 on Unix, 2 on Windows)\n*/\n\n\nextern unzFile ZEXPORT unzOpen OF((const char *path));\n/*\n  Open a Zip file. path contain the full pathname (by example,\n     on a Windows NT computer \"c:\\\\zlib\\\\zlib111.zip\" or on an Unix computer\n   \"zlib/zlib111.zip\".\n   If the zipfile cannot be opened (file don't exist or in not valid), the\n     return value is NULL.\n     Else, the return value is a unzFile Handle, usable with other function\n     of this unzip package.\n*/\n\nextern int ZEXPORT unzClose OF((unzFile file));\n/*\n  Close a ZipFile opened with unzipOpen.\n  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),\n    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\n  return UNZ_OK if there is no problem. */\n\nextern int ZEXPORT unzGetGlobalInfo OF((unzFile file,\n          unz_global_info *pglobal_info));\n/*\n  Write info about the ZipFile in the *pglobal_info structure.\n  No preparation of the structure is needed\n  return UNZ_OK if there is no problem. */\n\n\nextern int ZEXPORT unzGetGlobalComment OF((unzFile file,\n                       char *szComment,\n             uLong uSizeBuf));\n/*\n  Get the global comment string of the ZipFile, in the szComment buffer.\n  uSizeBuf is the size of the szComment buffer.\n  return the number of byte copied or an error code <0\n*/\n\n\n/***************************************************************************/\n/* Unzip package allow you browse the directory of the zipfile */\n\nextern int ZEXPORT unzGoToFirstFile OF((unzFile file));\n/*\n  Set the current file of the zipfile to the first file.\n  return UNZ_OK if there is no problem\n*/\n\nextern int ZEXPORT unzGoToNextFile OF((unzFile file));\n/*\n  Set the current file of the zipfile to the next file.\n  return UNZ_OK if there is no problem\n  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\n*/\n\nextern int ZEXPORT unzLocateFile OF((unzFile file,\n             const char *szFileName,\n             int iCaseSensitivity));\n/*\n  Try locate the file szFileName in the zipfile.\n  For the iCaseSensitivity signification, see unzStringFileNameCompare\n\n  return value :\n  UNZ_OK if the file is found. It becomes the current file.\n  UNZ_END_OF_LIST_OF_FILE if the file is not found\n*/\n\n\nextern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,\n               unz_file_info *pfile_info,\n               char *szFileName,\n               uLong fileNameBufferSize,\n               void *extraField,\n               uLong extraFieldBufferSize,\n               char *szComment,\n               uLong commentBufferSize));\n/*\n  Get Info about the current file\n  if pfile_info!=NULL, the *pfile_info structure will contain somes info about\n      the current file\n  if szFileName!=NULL, the filemane string will be copied in szFileName\n      (fileNameBufferSize is the size of the buffer)\n  if extraField!=NULL, the extra field information will be copied in extraField\n      (extraFieldBufferSize is the size of the buffer).\n      This is the Central-header version of the extra field\n  if szComment!=NULL, the comment string of the file will be copied in szComment\n      (commentBufferSize is the size of the buffer)\n*/\n\n/***************************************************************************/\n/* for reading the content of the current zipfile, you can open it, read data\n   from it, and close it (you can close it before reading all the file)\n   */\n\nextern int ZEXPORT unzOpenCurrentFile OF((unzFile file));\n/*\n  Open for reading data the current file in the zipfile.\n  If there is no error, the return value is UNZ_OK.\n*/\n\nextern int ZEXPORT unzCloseCurrentFile OF((unzFile file));\n/*\n  Close the file in zip opened with unzOpenCurrentFile\n  Return UNZ_CRCERROR if all the file was read but the CRC is not good\n*/\n\n\nextern int ZEXPORT unzReadCurrentFile OF((unzFile file,\n            voidp buf,\n            unsigned len));\n/*\n  Read bytes from the current file (opened by unzOpenCurrentFile)\n  buf contain buffer where data must be copied\n  len the size of buf.\n\n  return the number of byte copied if somes bytes are copied\n  return 0 if the end of file was reached\n  return <0 with error code if there is an error\n    (UNZ_ERRNO for IO error, or zLib error for uncompress error)\n*/\n\nextern z_off_t ZEXPORT unztell OF((unzFile file));\n/*\n  Give the current position in uncompressed data\n*/\n\nextern int ZEXPORT unzeof OF((unzFile file));\n/*\n  return 1 if the end of file was reached, 0 elsewhere\n*/\n\nextern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,\n                       voidp buf,\n                       unsigned len));\n/*\n  Read extra field from the current file (opened by unzOpenCurrentFile)\n  This is the local-header version of the extra field (sometimes, there is\n    more info in the local-header version than in the central-header)\n\n  if buf==NULL, it return the size of the local extra field\n\n  if buf!=NULL, len is the size of the buffer, the extra header is copied in\n  buf.\n  the return value is the number of bytes copied in buf, or (if <0)\n  the error code\n*/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _unz_H */\n\n"
  },
  {
    "path": "meka/srcs/vdp.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - vdp.c\r\n// TMS9918/28 Accesses and Registers Handling - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"vdp.h\"\r\n#include \"app_game.h\"\r\n#include \"debugger.h\"\r\n#include \"g_tools.h\"\r\n#include \"lightgun.h\"\r\n#include \"palette.h\"\r\n#include \"video.h\"\r\n#include \"video_m2.h\"\r\n\r\n//#define DEBUG_VDP\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\n// VDP Models Differences Table -----------------------------------------------\r\n// MODELS                               315-5124  315-5226  315-5378  315-5313\r\n// Machines                             M3,SMS    SMS/SMS2  GG        MD\r\n//-----------------------------------------------------------------------------\r\n// TMS9918 video modes                  Yes       Yes       Yes       No\r\n// 224-Lines Mode                       ??        ??        ??        ??\r\n// 240-Lines Mode                       ??        ??        ??        ??\r\n// Bits 0-4 of Status Register          ??        Garbage   ??        MD data\r\n// Bit 0 of Register 2 apply a mask     Yes       ??        No        No\r\n// Bit 7 of Register 1 (VRAM Size)      ??        ??        ??        ??\r\n// Zoomed Sprites Bug (+4 per Lines)    Yes       No        No        ??\r\n// Writing data port update read buf.   ??        Yes       ??        Yes\r\n// Palette write if only bit 1 is set   ??        ??        ??        Yes\r\n// First address byte is latched        ??        No        ??        Yes\r\n// Writing to Register update address   ??        ??        ??        ??\r\n//-----------------------------------------------------------------------------\r\n// Note: not everything is implemented as on this table.\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic u8   VDP_Mask [10] [2] =\r\n{\r\n  /* 0 */ { 0x00, /*0x3F*/ 0x07 },\r\n  /* 1 */ { 0xFF, /*0x3F*/ 0x07 },\r\n  /* 2 */ { 0x80, /*0x3C*/ 0x04 },\r\n  /* 3 */ { 0x00, /*0x07*/ 0x3F },\r\n  /* . */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nint     VDP_Model_FindByName(const char *name)\r\n{\r\n    if (!strcmp(name, \"315-5124\"))\r\n        return VDP_MODEL_315_5124;\r\n    else if (!strcmp(name, \"315-5246\")) //|| !strcmp(name, \"315-5226\")) // Prior to 2024 we had this listed (incorrectly) as 315-5226, however it was never used by meka.nam\r\n        return VDP_MODEL_315_5246;\r\n    else if (!strcmp(name, \"315-5378\"))\r\n        return VDP_MODEL_315_5378;\r\n    else if (!strcmp(name, \"315-5313\"))\r\n        return VDP_MODEL_315_5313;\r\n    return -1;\r\n}\r\n\r\nvoid    VDP_VideoMode_Change()\r\n{\r\n    int   i;\r\n\r\n    if (tsms.VDP_Video_Change & VDP_VIDEO_CHANGE_MODE)\r\n    {\r\n        //Msg(MSGT_DEBUG, \"Line %d. Change video mode %d -> %d (bits = %d)\",\r\n        //     tsms.VDP_Line, tsms.VDP_VideoMode, tsms.VDP_New_VideoMode, ((sms.VDP[0] & 0x06) >> 1) | ((sms.VDP[1] & 0x18) >> 1));\r\n        tsms.VDP_VideoMode = tsms.VDP_New_VideoMode;\r\n        if (tsms.VDP_VideoMode <= 3)\r\n        {\r\n            if (g_driver->id == DRV_SMS)\r\n                drv_set (DRV_SG1000);\r\n        }\r\n        else\r\n        {\r\n            drv_set (g_machine.driver_id); // Revert back to original driver\r\n        }\r\n        VDP_UpdateLineLimits();\r\n        Machine_Set_Handler_Loop();\r\n        Palette_Emulation_Reload();\r\n        for (i = 0; i < 16; i ++)\r\n            Tms_VDP_Out (i, sms.VDP [i]);\r\n    }\r\n\r\n    if (tsms.VDP_Video_Change & VDP_VIDEO_CHANGE_SIZE)\r\n    {\r\n        if (g_driver->id == DRV_SMS)\r\n        {\r\n            g_driver->y_res = ((Wide_Screen_28) ? 224 : 192);\r\n            gamebox_resize_all();\r\n            VDP_UpdateLineLimits();\r\n            Video_GameMode_UpdateBounds();\r\n            if (g_env.state == MEKA_STATE_GAME)\r\n            {\r\n                Video_ClearScreenBackBuffer();\r\n            }\r\n        }\r\n        else\r\n        {\r\n            VDP_UpdateLineLimits();\r\n        }\r\n    }\r\n    tsms.VDP_Video_Change = 0x00;\r\n}\r\n\r\n// See table in Charles' VDP documentation.\r\nvoid    VDP_VideoMode_Update()\r\n{\r\n    // Transform into M1/M2/M3/M4 as in Charles' VDP documentation (this is confusing).\r\n    //int mode;\r\n    //mode  = (sms.VDP[1] & 0x10) >> 4);  // M1 = Reg 1, Bit 4\r\n    //mode |= (sms.VDP[0] & 0x02);        // M2 = Reg 0, Bit 1\r\n    //mode |= (sms.VDP[1] & 0x08) >> 1);  // M3 = Reg 1, Bit 3\r\n    //mode |= (sms.VDP[0] & 0x04) << 1);  // M4 = Reg 0, Bit 2\r\n\r\n    switch (((sms.VDP[0] & 0x06) >> 1) | ((sms.VDP[1] & 0x18) >> 1))\r\n    {\r\n        // Bits 0, 1 are bits 1, 2 in VDP Register 0\r\n        // Bits 3, 4 are bits 3, 4 in VDP Register 1\r\n    case 0x08: /* 10.00 */ tsms.VDP_New_VideoMode = 0; break;\r\n    case 0x00: /* 00.00 */ tsms.VDP_New_VideoMode = 1; break;\r\n    case 0x01: /* 00.01 */ tsms.VDP_New_VideoMode = 2; break;\r\n    case 0x04: /* 01.00 */ tsms.VDP_New_VideoMode = 3; break;\r\n    case 0x02: /* 00.10 */ tsms.VDP_New_VideoMode = 4; break;\r\n    case 0x03: /* 00.11 */ tsms.VDP_New_VideoMode = 5; break;\r\n    case 0x0A: /* 10.10 */ tsms.VDP_New_VideoMode = 9; break; // ?\r\n        // default: Msg(MSGT_DEBUG, \"Error #42 - Unknown video mode %d - Please contact me\", ((sms.VDP[0] & 0x06) >> 1) | ((sms.VDP[1] & 0x18) >> 1));\r\n    }\r\n    if (tsms.VDP_VideoMode != tsms.VDP_New_VideoMode)\r\n    {\r\n        tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_MODE;\r\n        // Msg(MSGT_DEBUG, \"Change video mode, %d -> %d\", tsms.VDP_VideoMode, tsms.VDP_New_VideoMode);\r\n    }\r\n}\r\n\r\nvoid    VDP_UpdateLineLimits()\r\n{\r\n    if (g_driver->id == DRV_GG && Wide_Screen_28)\r\n        g_driver->y_show_start = g_driver->y_start + 16;\r\n    else\r\n        g_driver->y_show_start = g_driver->y_start;\r\n    g_driver->y_show_end = g_driver->y_show_start + g_driver->y_res - 1;\r\n    if (Wide_Screen_28)\r\n        g_driver->y_int = 224;\r\n    else\r\n        g_driver->y_int = 192;\r\n}\r\n\r\n// WRITE A VALUE TO A VDP REGISTER --------------------------------------------\r\nvoid    Tms_VDP_Out (int vdp_register, int value)\r\n{\r\n  #ifdef DEBUG_VDP\r\n    Msg(MSGT_DEBUG, \"At PC=%04X: VDP Reg[%d] = %02X\", CPU_GetPC, vdp_register, value);\r\n  #endif\r\n\r\n  switch (vdp_register)\r\n    {\r\n     // VDP Configuration 0 ---------------------------------------------------\r\n     case 0: /*\r\n             if ((Value & 0x10) != HBlank_ON)\r\n                {\r\n                Msg(MSGT_DEBUG, \"At PC=%04X, Line=%d, HBlank %s, IRequest = %02X\", CPU_GetPC, tsms.VDP_Line, (Value & 0x10) ? \"Enable\" : \"Disable\", sms.R.IRequest);\r\n                }\r\n             */\r\n\r\n             if ((sms.Pending_HBlank) && ((HBlank_ON) != (value & 0x10)))\r\n             {\r\n                if (!(value & 0x10))\r\n                   {\r\n                   // Msg(MSGT_DEBUG, \"At PC=%04X, Line=%d, disabling IE1 unasserted the Z80 IRQ Line\", CPU_GetPC, tsms.VDP_Line);\r\n                   sms.R.IRequest = INT_NONE;\r\n                   }\r\n                else\r\n                   {\r\n                   sms.R.IRequest = INT_IRQ;\r\n                   }\r\n             }\r\n\r\n             sms.VDP [0] = value;\r\n             g_machine.VDP.sprite_shift_x = ((Sprites_Left_8) ? 8 : 0);\r\n             VDP_VideoMode_Update();\r\n             // Msg(MSGT_DEBUG, \"At PC=%04X, line=%d, VDP[0] = %02X\", sms.R.PC.W, tsms.VDP_Line, value);\r\n             return;\r\n\r\n     // VDP Configuration 1 ---------------------------------------------------\r\n     case 1: if ((value & 0x10) != Wide_Screen_28) // Wide just enabled/disabled\r\n                tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_SIZE;\r\n             /* if ((value & 0x40) != Display_ON)\r\n                {\r\n                Msg(MSGT_DEBUG, \"At PC=%04X, Line=%d, Enable/Disable Display %02X\", sms.R.PC.W, tsms.VDP_Line, value);\r\n                sms.R.Trace = TRUE;\r\n                } */\r\n             sms.VDP [1] = value;\r\n             // Sprite_Shift_Y = 0; // ((Wide_Screen_28) ? -16 : 0);\r\n             // Sprite_Shift_Y = ((Wide_Screen_28 && g_driver->id == DRV_GG) ? -16 : 0);\r\n             VDP_VideoMode_Update();\r\n             // Msg(MSGT_DEBUG, \"At PC=%04X, Line=%d, VDP[1] = %02X\", sms.R.PC.W, tsms.VDP_Line, value);\r\n\r\n             // Update tilemap/name table address accordingly\r\n             if (g_driver->vdp == VDP_SMSGG)\r\n             {\r\n                if (Wide_Screen_28)\r\n                    g_machine.VDP.name_table_address  = VRAM + 0x700 + (int)((sms.VDP[2] & 0xC) << 10); // 0x0700 -> 0x3700, 0x1000 increments\r\n                else\r\n                    g_machine.VDP.name_table_address  = VRAM + (int)((sms.VDP[2] & 0xE) << 10); // 0x0000 -> 0x3800, 0x0800 increments\r\n             }\r\n             return;\r\n\r\n     // Background/Foreground map address -------------------------------------\r\n     case 2: switch (g_driver->vdp)\r\n                {\r\n                case VDP_SMSGG:\r\n                     if (Wide_Screen_28)\r\n                         g_machine.VDP.name_table_address  = VRAM + 0x700 + (int)((value & 0xC) << 10); // 0x0700 -> 0x3700, 0x1000 increments\r\n                     else\r\n                         g_machine.VDP.name_table_address  = VRAM + (int)((value & 0xE) << 10); // 0x0000 -> 0x3800, 0x0800 increments\r\n                     break;\r\n                case VDP_TMS9918:\r\n                     g_machine.VDP.name_table_address = VRAM + (int)((value & 0xF) << 10); // 0x0000 -> 0x3C00, 0x0400 increments\r\n                     break;\r\n                }\r\n             break;\r\n\r\n     // TMS9918 register: contain bit 13 of the color table adress ------------\r\n     case 3: g_machine.VDP.sg_color_table_address = VRAM + ((((int)(value & VDP_Mask[tsms.VDP_VideoMode][0]) << 6) + ((int)sms.VDP[10] << 14)) & 0x3FFF);\r\n             break;\r\n\r\n     // TMS9918 register: address of tile data --------------------------------\r\n     // This is either $0000 or $2000 in VRAM\r\n     case 4: g_machine.VDP.sg_pattern_gen_address = VRAM + ((int)(value & VDP_Mask[tsms.VDP_VideoMode][1]) << 11);\r\n             break;\r\n\r\n     // Sprite Attribute Table (SAT) address\r\n     case 5: switch (g_driver->vdp)\r\n                {\r\n                case VDP_SMSGG:\r\n                     g_machine.VDP.sprite_attribute_table = VRAM + (((int)value << 7) & 0x3F00);\r\n                     break;\r\n                case VDP_TMS9918:\r\n                     g_machine.VDP.sprite_attribute_table = VRAM + ((int)(value & 0x7F) << 7);\r\n                     break;\r\n                }\r\n             break;\r\n\r\n     // Sprite tile data address ----------------------------------------------\r\n     case 6:\r\n         {\r\n             switch (g_driver->vdp)\r\n                {\r\n                case VDP_SMSGG:\r\n                    g_machine.VDP.sprite_pattern_gen_index = (value & 4) ? 256 : 0;\r\n                    g_machine.VDP.sprite_pattern_gen_address = VRAM + ((value & 4) ? 0x2000 : 0x0000);\r\n                    break;\r\n                case VDP_TMS9918:\r\n                    g_machine.VDP.sprite_pattern_gen_address = VRAM + ((int)(value & 7) << 11);\r\n                    break;\r\n                }\r\n             break;\r\n         }\r\n\r\n     // Border Color ----------------------------------------------------------\r\n     case 7: if (g_driver->vdp == VDP_TMS9918)\r\n                Palette_Emulation_SetColor(0, TMS9918_Palette[value & 15]);\r\n             break;\r\n\r\n     // Horizontal Scrolling --------------------------------------------------\r\n     case 8: if (CPU_GetICount() >= 8)\r\n                 g_machine.VDP.scroll_x_latched = value;\r\n             // Msg(MSGT_DEBUG, \"%d @ ICount = % 3d, VDP[8] = %d\", tsms.VDP_Line, CPU_GetICount(), value);\r\n             break;\r\n\r\n     // Vertical Scrolling ----------------------------------------------------\r\n     //case 9: Msg(MSGT_DEBUG, \"At PC=%04X, Line=%d: vscroll = %d\", CPU_GetPC(), tsms.VDP_Line, value);\r\n             // if ((Wide_Screen_28) && value > 224)\r\n             //   {\r\n             //   Msg(MSGT_DEBUG, \"Error #9384: Please contact me if you see this message.\");\r\n             //   value = 224;\r\n             //   }\r\n     //        break;\r\n\r\n     // TMS9918 register: contain bit 14-16 of the color table adress ---------\r\n     // Else in video mode 5 contains number of line for H-Interrupt\r\n     case 10: g_machine.VDP.sg_color_table_address = VRAM + ((((int)(sms.VDP[3] & VDP_Mask[tsms.VDP_VideoMode][0]) << 6) + ((int)(value & 0x07) << 14)) & 0x3FFF);\r\n              // Msg(MSGT_DEBUG, \"%d @ VDP[10] = %d\", tsms.VDP_Line, value);\r\n              break;\r\n    }\r\n\r\n    // Finally save to VDP Register state\r\n    sms.VDP[vdp_register] = value;\r\n}\r\n\r\nvoid    Tms_VDP_Palette_Write(int addr, int value)\r\n{\r\n    ALLEGRO_COLOR color;\r\n\r\n    // Write to CRAM (currently named PRAM)\r\n    PRAM [addr] = value;\r\n\r\n    switch (g_driver->id)\r\n    {\r\n    case DRV_GG:\r\n        {\r\n            // Sega Game Gear\r\n            if (addr & 0x01) // Update only on second byte write\r\n            {\r\n                Palette_Compute_RGB_GG(&color, addr & 0xFE);\r\n                Palette_Emulation_SetColor(addr >> 1, color);\r\n            }\r\n            return;\r\n        }\r\n    case DRV_SMS:\r\n        {\r\n            // Sega Master System\r\n            Palette_Compute_RGB_SMS(&color, addr);\r\n            Palette_Emulation_SetColor(addr, color);\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\nvoid    Tms_VDP_Out_Data (int value)\r\n{\r\n    sms.VDP_Access_Mode = VDP_Access_Mode_1;\r\n    if (sms.VDP_Pal == FALSE)\r\n    {\r\n        // VRAM write\r\n        VRAM [sms.VDP_Address] = value;\r\n        sms.VDP_ReadLatch = value;\r\n\r\n        // Debugger hook\r\n        #ifdef MEKA_Z80_DEBUGGER\r\n            if (Debugger.active)\r\n                Debugger_WrVRAM_Hook(sms.VDP_Address, value);\r\n        #endif\r\n\r\n        sms.VDP_Address = (sms.VDP_Address + 1) & 0x3FFF;\r\n\r\n        // Mark corresponding tile as dirty\r\n        tgfx.Tile_Dirty [sms.VDP_Address / 32] |= TILE_DIRTY_DECODE;\r\n        return;\r\n    }\r\n    else\r\n    {\r\n        // Address mask\r\n        const int address_mask = (g_driver->id == DRV_GG) ? 0x3F : 0x1F;\r\n\r\n        // Palette/CRAM write\r\n        Tms_VDP_Palette_Write(sms.VDP_Address & address_mask, value);\r\n        sms.VDP_ReadLatch = value;\r\n\r\n        // Debugger hook\r\n        #ifdef MEKA_Z80_DEBUGGER\r\n            if (Debugger.active)\r\n                Debugger_WrPRAM_Hook(sms.VDP_Address & address_mask, value);\r\n        #endif\r\n\r\n        // Increment VDP address\r\n        sms.VDP_Address++;\r\n    }\r\n}\r\n\r\nvoid    Tms_VDP_Out_Address (int value)\r\n{\r\n    // [DEBUG] Daffy Duck\r\n    //if (CPU_GetPC == 0x7348)\r\n    //{\r\n    //   Msg(MSGT_DEBUG, \"At PC=%04X: VDP Out: %02X\", CPU_GetPC, Value);\r\n    //   if (sms.VDP_Access_Mode != VDP_Access_Mode_1)\r\n    //       if ((Value & 0xC0) == 0x80)\r\n    //          Msg(MSGT_DEBUG, \" -> (line %d) vreg[%d] = %02X \", tsms.VDP_Line, Value & 0x0F, sms.VDP_Access_First);\r\n    //}\r\n\r\n    if (sms.VDP_Access_Mode == VDP_Access_Mode_1)\r\n    {\r\n        #ifdef DEBUG_VDP\r\n            Msg(MSGT_DEBUG, \"At PC=%04X: VDP Address1: %02X\", CPU_GetPC, value);\r\n        #endif\r\n        sms.VDP_Access_First = value;   // Latch\r\n        sms.VDP_Access_Mode  = VDP_Access_Mode_2;\r\n        // Fixes Cosmic Spacehead\r\n        // FIXME: line above is not valid for 315-5124\r\n        // We're keeping it as is now to speed up emulation a bit\r\n        sms.VDP_Address = (sms.VDP_Address & 0xFF00) | value;\r\n        // sms.VDP_Pal = FALSE;\r\n        return;\r\n    }\r\n\r\n    // 00 : ?\r\n    // 10 : VDP_Reg\r\n    // 11 : Palette\r\n    // 01 : Address\r\n    // Msg(MSGT_DEBUG, \"[%04X] VDP Set %02X,%02X\", sms.R.PC.W,sms.VDP_Access_First, Value);\r\n\r\n    #ifdef DEBUG_VDP\r\n        Msg(MSGT_DEBUG, \"At PC=%04X: VDP Address2: %02X\", CPU_GetPC, value);\r\n        // printf (\"At PC=%04X: VDP Address2: %02X\\n\", CPU_GetPC, Value);\r\n    #endif\r\n\r\n    sms.VDP_Access_Mode = VDP_Access_Mode_1;\r\n    if ((value & 0xC0) == 0xC0)\r\n    {\r\n        sms.VDP_Pal = TRUE;\r\n        sms.VDP_Address = (((word)value << 8) | sms.VDP_Access_First) & 0x3FFF;\r\n    }\r\n    else\r\n    {\r\n        if (value & 0x80)\r\n        {\r\n            Tms_VDP_Out (value & 0x0F, sms.VDP_Access_First);\r\n            // FIXME: clear last bit of value before setting address ?\r\n        }\r\n        sms.VDP_Pal = FALSE;\r\n        sms.VDP_Address = (((word)value << 8) | sms.VDP_Access_First) & 0x3FFF;\r\n\r\n        if ((value & 0xC0) == 0)\r\n        { // Read Mode\r\n            sms.VDP_ReadLatch = VRAM [sms.VDP_Address];\r\n            sms.VDP_Address ++;\r\n        }\r\n    }\r\n}\r\n\r\nu8      Tms_VDP_In_Data()\r\n{\r\n    sms.VDP_Access_Mode = VDP_Access_Mode_1;\r\n    // if (sms.VDP_Pal)\r\n    //    {\r\n    //    Msg(MSGT_DEBUG, \"Error #7313 [Read from PRAM] - Please contact me.\");\r\n    //    return (0);\r\n    //    }\r\n    // else\r\n    {\r\n        u8 b = sms.VDP_ReadLatch;\r\n\r\n        // Debugger hook\r\n        #ifdef MEKA_Z80_DEBUGGER\r\n            if (Debugger.active)\r\n                Debugger_RdVRAM_Hook(sms.VDP_Address, b);\r\n        #endif\r\n\r\n        // Read next latch and increment address\r\n        sms.VDP_ReadLatch = VRAM [sms.VDP_Address];\r\n        sms.VDP_Address = (sms.VDP_Address + 1) & 0x3FFF;\r\n\r\n        // Return latch\r\n        return (b);\r\n    }\r\n}\r\n\r\nu8          Tms_VDP_In_Status()\r\n{\r\n    u8      b;\r\n\r\n    b = sms.VDP_Status;\r\n    // Value &= 0xDF; // Disable sprite collisions\r\n    sms.VDP_Status &= 0x1F; // Clear bits 5, 6, 7\r\n    // sms.VDP_Status = 0x1F // FIXME: investigate on this!\r\n    sms.VDP_Access_Mode = VDP_Access_Mode_1;\r\n    sms.Pending_HBlank = FALSE;\r\n    sms.Pending_NMI = FALSE;\r\n    #ifdef MARAT_Z80\r\n        sms.R.IRequest = INT_NONE;\r\n    #elif MAME_Z80\r\n        z80_set_irq_line (0, CLEAR_LINE);\r\n    #endif\r\n    #ifdef DEBUG_VDP\r\n        Msg(MSGT_DEBUG, \"At PC=%04X: VDP Status Read, returning %02X\", CPU_GetPC, b | 0x1F);\r\n    #endif\r\n    return (b | 0x1F);\r\n    //return (b & 0xE0);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/vdp.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - vdp.h\r\n// TMS9918/28 Accesses and Registers Handling - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n// VDP Models (for accuracy, MEKA will head towards emulation of the\r\n// specificities between the different VDP models)\r\n// Values below are flags for the purpose of testing VDP for a certain\r\n// feature more easily (like if (VDP_Model & (VDP_MODEL.. | VDP_MODEL..)))\r\n#define VDP_MODEL_315_5124      (0x01)      // Mark III, Master System\r\n#define VDP_MODEL_315_5246      (0x02)      // Later Master System, Master System II\r\n#define VDP_MODEL_315_5378      (0x04)      // Game Gear\r\n#define VDP_MODEL_315_5313      (0x08)      // Mega Drive\r\n\r\n// VDP Video Change Flags\r\n#define VDP_VIDEO_CHANGE_MODE   (0x01)\r\n#define VDP_VIDEO_CHANGE_SIZE   (0x02)\r\n#define VDP_VIDEO_CHANGE_ALL    (VDP_VIDEO_CHANGE_MODE | VDP_VIDEO_CHANGE_SIZE)\r\n\r\n// FIXME: Latch. Remove/rename those definitions.\r\n#define VDP_Access_Mode_1       (0)\r\n#define VDP_Access_Mode_2       (1)\r\n\r\n//-----------------------------------------------------------------------------\r\n// VDP Registers Definitions\r\n//-----------------------------------------------------------------------------\r\n// FIXME: Rename below name/macro, use per-bit definitions/mask matching\r\n// naming in known/official documentations\r\n//-----------------------------------------------------------------------------\r\n// Unknown - 0          (sms.VDP[0] & 0x01) // \"External Video Input\"\r\n// Unknown - 1          (sms.VDP[0] & 0x02) // Mode bit 0\r\n// Unknown - 1          (sms.VDP[0] & 0x04) // Mode bit 1\r\n#define Sprites_Left_8  (sms.VDP[0] & 0x08)\r\n#define HBlank_ON       (sms.VDP[0] & 0x10)\r\n#define Mask_Left_8     (sms.VDP[0] & 0x20)\r\n#define Top_No_Scroll   (sms.VDP[0] & 0x40)\r\n#define Right_No_Scroll (sms.VDP[0] & 0x80)\r\n#define Sprites_Double  (sms.VDP[1] & 0x01)\r\n#define Sprites_8x16    (sms.VDP[1] & 0x02)\r\n#define Sprites_16x16   (sms.VDP[1] & 0x02)\r\n#define Sprites_32x32   (sms.VDP[1] & 0x02)\r\n// Unknown - 0          (sms.VDP[1] & 0x04)\r\n// Unknown - 0          (sms.VDP[1] & 0x08) // Mode bit 2\r\n#define Wide_Screen_28  (sms.VDP[1] & 0x10) // Also Mode bit 3\r\n#define VBlank_ON       (sms.VDP[1] & 0x20)\r\n#define Display_ON      (sms.VDP[1] & 0x40)\r\n// Unknown - 1          (sms.VDP[1] & 0x80) // \"VRAM 16 kbyte\"\r\n//-----------------------------------------------------------------------------\r\n#define VDP_STATUS_SpriteCollision  (0x20)\r\n#define VDP_STATUS_9thSprite        (0x40)\r\n#define VDP_STATUS_VBlank           (0x80)\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nint     VDP_Model_FindByName    (const char *name);\r\n\r\nvoid    VDP_VideoMode_Change    ();\r\nvoid    VDP_VideoMode_Update    ();\r\nvoid    VDP_UpdateLineLimits    ();\r\n\r\nvoid    Tms_VDP_Out             (int vdp_register, int value);\r\nvoid    Tms_VDP_Out_Data        (int value);\r\nvoid    Tms_VDP_Out_Address     (int value);\r\nu8      Tms_VDP_In_Status       ();\r\nu8      Tms_VDP_In_Data         ();\r\nvoid    Tms_VDP_Palette_Write   (int addr, int value);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/video.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - video.c\r\n// Video / Miscellaneous - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"blit.h\"\r\n#include \"blitintf.h\"\r\n#include \"capture.h\"\r\n#include \"debugger.h\"\r\n#include \"fskipper.h\"\r\n#include \"glasses.h\"\r\n#include \"inputs_i.h\"\r\n#include \"inputs_t.h\"\r\n#include \"palette.h\"\r\n#include \"skin_bg.h\"\r\n#include \"skin_fx.h\"\r\n#include \"vdp.h\"\r\n#include \"video.h\"\r\n#include \"vmachine.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_video g_video;\r\n\r\nt_video_driver  g_video_drivers[] =\r\n{\r\n#ifdef ARCH_WIN32\r\n    { \"directx\",    \"DirectX\",      0,                  },  // Allegro for Win32 wants a zero here because it is \"default\".\r\n#endif\r\n    { \"opengl\",     \"OpenGL\",       ALLEGRO_OPENGL,     },\r\n    { \"opengl30\",   \"OpenGL 3.0\",   ALLEGRO_OPENGL_3_0, },\r\n    { NULL, }\r\n};\r\n\r\nt_video_driver* g_video_driver_default = &g_video_drivers[0];\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Video_Init()\r\n{\r\n    //Video_CreateVideoBuffers();\r\n    Video_EnumerateDisplayModes();\r\n\r\n    // Clear variables\r\n    g_video.res_x                       = 0;\r\n    g_video.res_y                       = 0;\r\n    g_video.clear_requests              = 0;\r\n    g_video.game_area_x1                = 0;\r\n    g_video.game_area_x2                = 0;\r\n    g_video.game_area_y1                = 0;\r\n    g_video.game_area_y2                = 0;\r\n    g_video.driver                      = 1;\r\n    g_video.refresh_rate_requested      = 0;\r\n    g_video.display_mode_current_index  = 0;\r\n    fs_out                              = NULL;\r\n}\r\n\r\nvoid Video_DestroyVideoBuffers()\r\n{\r\n    if (Screenbuffer_IsLocked())\r\n        Screenbuffer_ReleaseLock();\r\n\r\n    if (screenbuffer_1)\r\n        al_destroy_bitmap(screenbuffer_1);\r\n    if (screenbuffer_2)\r\n        al_destroy_bitmap(screenbuffer_2);\r\n\r\n    screenbuffer_1 = screenbuffer_2 = NULL;\r\n\r\n    GUI_DestroyVideoBuffers();\r\n    Data_DestroyVideoBuffers();\r\n    Blit_DestroyVideoBuffers();\r\n    SkinFx_DestroyVideoBuffers();\r\n}\r\n\r\nvoid Video_CreateVideoBuffers()\r\n{\r\n    Video_DestroyVideoBuffers();\r\n\r\n    // Allocate buffers\r\n    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);\r\n    al_set_new_bitmap_format(g_config.video_game_format_request);\r\n    screenbuffer_1      = al_create_bitmap(MAX_RES_X + 32, MAX_RES_Y + 32);\r\n    screenbuffer_2      = al_create_bitmap(MAX_RES_X + 32, MAX_RES_Y + 32);\r\n    screenbuffer        = screenbuffer_1;\r\n    screenbuffer_next   = screenbuffer_2;\r\n\r\n    // Retrieve actual video format. This will be used to compute color values.\r\n    g_screenbuffer_format = al_get_bitmap_format(screenbuffer_1);\r\n\r\n    Screenbuffer_AcquireLock();\r\n\r\n    Blit_CreateVideoBuffers();\r\n    Data_CreateVideoBuffers();\r\n    SkinFx_CreateVideoBuffers();\r\n    if (g_env.state == MEKA_STATE_GUI)\r\n        GUI_SetupNewVideoMode();\r\n}\r\n\r\nstatic int Video_ChangeVideoMode(t_video_driver* driver, int w, int h, bool fullscreen, int refresh_rate, bool fatal)\r\n{\r\n    // Attempt to avoid unnecessary resolution change (on blitter change)\r\n    static struct\r\n    {\r\n        t_video_driver* driver;\r\n        int w, h;\r\n        int fullscreen;\r\n        int refresh_rate;\r\n    } previous_mode = { NULL, -1, -1, -1, -1 };\r\n    if (driver == previous_mode.driver && w == previous_mode.w && h == previous_mode.h && (int)fullscreen == previous_mode.fullscreen && refresh_rate == previous_mode.refresh_rate)\r\n    {\r\n        Video_GameMode_UpdateBounds();\r\n        if (g_env.state == MEKA_STATE_GUI)\r\n            gui_relayout_all();\r\n        return (MEKA_ERR_OK);\r\n    }\r\n\r\n    previous_mode.driver = driver;\r\n    previous_mode.w = w;\r\n    previous_mode.h = h;\r\n    previous_mode.fullscreen = fullscreen;\r\n    previous_mode.refresh_rate = refresh_rate;\r\n\r\n    Video_DestroyVideoBuffers();\r\n\r\n    // Set new mode\r\n    if (g_display != NULL)\r\n    {\r\n#ifdef ARCH_WIN32\r\n        // Allegro is missing keyboard events when there's no display, so as a workaround we clear the key states.\r\n        Inputs_KeyClearAllState();\r\n#endif\r\n        al_unregister_event_source(g_display_event_queue, al_get_display_event_source(g_display));\r\n        al_destroy_display(g_display);\r\n        g_display = NULL;\r\n    }\r\n\r\n    // Create new display\r\n    int display_flags = driver->flags;\r\n    if (fullscreen)\r\n#if ARCH_MACOSX\r\n        display_flags |= ALLEGRO_FULLSCREEN_WINDOW; // FIXME: Expose/use FULLSCREEN_WINDOW everywhere?\r\n#else\r\n        display_flags |= ALLEGRO_FULLSCREEN;\r\n#endif\r\n    else\r\n        display_flags |= ALLEGRO_WINDOWED;\r\n    al_set_new_display_flags(display_flags);\r\n    al_set_new_display_option(ALLEGRO_VSYNC, 2, ALLEGRO_SUGGEST);\r\n    al_set_new_display_refresh_rate(g_config.video_mode_gui_refresh_rate);\r\n    g_display = al_create_display(w, h);\r\n\r\n    if (!g_display)\r\n    {\r\n        if (fatal)\r\n            Quit_Msg(Msg_Get(MSG_Error_Video_Mode), w, h);\r\n        Msg(MSGT_USER, Msg_Get(MSG_Error_Video_Mode), w, h);\r\n        return (MEKA_ERR_FAIL);\r\n    }\r\n\r\n    al_register_event_source(g_display_event_queue, al_get_display_event_source(g_display));\r\n\r\n    g_video.res_x = w;\r\n    g_video.res_y = h;\r\n    g_video.refresh_rate_requested = refresh_rate;\r\n    Video_GameMode_UpdateBounds();\r\n\r\n    // Window title\r\n    al_set_window_title(g_display, Msg_Get(MSG_Window_Title));\r\n\r\n    // Recreate all video buffers\r\n    Video_CreateVideoBuffers();\r\n\r\n    return (MEKA_ERR_OK);\r\n}\r\n\r\nvoid    Video_GameMode_UpdateBounds()\r\n{\r\n    // Compute game area position to be centered on the screen\r\n    Blit_Fullscreen_UpdateBounds();\r\n}\r\n\r\nvoid    Video_GameMode_ScreenPosToEmulatedPos(int screen_x, int screen_y, int* pemu_x, int* pemu_y, bool clamp)\r\n{\r\n    if (clamp)\r\n    {\r\n        const int rx = LinearRemapClamp(screen_x, g_video.game_area_x1, g_video.game_area_x2, 0, g_driver->x_res);\r\n        const int ry = LinearRemapClamp(screen_y, g_video.game_area_y1, g_video.game_area_y2, 0, g_driver->y_res);\r\n        *pemu_x = rx;\r\n        *pemu_y = ry;\r\n    }\r\n    else\r\n    {\r\n        const int rx = LinearRemap(screen_x, g_video.game_area_x1, g_video.game_area_x2, 0, g_driver->x_res);\r\n        const int ry = LinearRemap(screen_y, g_video.game_area_y1, g_video.game_area_y2, 0, g_driver->y_res);\r\n        *pemu_x = rx;\r\n        *pemu_y = ry;\r\n    }\r\n}\r\n\r\nvoid    Video_GameMode_EmulatedPosToScreenPos(int emu_x, int emu_y, int* pscreen_x, int* pscreen_y, bool clamp)\r\n{\r\n    if (clamp)\r\n    {\r\n        const int rx = LinearRemapClamp(emu_x, 0, g_driver->x_res, g_video.game_area_x1, g_video.game_area_x2);\r\n        const int ry = LinearRemapClamp(emu_y, 0, g_driver->y_res, g_video.game_area_y1, g_video.game_area_y2);\r\n        *pscreen_x = rx;\r\n        *pscreen_y = ry;\r\n    }\r\n    else\r\n    {\r\n        const int rx = LinearRemap(emu_x, 0, g_driver->x_res, g_video.game_area_x1, g_video.game_area_x2);\r\n        const int ry = LinearRemap(emu_y, 0, g_driver->y_res, g_video.game_area_y1, g_video.game_area_y2);\r\n        *pscreen_x = rx;\r\n        *pscreen_y = ry;\r\n    }\r\n}\r\n\r\nvoid    Video_GameMode_GetScreenCenterPos(int* pscreen_x, int* pscreen_y)\r\n{\r\n    *pscreen_x = (g_video.game_area_x1 + g_video.game_area_x2) >> 1;\r\n    *pscreen_y = (g_video.game_area_y1 + g_video.game_area_y2) >> 1;\r\n}\r\n\r\nvoid    Video_ClearScreenBackBuffer()\r\n{\r\n    // Note: actual clearing will be done in blit.c\r\n    g_video.clear_requests = 3;\r\n}\r\n\r\nvoid    Video_EnumerateDisplayModes()\r\n{\r\n    std::vector<t_video_mode>& display_modes = g_video.display_modes;\r\n    display_modes.clear();\r\n\r\n    const int modes = al_get_num_display_modes();\r\n    for (int i = 0; i != modes; i++)\r\n    {\r\n        ALLEGRO_DISPLAY_MODE al_display_mode;\r\n        if (al_get_display_mode(i, &al_display_mode))\r\n        {\r\n            //Msg(MSGT_DEBUG, \"Display Mode: %dx%d @ %d Hz, format %d\", display_mode.width, display_mode.height, display_mode.refresh_rate, display_mode.format);\r\n            display_modes.resize(display_modes.size()+1);\r\n\r\n            t_video_mode* video_mode = &display_modes.back();\r\n            video_mode->w = al_display_mode.width;\r\n            video_mode->h = al_display_mode.height;\r\n            //video_mode->color_format = al_display_mode.format;\r\n            video_mode->refresh_rate = al_display_mode.refresh_rate;\r\n        }\r\n    }\r\n\r\n    // filter out color_format duplicates because we ignore it for now\r\n    for (size_t i = 0; i < display_modes.size(); i++)\r\n    {\r\n        t_video_mode* video_mode = &display_modes[i];\r\n        for (size_t j = i + 1; j < display_modes.size(); j++)\r\n        {\r\n            t_video_mode* video_mode_2 = &display_modes[j];\r\n            if (video_mode->w == video_mode_2->w && video_mode->h == video_mode_2->h)\r\n            {\r\n                 if (video_mode->refresh_rate == video_mode_2->refresh_rate)\r\n                 {\r\n                     display_modes.erase(display_modes.begin()+j);\r\n                     j--;\r\n                 }\r\n            }\r\n        }\r\n    }\r\n\r\n    // find mode closest to current setting\r\n    g_video.display_mode_current_index = 0;\r\n    int closest_index = -1;\r\n    float closest_d2 = FLT_MAX;\r\n    for (size_t i = 0; i < display_modes.size(); i++)\r\n    {\r\n        t_video_mode* video_mode = &display_modes[i];\r\n\r\n        int dx = (video_mode->w - g_config.video_mode_gui_res_x);\r\n        int dy = (video_mode->h - g_config.video_mode_gui_res_y);\r\n        float d2 = dx*dx + dy*dy;\r\n\r\n        if (closest_d2 > d2)\r\n        {\r\n            if (closest_index != -1)\r\n                if (video_mode->refresh_rate != 0 && g_config.video_mode_gui_refresh_rate != 0 && video_mode->refresh_rate != g_config.video_mode_gui_refresh_rate)\r\n                    continue;\r\n            closest_d2 = d2;\r\n            closest_index = i;\r\n        }\r\n    }\r\n    if (closest_index != -1)\r\n        g_video.display_mode_current_index = closest_index;\r\n}\r\n\r\nvoid    Video_Setup_State()\r\n{\r\n    switch (g_env.state)\r\n    {\r\n    case MEKA_STATE_SHUTDOWN:\r\n        {\r\n            Video_DestroyVideoBuffers();\r\n            if (g_display)\r\n                al_destroy_display(g_display);\r\n            g_display = NULL;\r\n            break;\r\n        }\r\n    case MEKA_STATE_GAME: // FullScreen mode ----------------------------\r\n        {\r\n            const int refresh_rate = g_config.video_mode_gui_refresh_rate;\r\n            const int game_res_x = g_config.video_mode_gui_res_x;\r\n            const int game_res_y = g_config.video_mode_gui_res_y;\r\n            const bool game_fullscreen = g_config.video_fullscreen;\r\n\r\n            if (Video_ChangeVideoMode(g_config.video_driver, game_res_x, game_res_y, game_fullscreen, refresh_rate, FALSE) != MEKA_ERR_OK)\r\n            {\r\n                g_env.state = MEKA_STATE_GUI;\r\n                Video_Setup_State();\r\n                Msg(MSGT_USER, \"%s\", Msg_Get(MSG_Error_Video_Mode_Back_To_GUI));\r\n                return;\r\n            }\r\n            fs_out = al_get_backbuffer(g_display);\r\n            Palette_Emulation_Reload();\r\n            Video_ClearScreenBackBuffer();\r\n        }\r\n        break;\r\n    case MEKA_STATE_GUI:\r\n        {\r\n            const int refresh_rate = g_config.video_mode_gui_refresh_rate;\r\n            const int gui_res_x = g_config.video_mode_gui_res_x;\r\n            const int gui_res_y = g_config.video_mode_gui_res_y;\r\n            Video_ChangeVideoMode(g_config.video_driver, gui_res_x, gui_res_y, g_config.video_fullscreen, refresh_rate, TRUE);\r\n            if (opt.GUI_Inited)\r\n                gui_redraw_everything_now_once();\r\n        }\r\n        break;\r\n    }\r\n    Inputs_Peripheral_Change_Update();\r\n}\r\n\r\nvoid    Screen_Save_to_Next_Buffer()\r\n{\r\n    al_set_target_bitmap(screenbuffer_next);\r\n    al_draw_bitmap(screenbuffer, 0, 0, 0);\r\n}\r\n\r\nvoid    Screen_Restore_from_Next_Buffer()\r\n{\r\n    al_set_target_bitmap(screenbuffer);\r\n    al_draw_bitmap(screenbuffer_next, 0, 0, 0);\r\n}\r\n\r\nvoid    Screenbuffer_AcquireLock()\r\n{\r\n    assert(g_screenbuffer_locked_region == NULL && g_screenbuffer_locked_buffer == NULL);\r\n    g_screenbuffer_locked_region = al_lock_bitmap(screenbuffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);\r\n    g_screenbuffer_locked_buffer = screenbuffer;\r\n}\r\n\r\nvoid    Screenbuffer_ReleaseLock()\r\n{\r\n    assert(g_screenbuffer_locked_region != NULL && g_screenbuffer_locked_buffer != NULL);\r\n    assert(g_screenbuffer_locked_buffer == screenbuffer);\r\n    al_unlock_bitmap(screenbuffer);\r\n    g_screenbuffer_locked_region = NULL;\r\n    g_screenbuffer_locked_buffer = NULL;\r\n}\r\n\r\nbool    Screenbuffer_IsLocked()\r\n{\r\n    return g_screenbuffer_locked_region != NULL;\r\n}\r\n\r\nvoid    Video_UpdateEvents()\r\n{\r\n    ALLEGRO_EVENT event;\r\n    while (al_get_next_event(g_display_event_queue, &event))\r\n    {\r\n        switch (event.type)\r\n        {\r\n        case ALLEGRO_EVENT_DISPLAY_CLOSE:\r\n            if (g_env.state == MEKA_STATE_INIT || g_env.state == MEKA_STATE_SHUTDOWN)\r\n                break;\r\n            opt.Force_Quit = TRUE;\r\n            break;\r\n        case ALLEGRO_EVENT_DISPLAY_SWITCH_IN:\r\n            //Msg(MSGT_USER, \"ALLEGRO_EVENT_DISPLAY_SWITCH_IN\");\r\n            //if (g_env.state == MEKA_STATE_INIT || g_env.state == MEKA_STATE_SHUTDOWN)\r\n            //  return;\r\n            //// clear_to_color (screen, BORDER_COLOR);\r\n            //Video_Clear();\r\n            //Sound_Playback_Resume();\r\n            Inputs_Sources_ClearOutOfFocus();\r\n            break;\r\n        case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT:\r\n            //Msg(MSGT_USER, \"ALLEGRO_EVENT_DISPLAY_SWITCH_OUT\");\r\n            //if (g_env.state == MEKA_STATE_INIT || g_env.state == MEKA_STATE_SHUTDOWN)\r\n            //  break;\r\n            //Sound_Playback_Mute();\r\n            Inputs_Sources_ClearOutOfFocus();\r\n            break;\r\n        }\r\n    }\r\n}\r\n\r\n// This is called when line == tsms.VDP_Line_End\r\nvoid    Video_RefreshScreen()\r\n{\r\n    PROFILE_STEP(\"Video_RefreshScreen()\");\r\n\r\n    Screenbuffer_ReleaseLock();\r\n    PROFILE_STEP(\"Screenbuffer_ReleaseLock()\");\r\n\r\n    Video_UpdateEvents();\r\n    PROFILE_STEP(\"Video_UpdateEvents()\");\r\n\r\n    // 3-D glasses emulation cancel out one render out of two\r\n    if (Glasses.Enabled && Glasses_Must_Skip_Frame())\r\n        Screen_Restore_from_Next_Buffer();\r\n\r\n    if (fskipper.Show_Current_Frame)\r\n    {\r\n        Capture_Update();\r\n\r\n        if (g_machine_pause_requests > 0)\r\n            Machine_Pause();\r\n\r\n        gui_update_mouse();\r\n        if (g_env.state == MEKA_STATE_GUI)\r\n        {\r\n            gui_update();\r\n            PROFILE_STEP(\"gui_update()\");\r\n\r\n            // Check if we're switching GUI off now\r\n            if (g_env.state != MEKA_STATE_GUI)\r\n            {\r\n                Screenbuffer_AcquireLock();\r\n                return;\r\n            }\r\n\r\n            gui_draw();\r\n            PROFILE_STEP(\"gui_draw()\");\r\n\r\n            Blit_GUI();\r\n            PROFILE_STEP(\"Blit_GUI()\");\r\n        }\r\n\r\n        if (g_env.state == MEKA_STATE_GAME)\r\n        {\r\n            // Show current FPS\r\n            if (fskipper.FPS_Display)\r\n            {\r\n                char buf[16];\r\n                sprintf(buf, \"%.1f FPS\", fskipper.FPS);\r\n                int x, y;\r\n                if (g_driver->id == DRV_GG) { x = 48; y = 24; } else { x = 8; y = 6; }\r\n                al_set_target_bitmap(screenbuffer);\r\n                Font_Print(FONTID_MEDIUM, buf, x, y, COLOR_WHITE); // In white\r\n                //g_gui_status.timeleft = 0; // Force disabling the current message because it is slow to display\r\n            }\r\n\r\n            // Blit emulated screen in fullscreen mode\r\n            Blit_Fullscreen();\r\n        }\r\n\r\n        // Palette update after redraw\r\n        Palette_UpdateAfterRedraw();\r\n\r\n        // Clear keypress queue\r\n        Inputs_KeyPressQueue_Clear();\r\n\r\n    } // of: if (fskipper.Show_Current_Frame)\r\n\r\n    // Draw next image in other buffer\r\n    if (g_machine_flags & MACHINE_PAUSED)\r\n    {\r\n        Screen_Restore_from_Next_Buffer();\r\n    }\r\n    else\r\n    {\r\n        // Swap buffers\r\n        ALLEGRO_BITMAP *tmp = screenbuffer;\r\n        screenbuffer = screenbuffer_next;\r\n        screenbuffer_next = tmp;\r\n        // Msg(MSGT_DEBUG, \"Swap buffer. screenbuffer=%d\", screenbuffer==screenbuffer_1?1:2);\r\n\r\n        // In debugging mode, copy previously rendered buffer to new one\r\n        // This is so the user always see the current rendering taking place over the previous one\r\n        #ifdef MEKA_Z80_DEBUGGER\r\n            if (Debugger.active)\r\n                Screen_Restore_from_Next_Buffer();\r\n        #endif\r\n    }\r\n\r\n    // Ask frame-skipper whether next frame should be drawn or not\r\n    fskipper.Show_Current_Frame = Frame_Skipper();\r\n    PROFILE_STEP(\"Frame_Skipper()\");\r\n\r\n    Screenbuffer_AcquireLock();\r\n    PROFILE_STEP(\"Screenbuffer_AcquireLock()\");\r\n}\r\n\r\nt_video_driver* VideoDriver_FindByName(const char* name)\r\n{\r\n    t_video_driver* driver = &g_video_drivers[0];\r\n    while (driver->name)\r\n    {\r\n        if (stricmp(name, driver->name) == 0)\r\n            return driver;\r\n        driver++;\r\n    }\r\n\r\n    // Silently return default\r\n    return g_video_driver_default;\r\n}\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/video.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - video.h\r\n// Video / Miscellaneous - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct t_video_mode\r\n{\r\n    int         w;\r\n    int         h;\r\n    //int       color_format;\r\n    int         refresh_rate;\r\n};\r\n\r\nstruct t_video\r\n{\r\n    int     driver;                         // Current driver\r\n    int     res_x, res_y;                   // Current resolution\r\n    int     refresh_rate_requested;         // Requested refresh rate\r\n    int     clear_requests;                 // Set to a value to request successive clears\r\n    int     game_area_x1, game_area_y1;     // Game area frame\r\n    int     game_area_x2, game_area_y2;\r\n    std::vector<t_video_mode>   display_modes;\r\n    int                         display_mode_current_index;\r\n};\r\n\r\nstruct t_video_driver\r\n{\r\n    const char* name;\r\n    const char* desc;\r\n    int         flags;\r\n};\r\nextern t_video          g_video;\r\nextern t_video_driver   g_video_drivers[];\r\nextern t_video_driver*  g_video_driver_default;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    Video_Init();\r\nvoid    Video_CreateVideoBuffers();\r\nvoid    Video_DestroyVideoBuffers();\r\n\r\nvoid    Video_ClearScreenBackBuffer();\r\nvoid    Video_Setup_State();\r\nvoid    Video_EnumerateDisplayModes();\r\nint     Video_FindClosestDisplayMode(int w, int h, int refresh_rate);\r\n\r\nvoid    Video_GameMode_UpdateBounds();\r\nvoid    Video_GameMode_ScreenPosToEmulatedPos(int screen_x, int screen_y, int* pemu_x, int* pemu_y, bool clamp);\r\nvoid    Video_GameMode_EmulatedPosToScreenPos(int emu_x, int emu_y, int* pscreen_x, int* pscreen_y, bool clamp);\r\nvoid    Video_GameMode_GetScreenCenterPos(int* pscreen_x, int* pscreen_y);\r\n\r\nvoid    Video_RefreshScreen();\r\nvoid    Video_UpdateEvents();\r\n\r\nvoid    Screenbuffer_AcquireLock();\r\nvoid    Screenbuffer_ReleaseLock();\r\nbool    Screenbuffer_IsLocked();\r\n\r\nvoid    Screen_Save_to_Next_Buffer();\r\nvoid    Screen_Restore_from_Next_Buffer();\r\n\r\nt_video_driver* VideoDriver_FindByName(const char* name);\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/video_c.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - video_c.c\n// Video / C Functions - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"video_m5.h\"\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Decode_Tile_C (int tile_n, u8* dst)\n{\n    const u8* src = &VRAM[tile_n << 5];\n\n    // byte 0->3: bitplane x for line 0\n    int lines = 8;\n    while (lines-- != 0)\n    {\n        const u32 src0 = src[0];\n        const u32 src1 = src[1];\n        const u32 src2 = src[2];\n        const u32 src3 = src[3];\n        dst[0] = ((src0 & 0x80)>>7) | ((src1 & 0x80)>>6) | ((src2 & 0x80)>>5) | ((src3 & 0x80)>>4);\n        dst[1] = ((src0 & 0x40)>>6) | ((src1 & 0x40)>>5) | ((src2 & 0x40)>>4) | ((src3 & 0x40)>>3);\n        dst[2] = ((src0 & 0x20)>>5) | ((src1 & 0x20)>>4) | ((src2 & 0x20)>>3) | ((src3 & 0x20)>>2);\n        dst[3] = ((src0 & 0x10)>>4) | ((src1 & 0x10)>>3) | ((src2 & 0x10)>>2) | ((src3 & 0x10)>>1);\n        dst[4] = ((src0 & 0x08)>>3) | ((src1 & 0x08)>>2) | ((src2 & 0x08)>>1) | ((src3 & 0x08)   );\n        dst[5] = ((src0 & 0x04)>>2) | ((src1 & 0x04)>>1) | ((src2 & 0x04)   ) | ((src3 & 0x04)<<1);\n        dst[6] = ((src0 & 0x02)>>1) | ((src1 & 0x02)   ) | ((src2 & 0x02)<<1) | ((src3 & 0x02)<<2);\n        dst[7] = ((src0 & 0x01)   ) | ((src1 & 0x01)<<1) | ((src2 & 0x01)<<2) | ((src3 & 0x01)<<3);\n        src += 4;\n        dst += 8;\n    }\n}\n\nvoid    Find_Last_Sprite(int sprites_height, int VDP_Line)\n{\n    int sprites_count = 0;\n    int sprites_on_line = 0;\n\n    const u8* sat = g_machine.VDP.sprite_attribute_table;\n    while (sprites_count < 64)\n    {\n        int y;\n        if ((y = sat[sprites_count]) == 208)\n            break;\n        sprites_count++;\n        if (y > 224)\n            y -= 256;\n        const int line = VDP_Line - y - 1;\n        if (line >= 0 && line < sprites_height)\n            sprites_on_line++;\n    }\n\n    // Assign to globals\n    Sprite_Last = sprites_count - 1;\n    Sprites_on_Line = sprites_on_line;\n}\n\n// FIXME-EMU: Not sure if this behavior is correct but it served us well so far.\nvoid    Find_Last_Sprite_Wide(int sprites_height, int VDP_Line)\n{\n    int sprites_count = 0;\n    int sprites_on_line = 0;\n\n    const u8* sat = g_machine.VDP.sprite_attribute_table;\n    while (sprites_count < 64)\n    {\n        int y;\n        if ((y = sat[sprites_count++]) > 224)\n            y -= 256;\n        const int line = VDP_Line - y - 1;\n        if (line >= 0 && line < sprites_height)\n            sprites_on_line++;\n    }\n\n    // Assign to globals\n    Sprite_Last = sprites_count - 1;\n    Sprites_on_Line = sprites_on_line;\n}\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/video_c.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - video_c.h\n// Video / C Functions - Headers\n//-----------------------------------------------------------------------------\n// NOTE:\n//  This file also contains definition pointing to X86 versions, if enabled.\n//-----------------------------------------------------------------------------\n\n#define Decode_Tile(n)                 Decode_Tile_C (n, tgfx.Tile_Decoded[n])\n#define Sprite_Collide_Line            Sprite_Collide_Line_C\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/video_m2.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - video_m2.c\n// TMS9918 Video Modes Emulation - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n#include \"palette.h\"\n#include \"vdp.h\"\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstatic u8    Sprites_On_Line[192 + 32];\n\nALLEGRO_COLOR TMS9918_Palette[16] =\n{\n    { (4*0x00)/255.0f, (4*0x00)/255.0f, (4*0x00)/255.0f, 1.0f }, /*  0: Transparent   */\n    { (4*0x00)/255.0f, (4*0x00)/255.0f, (4*0x00)/255.0f, 1.0f }, /*  1: Black         */\n    { (4*0x08)/255.0f, (4*0x30)/255.0f, (4*0x08)/255.0f, 1.0f }, /*  2: Medium Green  */\n    { (4*0x18)/255.0f, (4*0x38)/255.0f, (4*0x18)/255.0f, 1.0f }, /*  3: Light Green   */\n    { (4*0x08)/255.0f, (4*0x08)/255.0f, (4*0x38)/255.0f, 1.0f }, /*  4: Dark Blue     */\n    { (4*0x10)/255.0f, (4*0x18)/255.0f, (4*0x38)/255.0f, 1.0f }, /*  5: Light Blue    */\n    { (4*0x28)/255.0f, (4*0x08)/255.0f, (4*0x08)/255.0f, 1.0f }, /*  6: Dark Red      */\n    { (4*0x10)/255.0f, (4*0x30)/255.0f, (4*0x38)/255.0f, 1.0f }, /*  7: Cyan          */\n    { (4*0x38)/255.0f, (4*0x08)/255.0f, (4*0x08)/255.0f, 1.0f }, /*  8: Medium Red    */\n    { (4*0x38)/255.0f, (4*0x18)/255.0f, (4*0x18)/255.0f, 1.0f }, /*  9: Light Red     */\n    { (4*0x30)/255.0f, (4*0x30)/255.0f, (4*0x08)/255.0f, 1.0f }, /* 10: Dark Yellow   */\n    { (4*0x30)/255.0f, (4*0x30)/255.0f, (4*0x20)/255.0f, 1.0f }, /* 11: Light Yellow  */\n    { (4*0x08)/255.0f, (4*0x20)/255.0f, (4*0x08)/255.0f, 1.0f }, /* 12: Dark Green    */\n    { (4*0x30)/255.0f, (4*0x10)/255.0f, (4*0x28)/255.0f, 1.0f }, /* 13: Magenta       */\n    { (4*0x28)/255.0f, (4*0x28)/255.0f, (4*0x28)/255.0f, 1.0f }, /* 14: Grey          */\n    { (4*0x38)/255.0f, (4*0x38)/255.0f, (4*0x38)/255.0f, 1.0f }  /* 15: White         */\n};\n\n//-----------------------------------------------------------------------------\n// Color configuration\n// (Note: absolutly uses those define, so it'll be easier to switch to direct\n//  24/32 output someday)\n//-----------------------------------------------------------------------------\n\nstatic u16* GFX_ScreenData = NULL;\nstatic int  GFX_ScreenPitch = 0;\n\n#define PIXEL_TYPE              u16\n#define PIXEL_PALETTE_TABLE     Palette_EmulationToHostGame\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    TMS9918_Palette_Setup()\n{\n    int i;\n\n    // Set TMS9918 emulation palette\n    Palette_Emulation_SetColor(0, TMS9918_Palette[sms.VDP[7] & 15]);\n    for (i = 1; i != 16; i++)\n        Palette_Emulation_SetColor(i, TMS9918_Palette[i]);\n}\n\n// Note: this is used by tools only (not actual emulation refresh)\nvoid    VDP_Mode0123_DrawTile(ALLEGRO_BITMAP *dst, ALLEGRO_LOCKED_REGION* dst_region, int x, int y, const u8 *pixels_data, int fgcolor_host, int bgcolor_host)\n{\n    const int color_format = al_get_bitmap_format(dst);\n    switch (al_get_pixel_format_bits(color_format))\n    {\n    case 16:\n        {\n            u16* dst_data = (u16*)dst_region->data;\n            const int dst_pitch = dst_region->pitch >> 1;\n            const u16 fgcolor = fgcolor_host;\n            const u16 bgcolor = bgcolor_host;\n            for (int i = 0; i != 8; i++)\n            {\n                const u8 cc = *pixels_data++;\n                u16 *dst8 = dst_data + (dst_pitch*y) + x;\n                dst8[0] = (cc & 0x80) ? fgcolor : bgcolor;\n                dst8[1] = (cc & 0x40) ? fgcolor : bgcolor;\n                dst8[2] = (cc & 0x20) ? fgcolor : bgcolor;\n                dst8[3] = (cc & 0x10) ? fgcolor : bgcolor;\n                dst8[4] = (cc & 0x08) ? fgcolor : bgcolor;\n                dst8[5] = (cc & 0x04) ? fgcolor : bgcolor;\n                dst8[6] = (cc & 0x02) ? fgcolor : bgcolor;\n                dst8[7] = (cc & 0x01) ? fgcolor : bgcolor;\n                y++;\n            }\n            break;\n        }\n    case 32:\n        {\n            u32* dst_data = (u32*)dst_region->data;\n            const int dst_pitch = dst_region->pitch >> 2;\n            const u32 fgcolor = fgcolor_host;\n            const u32 bgcolor = bgcolor_host;\n            for (int i = 0; i != 8; i++)\n            {\n                const u8 cc = *pixels_data++;\n                u32 *dst8 = dst_data + (dst_pitch*y) + x;\n                dst8[0] = (cc & 0x80) ? fgcolor : bgcolor;\n                dst8[1] = (cc & 0x40) ? fgcolor : bgcolor;\n                dst8[2] = (cc & 0x20) ? fgcolor : bgcolor;\n                dst8[3] = (cc & 0x10) ? fgcolor : bgcolor;\n                dst8[4] = (cc & 0x08) ? fgcolor : bgcolor;\n                dst8[5] = (cc & 0x04) ? fgcolor : bgcolor;\n                dst8[6] = (cc & 0x02) ? fgcolor : bgcolor;\n                dst8[7] = (cc & 0x01) ? fgcolor : bgcolor;\n                y++;\n            }\n            break;\n        }\n    default:\n        Msg(MSGT_USER, \"video_m2: unsupported color format: %d\", color_format);\n        break;\n    }\n}\n\nvoid    VDP_Mode0123_DrawTile(ALLEGRO_BITMAP *dst, ALLEGRO_LOCKED_REGION* dst_region, int x, int y, const u8 *pixels_data, const u8 *colors_data)\n{\n    const int color_format = al_get_bitmap_format(dst);\n    switch (al_get_pixel_format_bits(color_format))\n    {\n    case 16:\n        {\n            u16* dst_data = (u16*)dst_region->data;\n            const int dst_pitch = dst_region->pitch >> 1;\n            for (int i = 0; i != 8; i++)\n            {\n                const u8 cc = *pixels_data++;\n                const u8 color_indexes = *colors_data++;\n                const u16 fgcolor = Palette_EmulationToHostGui[color_indexes >> 4];\n                const u16 bgcolor = Palette_EmulationToHostGui[color_indexes & 0x0F];\n                u16 *dst8 = dst_data + (dst_pitch*y) + x;\n                dst8[0] = (cc & 0x80) ? fgcolor : bgcolor;\n                dst8[1] = (cc & 0x40) ? fgcolor : bgcolor;\n                dst8[2] = (cc & 0x20) ? fgcolor : bgcolor;\n                dst8[3] = (cc & 0x10) ? fgcolor : bgcolor;\n                dst8[4] = (cc & 0x08) ? fgcolor : bgcolor;\n                dst8[5] = (cc & 0x04) ? fgcolor : bgcolor;\n                dst8[6] = (cc & 0x02) ? fgcolor : bgcolor;\n                dst8[7] = (cc & 0x01) ? fgcolor : bgcolor;\n                y++;\n            }\n            break;\n        }\n    case 32:\n        {\n            u32* dst_data = (u32*)dst_region->data;\n            const int dst_pitch = dst_region->pitch >> 2;\n            for (int i = 0; i != 8; i++)\n            {\n                const u8 cc = *pixels_data++;\n                const u8 color_indexes = *colors_data++;\n                const u32 fgcolor = Palette_EmulationToHostGui[color_indexes >> 4];\n                const u32 bgcolor = Palette_EmulationToHostGui[color_indexes & 0x0F];\n                u32 *dst8 = dst_data + (dst_pitch*y) + x;\n                dst8[0] = (cc & 0x80) ? fgcolor : bgcolor;\n                dst8[1] = (cc & 0x40) ? fgcolor : bgcolor;\n                dst8[2] = (cc & 0x20) ? fgcolor : bgcolor;\n                dst8[3] = (cc & 0x10) ? fgcolor : bgcolor;\n                dst8[4] = (cc & 0x08) ? fgcolor : bgcolor;\n                dst8[5] = (cc & 0x04) ? fgcolor : bgcolor;\n                dst8[6] = (cc & 0x02) ? fgcolor : bgcolor;\n                dst8[7] = (cc & 0x01) ? fgcolor : bgcolor;\n                y++;\n            }\n            break;\n        }\n    default:\n        Msg(MSGT_USER, \"video_m2: unsupported color format: %d\", color_format);\n        break;\n    }\n}\n\nvoid    Display_Text_0()\n{\n    int         i, j;\n    const PIXEL_TYPE fgcolor = PIXEL_PALETTE_TABLE[sms.VDP[7] >> 4];\n    const PIXEL_TYPE bgcolor = PIXEL_PALETTE_TABLE[0];\n\n    for (j = 0; j != (24 * 8); j += 8)\n    {\n        int k;\n        for (k = 0; k != 8; k ++)\n        {\n            PIXEL_TYPE *dst = GFX_ScreenData + GFX_ScreenPitch*(j + k);\n            const u8 *tile_n = g_machine.VDP.name_table_address + (j * 5);\n\n            // 8 left pixels are black\n            dst[0] = dst[1] = dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = dst[7] = COLOR_BLACK16;    // FIXME-BORDER\n            dst += 8;\n\n            for (i = 8; i != (40 * 6) + 8; i += 6)\n            {\n                const u8 *p2  = g_machine.VDP.sg_pattern_gen_address + (*tile_n << 3) + k;\n                const u8 src6 = *p2;\n                dst[0] = (src6 & 0x80) ? fgcolor : bgcolor;\n                dst[1] = (src6 & 0x40) ? fgcolor : bgcolor;\n                dst[2] = (src6 & 0x20) ? fgcolor : bgcolor;\n                dst[3] = (src6 & 0x10) ? fgcolor : bgcolor;\n                dst[4] = (src6 & 0x08) ? fgcolor : bgcolor;\n                dst[5] = (src6 & 0x04) ? fgcolor : bgcolor;\n                dst += 6;\n                tile_n++;\n            }\n\n            // 8 right pixels are black\n            dst[0] = dst[1] = dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = dst[7] = COLOR_BLACK16;    // FIXME-BORDER\n        }\n    }\n}\n\nvoid    Display_Background_1()\n{\n    int    i, j, j2;\n    int    x, y = 0;\n    const u8 *tile_n = g_machine.VDP.name_table_address;           //-- Tile Table --------//\n\n    // DRAW ALL TILES ------------------------------------------------------------\n    for (i = 0; i != 24; i++)\n    {\n        x = 0;\n        for (j = 0; j != 32; j++)\n        {\n            // Draw one tile\n            const u8 * p1 = g_machine.VDP.sg_pattern_gen_address  + (*tile_n << 3);\n            const u8 * p2 = g_machine.VDP.sg_color_table_address + (*tile_n >> 3);\n            const PIXEL_TYPE color1 = PIXEL_PALETTE_TABLE[*p2 >> 4];\n            const PIXEL_TYPE color2 = PIXEL_PALETTE_TABLE[(*p2) & 0x0F];\n            for (j2 = 0; j2 != 8; j2++)\n            {\n                const u8    src8 = *p1++;\n                PIXEL_TYPE *dst8 = GFX_ScreenData + GFX_ScreenPitch*(y + j2) + x;\n                dst8[0] = (src8 & 0x80) ? color1 : color2;\n                dst8[1] = (src8 & 0x40) ? color1 : color2;\n                dst8[2] = (src8 & 0x20) ? color1 : color2;\n                dst8[3] = (src8 & 0x10) ? color1 : color2;\n                dst8[4] = (src8 & 0x08) ? color1 : color2;\n                dst8[5] = (src8 & 0x04) ? color1 : color2;\n                dst8[6] = (src8 & 0x02) ? color1 : color2;\n                dst8[7] = (src8 & 0x01) ? color1 : color2;\n            }\n            tile_n++;\n            x += 8;\n        }\n        y += 8;\n    }\n}\n\nvoid    Display_Background_2 ()\n{\n    const u8* pattern_name_table = g_machine.VDP.name_table_address;\n    const int vsection_mask = sms.VDP[4] & 3;\n\n    int y = 0;\n    for (int vsection_idx = 0; vsection_idx < 3; vsection_idx++) // screen in 3 parts\n    {\n        const u8* tile_base = g_machine.VDP.sg_pattern_gen_address + ((vsection_idx & vsection_mask) * 0x800);  // Pattern data base\n        const u8* col_base = g_machine.VDP.sg_color_table_address + ((vsection_idx & vsection_mask) * 0x800);   // Color table base\n        for (int ty = 0; ty < 8; ty++)\n        {\n            int x = 0;\n            for (int tx = 0; tx < 32; tx++)\n            {\n                const u32 char_name_value = (*pattern_name_table++);\n                const u32 char_name_addr = char_name_value * 8;\n                const u8* char_pattern_data = tile_base + char_name_addr;\n                const u8* char_color_data = col_base  + char_name_addr;\n\n                // Draw one tile\n                for (int j2 = 0; j2 < 8; j2++)\n                {\n                    PIXEL_TYPE *dst = GFX_ScreenData + GFX_ScreenPitch * (y+j2) + x;\n                    const u8 pattern_8 = (*char_pattern_data++);\n                    const u8 color_indexes = (*char_color_data++);\n                    const PIXEL_TYPE color1 = PIXEL_PALETTE_TABLE[color_indexes >> 4];\n                    const PIXEL_TYPE color2 = PIXEL_PALETTE_TABLE[color_indexes & 0x0F];\n                    dst[0] = (pattern_8 & 0x80) ? color1 : color2;\n                    dst[1] = (pattern_8 & 0x40) ? color1 : color2;\n                    dst[2] = (pattern_8 & 0x20) ? color1 : color2;\n                    dst[3] = (pattern_8 & 0x10) ? color1 : color2;\n                    dst[4] = (pattern_8 & 0x08) ? color1 : color2;\n                    dst[5] = (pattern_8 & 0x04) ? color1 : color2;\n                    dst[6] = (pattern_8 & 0x02) ? color1 : color2;\n                    dst[7] = (pattern_8 & 0x01) ? color1 : color2;\n                }\n                x += 8;\n            }\n            y += 8;\n        }\n    }\n}\n\nvoid    Display_Background_3()\n{\n    int         x, y, z;\n    const u8 *  pattern = g_machine.VDP.name_table_address;\n\n    for (y = 0; y != 192; y += 32)\n    {\n        for (x = 0; x != 256; x += 8)\n        {\n            const u8 *tiles_data = g_machine.VDP.sg_pattern_gen_address + (*pattern++ * 8);\n            for (z = 0; z != 8; z ++)\n            {\n                PIXEL_TYPE *dst;\n                const PIXEL_TYPE color1 = PIXEL_PALETTE_TABLE[*tiles_data >> 4];\n                const PIXEL_TYPE color2 = PIXEL_PALETTE_TABLE[*tiles_data & 0x0F];\n\n                dst = GFX_ScreenData + GFX_ScreenPitch * (y + 0) + x;\n                dst[0] = dst[1] = dst[2] = dst[3] = color1;\n                dst[4] = dst[5] = dst[6] = dst[7] = color2;\n                dst = GFX_ScreenData + GFX_ScreenPitch * (y + 1) + x;\n                dst[0] = dst[1] = dst[2] = dst[3] = color1;\n                dst[4] = dst[5] = dst[6] = dst[7] = color2;\n                dst = GFX_ScreenData + GFX_ScreenPitch * (y + 2) + x;\n                dst[0] = dst[1] = dst[2] = dst[3] = color1;\n                dst[4] = dst[5] = dst[6] = dst[7] = color2;\n                dst = GFX_ScreenData + GFX_ScreenPitch * (y + 3) + x;\n                dst[0] = dst[1] = dst[2] = dst[3] = color1;\n                dst[4] = dst[5] = dst[6] = dst[7] = color2;\n                y += 4;\n                tiles_data++;\n            }\n            y -= 32;\n        }\n        pattern += 96;\n    }\n}\n\n// DRAW A MAGNIFIED MONOCHROME SPRITE TILE ------------------------------------\nvoid    Draw_Sprite_Mono_Double (const u8 *src, int x, int y, int fcolor_idx)\n{\n    if (fcolor_idx & 0x80)\n        x -= 32;\n    fcolor_idx &= 0x0F;\n    if (fcolor_idx == 0)\n        return;\n    const PIXEL_TYPE fcolor = PIXEL_PALETTE_TABLE[fcolor_idx];\n\n    for (int j = 0; j != 8; j++, src++)\n    {\n        if (y < 0 || y > 190)\n        {\n            y += 2;\n            continue;\n        }\n        else\n        {\n            const u8 src8 = *src;\n            if (!(g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED) || Sprites_On_Line [y] <= 4)\n            {\n                PIXEL_TYPE* dst8 = GFX_ScreenData + GFX_ScreenPitch * y + x;\n                if  (src8 & 0x80) { dst8[0]  = dst8[1]  = fcolor; }\n                if  (src8 & 0x40) { dst8[2]  = dst8[3]  = fcolor; }\n                if  (src8 & 0x20) { dst8[4]  = dst8[5]  = fcolor; }\n                if  (src8 & 0x10) { dst8[6]  = dst8[7]  = fcolor; }\n                if  (src8 & 0x08) { dst8[8]  = dst8[9]  = fcolor; }\n                if  (src8 & 0x04) { dst8[10] = dst8[11] = fcolor; }\n                if  (src8 & 0x02) { dst8[12] = dst8[13] = fcolor; }\n                if  (src8 & 0x01) { dst8[14] = dst8[15] = fcolor; }\n            }\n            // if (Sprites_On_Line [y] == 5) { }\n            y++;\n            if (!(g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED) || Sprites_On_Line [y] <= 4)\n            {\n                PIXEL_TYPE* dst8 = GFX_ScreenData + GFX_ScreenPitch * y + x;\n                if  (src8 & 0x80) { dst8[0]  = dst8[1]  = fcolor; }\n                if  (src8 & 0x40) { dst8[2]  = dst8[3]  = fcolor; }\n                if  (src8 & 0x20) { dst8[4]  = dst8[5]  = fcolor; }\n                if  (src8 & 0x10) { dst8[6]  = dst8[7]  = fcolor; }\n                if  (src8 & 0x08) { dst8[8]  = dst8[9]  = fcolor; }\n                if  (src8 & 0x04) { dst8[10] = dst8[11] = fcolor; }\n                if  (src8 & 0x02) { dst8[12] = dst8[13] = fcolor; }\n                if  (src8 & 0x01) { dst8[14] = dst8[15] = fcolor; }\n            }\n            // if (Sprites_On_Line [y] == 5) { }\n            y++;\n        }\n    }\n}\n\n// DRAW A MONOCHROME SPRITE TILE ----------------------------------------------\nvoid    Draw_Sprite_Mono (const u8 *src, int x, int y, int fcolor_idx)\n{\n    if (fcolor_idx & 0x80)\n        x -= 32;\n    fcolor_idx &= 0x0F;\n    if (fcolor_idx == 0)\n        return;\n    PIXEL_TYPE fcolor = PIXEL_PALETTE_TABLE[fcolor_idx];\n\n    for (int j = 0; j != 8; j++, y++, src++)\n    {\n        if (y < 0 || y > 191)\n            continue;\n        if (!(g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED) || Sprites_On_Line [y] <= 4)\n        {\n            const u8     src8 = *src;\n            PIXEL_TYPE* dst8 = GFX_ScreenData + GFX_ScreenPitch * y + x;\n            if  (src8 & 0x80) dst8[0] = fcolor;\n            if  (src8 & 0x40) dst8[1] = fcolor;\n            if  (src8 & 0x20) dst8[2] = fcolor;\n            if  (src8 & 0x10) dst8[3] = fcolor;\n            if  (src8 & 0x08) dst8[4] = fcolor;\n            if  (src8 & 0x04) dst8[5] = fcolor;\n            if  (src8 & 0x02) dst8[6] = fcolor;\n            if  (src8 & 0x01) dst8[7] = fcolor;\n        }\n        // if (Sprites_On_Line [y] == 5) { }\n    }\n}\n\nstatic const int Table_Height [4] = { 8, 16, 16, 32 };\nstatic const int Table_Mask [4] =   { 0xFF, 0xFF, 0xFC, 0xFC };\n\n// DISPLAY SPRITES IN VIDEO MODE 1/2/3 ----------------------------------------\nvoid    Display_Sprites_1_2_3()\n{\n    const int Sprite_Mode = Sprites_Double | Sprites_16x16;\n    const int Mask = Table_Mask [Sprite_Mode];\n    const int sprites_height = Table_Height [Sprite_Mode];\n\n    // No sprites in Video Mode 0 (Text Mode)\n    if (tsms.VDP_VideoMode == 0)\n        return;\n\n    memset (Sprites_On_Line, 0, 192 + 32);\n\n    // Find last sprite\n    const u8* sat = g_machine.VDP.sprite_attribute_table;\n    int i;\n    for (i = 0; i < 32 * 4; i += 4)\n    {\n        int y = sat[i];\n        if ((y ++) == 0xD0)\n            break;\n        if (y > 0xD0) y -= 0xFF;\n        for (int j = y; j < y + sprites_height; j++)\n            if (j >= 0)\n                Sprites_On_Line [j]++;\n    }\n    i -= 4;\n\n    // Display sprites -----------------------------------------------------------\n    while (i >= 0)\n    {\n        // Calculate vertical position and handle special meanings ----------------\n        int y = sat[i];\n        if ((y ++) == 0xD0)\n            break;\n        if (y > 0xD0)\n            y -= 0x100;\n        // Calculate horizontal position ------------------------------------------\n        int x = sat[i + 1];\n        // Calculate tile starting address in VRAM --------------------------------\n        const u8* k = (u8 *)((long int)((sat[i + 2] & Mask) << 3) + (long int)g_machine.VDP.sprite_pattern_gen_address);\n        switch (Sprite_Mode)\n        {\n            // 8x8 (used in: Sokouban)\n        case 0: //----------- address -- x position -- y position -- color\n            Draw_Sprite_Mono (k, x, y, sat[i + 3]);\n            break;\n            // 16x16 - 8x8 Doubled (used in: ?)\n        case 1: //----------- address -- x position -- y position -- color\n            Draw_Sprite_Mono_Double (k, x, y, sat[i + 3]);\n            break;\n            // 16x16 (used in most games)\n        case 2: //----------- address -- x position --- y position --- color -----\n            Draw_Sprite_Mono (k,      x,     y,     sat[i + 3]);\n            Draw_Sprite_Mono (k + 8,  x,     y + 8, sat[i + 3]);\n            Draw_Sprite_Mono (k + 16, x + 8, y,     sat[i + 3]);\n            Draw_Sprite_Mono (k + 24, x + 8, y + 8, sat[i + 3]);\n            break;\n        case 3: //------------------ address ---- x position ---- y position --- color ----\n            Draw_Sprite_Mono_Double (k,      x,      y,      sat[i + 3]);\n            Draw_Sprite_Mono_Double (k + 8,  x,      y + 16, sat[i + 3]);\n            Draw_Sprite_Mono_Double (k + 16, x + 16, y,      sat[i + 3]);\n            Draw_Sprite_Mono_Double (k + 24, x + 16, y + 16, sat[i + 3]);\n            break;\n        }\n        i -= 4;\n        // Decrease Sprites_On_Line values ----------------------------------------\n        for (int j = y; j < y + sprites_height; j++)\n            if (j >= 0)\n                Sprites_On_Line [j]--;\n    }\n}\n\nvoid    Refresh_Modes_0_1_2_3()\n{\n    GFX_ScreenData = (u16*)g_screenbuffer_locked_region->data;\n    GFX_ScreenPitch = g_screenbuffer_locked_region->pitch / sizeof(u16);    // Pitch in u16 pixel unit to ease pointer manipulations\n\n    // Display Background\n    if (opt.Layer_Mask & LAYER_BACKGROUND)\n    {\n        if (Display_ON)\n        {\n            switch (tsms.VDP_VideoMode)\n            {\n            case 0: Display_Text_0(); break;\n            case 1: Display_Background_1(); break;\n            case 2: Display_Background_2(); break;\n            case 3: Display_Background_3(); break;\n            }\n        }\n        else\n        {\n            // Clear screen\n            al_set_target_bitmap(screenbuffer);\n            alx_locked_draw_filled_rectangle(g_screenbuffer_locked_region, 0, 0, SMS_RES_X, SMS_RES_Y, BORDER_COLOR);\n        }\n    }\n    else\n    {\n        // Clear screen with yellow-ish color\n        al_set_target_bitmap(screenbuffer);\n        alx_locked_draw_filled_rectangle(g_screenbuffer_locked_region, 0, 0, SMS_RES_X, SMS_RES_Y, COLOR_DEBUG_BACKDROP);\n    }\n    // Display Sprites\n    if ((opt.Layer_Mask & LAYER_SPRITES) && Display_ON)\n    {\n        Display_Sprites_1_2_3();\n    }\n}\n\n/*\n**     _____\n**    |     |\n**  1 |   __|__\n**    |__|__|  |\n**       |     | 2\n**       |_____|\n**\n*/\n// FIXME: Zoomed sprites are actually not handled well in the collision tests\n/*\nvoid    Check_Sprites_Collision_Modes_1_2_3()\n{\n int    Mask = Table_Mask [Sprites_Double | Sprites_16x16];\n int    Size = Table_Height [Sprites_Double | Sprites_16x16];\n byte   Sprite_Last;\n byte   n1, n2, dx, dy;\n byte   *SprSrc, *SprDst;\n byte   *TileSrc, *TileDst, *TileTmp;\n\n Sprite_Last = 0;\n SprSrc = sprite_attribute_table;\n while (Sprite_Last < 32 && SprSrc[0] != 208)\n    { Sprite_Last++; SprSrc += 4; }\n\n for (n1 = 0, SprSrc = sprite_attribute_table; n1 < Sprite_Last; n1++, SprSrc += 4)\n     {\n     // Skip if this sprite is not drawn\n     if ((SprSrc[3] & 0x0F) == 0)\n        continue;\n\n     for (n2 = n1 + 1, SprDst = SprSrc + 4; n2 < Sprite_Last; n2++, SprDst += 4)\n        {\n        // Skip if this sprite is not drawn\n        if ((SprDst[3] & 0x0F) == 0)\n           continue;\n\n        // Compute delta-y between the two sprites, skip if they cannot overlap\n        dy = SprSrc[0] - SprDst[0];\n        if ((dy >= Size) && (dy <= 256 - Size))\n           continue;\n\n        // Compute delta-x between the two sprites, skip if they cannot overlap\n        dx = SprSrc[1] - SprDst[1];\n        if ((dx >= Size) && (dx <= 256 - Size))\n           continue;\n\n        // Prepare pointers to the first tile line of each sprite\n        TileSrc = g_machine.VDP.sprite_pattern_gen_address | ((long)(SprSrc[2] & Mask) << 3);\n        TileDst = g_machine.VDP.sprite_pattern_gen_address | ((long)(SprDst[2] & Mask) << 3);\n\n        if (dy < Size)\n           {\n           TileDst += dy;\n           }\n        else\n           {\n           dy = 256 - dy;\n           TileSrc += dy;\n           }\n        if (dx > 256 - Size)\n           {\n           dx = 256 - dx;\n           TileTmp = TileSrc; TileSrc = TileDst; TileDst = TileTmp;\n           }\n\n        // Finally, attempt to compare actual sprites pixels\n        while (dy < Size)\n           {\n           if (Size == 8)\n              {\n              if (*TileDst & (*TileSrc >> dx))\n                 break;\n              }\n           else\n              {\n              if ( (((word)*TileDst << 8) + *(TileDst + 16))\n               & ((((word)*TileSrc << 8) + *(TileSrc + 16)) >> dx) )\n                 break;\n              }\n           dy++;\n           TileSrc++;\n           TileDst++;\n           }\n\n        if (dy < Size)\n           {\n           //Msg(MSGT_USER, \"Sprites %d & %d Collide\", n1, n2);\n           sms.VDP_Status |= VDP_STATUS_SpriteCollision; // Set VDP Status Collision Bit\n           return;\n           }\n        }\n    }\n}\n*/\n\n// FIXME: Zoomed sprites are actually not handled well in the collision tests\nvoid    Check_Sprites_Collision_Modes_1_2_3_Line (int line)\n{\n  const int   mask = Table_Mask [Sprites_Double | Sprites_16x16];\n  const int   size = Table_Height [Sprites_Double | Sprites_16x16];\n\n  int   src_n,     dst_n;\n  int   src_y,     dst_y;\n  const u8 * src_spr;\n  const u8 * src_tile;\n  const u8 * dst_spr;\n  const u8 * dst_tile;\n\n  int   delta_x;\n  int   delta_y;\n\n  const u8* sat = g_machine.VDP.sprite_attribute_table;\n  for (src_n = 0, src_spr = sat, src_y = src_spr[0]; src_n < 31 && src_y != 208;\n       src_n++, src_spr += 4, src_y = src_spr[0])\n     {\n     // Skip if this sprite does not cover current line\n     if (line < src_y || line >= src_y + size)\n        continue;\n\n     // Skip if this sprite is not shown (color 0)\n     if ((src_spr[3] & 0x0F) == 0)\n        continue;\n\n     // Now for all other sprites to compare with...\n     for (dst_n = src_n + 1, dst_spr = src_spr + 4, dst_y = dst_spr[0];\n          dst_n < 32 && dst_y != 208;\n          dst_n++, dst_spr += 4, dst_y = dst_spr[0])\n        {\n        // Skip if this sprite does not cover current line\n        if (line < dst_y || line >= dst_y + size)\n           continue;\n\n        // Skip if this sprite is not shown (color 0)\n        if ((dst_spr[3] & 0x0F) == 0)\n           continue;\n\n        // Compare delta_y\n        delta_y = src_y - dst_y;\n        //if (delta_y >= size || delta_y <= -size)\n        //   Msg(MSGT_USER, \"delta_y = %d\", delta_y);\n\n        // Compute delta_x, skip if the sprites cannot overlap\n        delta_x = src_spr[1] - dst_spr[1];\n        if (delta_x >= size || delta_x <= -size)\n           continue;\n\n        // Prepare pointers to the first tile of each sprite\n        src_tile = (u8 *)((long int)g_machine.VDP.sprite_pattern_gen_address | ((long int)(src_spr[2] & mask) << 3));\n        dst_tile = (u8 *)((long int)g_machine.VDP.sprite_pattern_gen_address | ((long int)(dst_spr[2] & mask) << 3));\n\n        // Offset those pointers to the first tile line\n        if (delta_y > 0)\n           dst_tile += delta_y;\n        else\n        if (delta_y < 0)\n        {\n           delta_y = -delta_y;\n           src_tile += delta_y;\n        }\n\n        // Inverse sprites if delta_x < 0 for the purpose of the comparaison\n        if (delta_x < 0)\n        {\n            const u8* tmp = src_tile;\n            src_tile  = dst_tile;\n            dst_tile  = tmp;\n            delta_x = -delta_x;\n        }\n\n        // Finally compare actual sprites pixels\n        if (size == 8)\n           {\n           while (delta_y < 8)\n              {\n              if (*dst_tile++ & (*src_tile++ >> delta_x))\n                 break;\n              delta_y++;\n              }\n           }\n        else\n           {\n           while (delta_y < size)\n              {\n              if ( (((word)*dst_tile << 8) | *(dst_tile + 16))\n                & ((((word)*src_tile << 8) | *(src_tile + 16)) >> delta_x) )\n                 break;\n              delta_y++;\n              dst_tile++;\n              src_tile++;\n              }\n           }\n\n        if (delta_y < size)\n           {\n           // Msg(MSGT_USER, \"Sprites %d & %d Collide\", src_n, dst_n);\n           sms.VDP_Status |= VDP_STATUS_SpriteCollision; // Set VDP Status Collision Bit\n           return;\n           }\n\n        }\n     }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/video_m2.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - video_m2.h\n// TMS9918 Video Modes Emulation - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Display_Text_0();\nvoid    Display_Sprites_1_2_3();\nvoid    Display_Background_1();\nvoid    Display_Background_2();\nvoid    Display_Background_3();\nvoid    Refresh_Modes_0_1_2_3();\n\n//void    Check_Sprites_Collision_Modes_1_2_3();\nvoid    Check_Sprites_Collision_Modes_1_2_3_Line(int line);\n\nvoid    TMS9918_Palette_Setup();\nextern ALLEGRO_COLOR    TMS9918_Palette[16];\n\n//-----------------------------------------------------------------------------\n\nvoid     VDP_Mode0123_DrawTile(ALLEGRO_BITMAP *dst, ALLEGRO_LOCKED_REGION* dst_region, int x, int y, const u8 *pixels_data, int fgcolor, int bgcolor);\nvoid     VDP_Mode0123_DrawTile(ALLEGRO_BITMAP *dst, ALLEGRO_LOCKED_REGION* dst_region, int x, int y, const u8 *pixels_data, const u8 *colors_data);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/video_m5.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// Meka - video_m5.c\r\n// SMS/GG Video Mode Rendering - Code\r\n//-----------------------------------------------------------------------------\r\n// Note: 'video_m5.h' is a legacy name. Should be renamed to video_m4 ?\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"fskipper.h\"\r\n#include \"palette.h\"\r\n#include \"vdp.h\"\r\n#include \"video_c.h\"\r\n#include \"video_m5.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic u16* GFX_LineRegionData = NULL;\r\n\r\nextern \"C\"\r\n{\r\nint         Sprite_Last;\r\nint         Sprites_on_Line;\r\nint         Do_Collision;\r\n\r\n#define     Sprites_Collision_Table_Len (SMS_RES_X + 32)\r\nint         Sprites_Collision_Table_Start[Sprites_Collision_Table_Len + 32];\r\nint *       Sprites_Collision_Table = Sprites_Collision_Table_Start + 16;\r\n}\r\nstatic byte Sprites_Draw_Mask [SMS_RES_X + 16];\r\n\r\n//-----------------------------------------------------------------------------\r\n// Color configuration\r\n// (Note: absolutly uses those define, so it'll be easier to switch to direct\r\n//  24/32 output someday)\r\n//-----------------------------------------------------------------------------\r\n\r\n#define PIXEL_TYPE              u16\r\n#define PIXEL_LINE_DST          GFX_LineRegionData\r\n#define PIXEL_PALETTE_TABLE     Palette_EmulationToHostGame\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Note: this is used by tools only (not actual emulation refresh)\r\nvoid    VDP_Mode4_DrawTile(ALLEGRO_BITMAP *dst, ALLEGRO_LOCKED_REGION* dst_region, const u8 *pixels, const u32 *palette_host, int x, int y, int flip)\r\n{\r\n    const int color_format = al_get_bitmap_format(dst);\r\n    switch (al_get_pixel_format_bits(color_format))\r\n    {\r\n    case 16:\r\n        {\r\n            u16* dst_data = (u16*)dst_region->data;\r\n            const int dst_pitch = dst_region->pitch >> 1;\r\n            int i;\r\n            if (flip & 0x0400)\r\n            {\r\n                y += 7;\r\n                if (flip & 0x0200)\r\n                {\r\n                    // 0x0600 : HV Flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u16 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        y--;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    // 0x0400 : V flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u16 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        y--;\r\n                    }\r\n                }\r\n            }\r\n            else\r\n            {\r\n                if (flip & 0x0200)\r\n                {\r\n                    // 0x0200 : H Flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u16 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        y++;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    // 0x0000 : No flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u16 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        y++;\r\n                    }\r\n                }\r\n            }\r\n            break;\r\n        }\r\n    case 32:\r\n        {\r\n            u32* dst_data = (u32*)dst_region->data;\r\n            const int dst_pitch = dst_region->pitch >> 2;\r\n            int i;\r\n            if (flip & 0x0400)\r\n            {\r\n                y += 7;\r\n                if (flip & 0x0200)\r\n                {\r\n                    // 0x0600 : HV Flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u32 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        y--;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    // 0x0400 : V flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u32 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        y--;\r\n                    }\r\n                }\r\n            }\r\n            else\r\n            {\r\n                if (flip & 0x0200)\r\n                {\r\n                    // 0x0200 : H Flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u32 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        y++;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    // 0x0000 : No flip\r\n                    for (i = 0; i != 8; i++)\r\n                    {\r\n                        u32 *dst8 = dst_data + (dst_pitch*y) + x;\r\n                        dst8[0] = palette_host[*pixels++];\r\n                        dst8[1] = palette_host[*pixels++];\r\n                        dst8[2] = palette_host[*pixels++];\r\n                        dst8[3] = palette_host[*pixels++];\r\n                        dst8[4] = palette_host[*pixels++];\r\n                        dst8[5] = palette_host[*pixels++];\r\n                        dst8[6] = palette_host[*pixels++];\r\n                        dst8[7] = palette_host[*pixels++];\r\n                        y++;\r\n                    }\r\n                }\r\n            }\r\n            break;\r\n        }\r\n    default:\r\n        Msg(MSGT_USER, \"video_m5: Unsupported color format: %d.\", color_format);\r\n        break;\r\n    }\r\n}\r\n\r\nvoid    Refresh_Line_5()\r\n{\r\n    // Point to current video line\r\n    GFX_LineRegionData = (u16*)( (u8*)g_screenbuffer_locked_region->data + g_screenbuffer_locked_region->pitch * tsms.VDP_Line );\r\n\r\n    if (fskipper.Show_Current_Frame == TRUE)\r\n    {\r\n        // Scroll lock, update in X latch table (for tilemap viewer)\r\n        if (Top_No_Scroll && tsms.VDP_Line < 16)\r\n            g_machine.VDP.scroll_x_latched_table[tsms.VDP_Line] = 0;\r\n\r\n        // Display Background & Foreground\r\n        if ((opt.Layer_Mask & LAYER_BACKGROUND) && Display_ON)\r\n        {\r\n            Display_BackGround_Line_5();\r\n        }\r\n        else\r\n        {\r\n            // Display is off\r\n            // Select SMS/GG backdrop color, unless background layer display was disabled by user, then use custom color for easier sprite extraction\r\n            u16 backdrop_color;\r\n            if (opt.Layer_Mask & LAYER_BACKGROUND)\r\n                backdrop_color = Palette_EmulationToHostGame[16 | (sms.VDP[7] & 15)];\r\n            else\r\n                backdrop_color = Palette_MakeHostColor(g_screenbuffer_format, COLOR_DEBUG_BACKDROP);\r\n\r\n            u16 *p = GFX_LineRegionData;\r\n            for (int n = 256; n != 0; n--)\r\n                *p++ = backdrop_color;\r\n\r\n            // Clear sprite draw mask, so that all sprite will be displayed\r\n            memset(Sprites_Draw_Mask, 0, 256);\r\n        }\r\n\r\n        Refresh_Sprites_5 (Display_ON && (opt.Layer_Mask & LAYER_SPRITES));\r\n\r\n        // Mask left columns with black if necessary\r\n        if (Mask_Left_8)\r\n        {\r\n            // FIXME-BORDER\r\n            const u16 color_black = COLOR_BLACK16;\r\n            u16* p = GFX_LineRegionData;\r\n            p[0] = color_black;\r\n            p[1] = color_black;\r\n            p[2] = color_black;\r\n            p[3] = color_black;\r\n            p[4] = color_black;\r\n            p[5] = color_black;\r\n            p[6] = color_black;\r\n            p[7] = color_black;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        // Only update collision if frame is being skipped\r\n        Refresh_Sprites_5 (FALSE);\r\n    }\r\n}\r\n\r\n// DISPLAY A BACKGROUND LINE --------------------------------------------------\r\nvoid    Display_BackGround_Line_5()\r\n{\r\n    // X scrolling computations\r\n    int x_scroll = ((Top_No_Scroll) && (tsms.VDP_Line < 16)) ? 0 : g_machine.VDP.scroll_x_latched;\r\n    int x = x_scroll & 7;  // x = x_scroll % 8\r\n    x_scroll >>= 3;    // x_scroll /= 8\r\n    if (x_scroll == 0)\r\n        x_scroll = 32;\r\n\r\n    // Set destination address\r\n    PIXEL_TYPE* dst_buf = PIXEL_LINE_DST;\r\n    u8* sprite_mask = Sprites_Draw_Mask;\r\n\r\n    // Fill first 'non existents' pixels\r\n    // (see SMS \"Scrolling Test\" for exemple of this)\r\n    if (x > 0)\r\n    {\r\n        // If left column is masked, no need to care about what we put there\r\n        // and not even the Sprite_Mask (it can stay undefined!)\r\n        if (Mask_Left_8)\r\n        {\r\n            dst_buf += x;\r\n            sprite_mask += x;\r\n        }\r\n        else\r\n        {\r\n            const PIXEL_TYPE color = PIXEL_PALETTE_TABLE[0];\r\n            for (int i = x; i != 0; i--)\r\n            {\r\n                *dst_buf++ = color;\r\n                *sprite_mask++ = 0;\r\n            }\r\n        }\r\n    }\r\n\r\n    // Y scrolling computations\r\n    int y = tsms.VDP_Line + g_machine.VDP.scroll_y_latched;\r\n    if (Wide_Screen_28)\r\n    {\r\n        y &= 255; // y %= 256, Wrap at 256\r\n        //y -= 32;\r\n    }\r\n    else\r\n    {\r\n        y %= 224;\r\n    }\r\n\r\n    // Bit 0 of Register 2 act as a mask on the 315-5124\r\n    if (g_machine.VDP.model == VDP_MODEL_315_5124)\r\n        if ((sms.VDP[2] & 1) == 0)\r\n            y &= 127;\r\n\r\n    // Calculate source address & line in tile\r\n    const u8* src_map = g_machine.VDP.name_table_address + ((y & 0xFFFFFFF8) * 8) + (2 * (32 - x_scroll));\r\n    int tile_line = (y & 0x07) * 8;\r\n\r\n    // Calculate position where vertical scrolling will be ignored\r\n    const int x_ignore_vscroll = (Right_No_Scroll) ? 23 : -1;\r\n\r\n    // Drawing loop\r\n    int tile_x = 0;\r\n    while (tile_x < 32)\r\n    {\r\n        // Part of Horizontal Line not refreshed in Game Gear mode\r\n        if ((g_driver->id != DRV_GG) || ((tile_x > 4) && (tile_x < 26)))\r\n        {\r\n            // Draw tile line\r\n            const u8 tile_attr = src_map[1];\r\n            const int tile_n = *((u16 *)src_map) & 511;\r\n            if (tgfx.Tile_Dirty [tile_n] & TILE_DIRTY_DECODE)\r\n            {\r\n                Decode_Tile(tile_n);\r\n                tgfx.Tile_Dirty [tile_n] = TILE_DIRTY_REDRAW;\r\n            }\r\n\r\n            const u16* tile_palette = (tile_attr & 0x08) ? &PIXEL_PALETTE_TABLE[16] : &PIXEL_PALETTE_TABLE[0];\r\n            const u8* tile_pixels = tgfx.Tile_Decoded[tile_n] + ((tile_attr & 0x04) ? (7 * 8) - tile_line : tile_line);\r\n\r\n            switch (tile_attr & 0x12)\r\n            {\r\n            case 0x00:\r\n                {\r\n                    // 0x00 - Not Flipped - Background Tile\r\n                    dst_buf[0] = tile_palette[tile_pixels[0]];\r\n                    dst_buf[1] = tile_palette[tile_pixels[1]];\r\n                    dst_buf[2] = tile_palette[tile_pixels[2]];\r\n                    dst_buf[3] = tile_palette[tile_pixels[3]];\r\n                    dst_buf[4] = tile_palette[tile_pixels[4]];\r\n                    dst_buf[5] = tile_palette[tile_pixels[5]];\r\n                    dst_buf[6] = tile_palette[tile_pixels[6]];\r\n                    dst_buf[7] = tile_palette[tile_pixels[7]];\r\n                    ((int *)sprite_mask)[0] = 0;\r\n                    ((int *)sprite_mask)[1] = 0;\r\n                    break;\r\n                }\r\n            case 0x02:\r\n                {\r\n                    // 0x02 -  X Flipped - Background Tile\r\n                    dst_buf[0] = tile_palette[tile_pixels[7]];\r\n                    dst_buf[1] = tile_palette[tile_pixels[6]];\r\n                    dst_buf[2] = tile_palette[tile_pixels[5]];\r\n                    dst_buf[3] = tile_palette[tile_pixels[4]];\r\n                    dst_buf[4] = tile_palette[tile_pixels[3]];\r\n                    dst_buf[5] = tile_palette[tile_pixels[2]];\r\n                    dst_buf[6] = tile_palette[tile_pixels[1]];\r\n                    dst_buf[7] = tile_palette[tile_pixels[0]];\r\n                    ((int *)sprite_mask)[0] = 0;\r\n                    ((int *)sprite_mask)[1] = 0;\r\n                    break;\r\n                }\r\n            case 0x10:\r\n                {\r\n                    // 0x10 - Not Flipped - Foreground Tile\r\n                    int color;\r\n                    color = tile_pixels[0]; dst_buf[0] = tile_palette[color]; sprite_mask[0] = (color ? 1 : 0);\r\n                    color = tile_pixels[1]; dst_buf[1] = tile_palette[color]; sprite_mask[1] = (color ? 1 : 0);\r\n                    color = tile_pixels[2]; dst_buf[2] = tile_palette[color]; sprite_mask[2] = (color ? 1 : 0);\r\n                    color = tile_pixels[3]; dst_buf[3] = tile_palette[color]; sprite_mask[3] = (color ? 1 : 0);\r\n                    color = tile_pixels[4]; dst_buf[4] = tile_palette[color]; sprite_mask[4] = (color ? 1 : 0);\r\n                    color = tile_pixels[5]; dst_buf[5] = tile_palette[color]; sprite_mask[5] = (color ? 1 : 0);\r\n                    color = tile_pixels[6]; dst_buf[6] = tile_palette[color]; sprite_mask[6] = (color ? 1 : 0);\r\n                    color = tile_pixels[7]; dst_buf[7] = tile_palette[color]; sprite_mask[7] = (color ? 1 : 0);\r\n                    break;\r\n                }\r\n            case 0x12:\r\n                {\r\n                    // 0x12 - X Flipped - Foreground Tile\r\n                    int color;\r\n                    color = tile_pixels[7]; dst_buf[0] = tile_palette[color]; sprite_mask[0] = (color ? 1 : 0);\r\n                    color = tile_pixels[6]; dst_buf[1] = tile_palette[color]; sprite_mask[1] = (color ? 1 : 0);\r\n                    color = tile_pixels[5]; dst_buf[2] = tile_palette[color]; sprite_mask[2] = (color ? 1 : 0);\r\n                    color = tile_pixels[4]; dst_buf[3] = tile_palette[color]; sprite_mask[3] = (color ? 1 : 0);\r\n                    color = tile_pixels[3]; dst_buf[4] = tile_palette[color]; sprite_mask[4] = (color ? 1 : 0);\r\n                    color = tile_pixels[2]; dst_buf[5] = tile_palette[color]; sprite_mask[5] = (color ? 1 : 0);\r\n                    color = tile_pixels[1]; dst_buf[6] = tile_palette[color]; sprite_mask[6] = (color ? 1 : 0);\r\n                    color = tile_pixels[0]; dst_buf[7] = tile_palette[color]; sprite_mask[7] = (color ? 1 : 0);\r\n                    break;\r\n                }\r\n            } // switch\r\n        }\r\n\r\n        if (tile_x == x_ignore_vscroll)\r\n        {\r\n            //if (Wide_Screen_28)\r\n            //{\r\n            //    src_map = g_machine.VDP.name_table_address + (((tsms.VDP_Line - 32) & 0xFFFFFFF8) * 8) + ((2 * (32 - x_scroll + tile_x)) & 63);\r\n            //    tile_line = ((tsms.VDP_Line - 32) & 0x07) * 8;\r\n            //}\r\n            //else\r\n            //{\r\n                src_map = g_machine.VDP.name_table_address + ((tsms.VDP_Line & 0xFFFFFFF8) * 8) + ((2 * (32 - x_scroll + tile_x)) & 63);\r\n                tile_line = (tsms.VDP_Line & 0x07) * 8;\r\n            //}\r\n        }\r\n\r\n        if (++tile_x == x_scroll)\r\n        {\r\n            src_map -= (64 - 2);\r\n        }\r\n        else\r\n        {\r\n            src_map += 2;\r\n        }\r\n\r\n        dst_buf += 8;\r\n        sprite_mask += 8;\r\n        // x += 8 // It is not necessary to maintain 'x' in the loop\r\n    }\r\n}\r\n\r\n// PROCESS COLLISION FOR A SPRITE LINE ----------------------------------------\r\nINLINE void     Sprite_Collide_Line_C (byte *p_src, int x)\r\n{\r\n    int *       p_collision_table;\r\n\r\n    p_collision_table = &Sprites_Collision_Table [x];\r\n    if (p_src[0]) { if ((p_collision_table[0])++ > 0) goto collide; }\r\n    if (p_src[1]) { if ((p_collision_table[1])++ > 0) goto collide; }\r\n    if (p_src[2]) { if ((p_collision_table[2])++ > 0) goto collide; }\r\n    if (p_src[3]) { if ((p_collision_table[3])++ > 0) goto collide; }\r\n    if (p_src[4]) { if ((p_collision_table[4])++ > 0) goto collide; }\r\n    if (p_src[5]) { if ((p_collision_table[5])++ > 0) goto collide; }\r\n    if (p_src[6]) { if ((p_collision_table[6])++ > 0) goto collide; }\r\n    if (p_src[7]) { if ((p_collision_table[7])++ > 0) goto collide; }\r\n    return;\r\ncollide:\r\n    sms.VDP_Status |= VDP_STATUS_SpriteCollision;\r\n    Do_Collision = FALSE;\r\n}\r\n\r\n// PROCESS COLLISION FOR A DOUBLED SPRITE LINE --------------------------------\r\nINLINE void     Sprite_Collide_Line_Double (byte *p_src, int x)\r\n{\r\n    int *       p_collision_table;\r\n\r\n    p_collision_table = &Sprites_Collision_Table [x];\r\n    if (p_src[0]) { if ((p_collision_table[ 0])++ > 0 || (p_collision_table[ 1])++ > 0) goto collide; }\r\n    if (p_src[1]) { if ((p_collision_table[ 2])++ > 0 || (p_collision_table[ 3])++ > 0) goto collide; }\r\n    if (p_src[2]) { if ((p_collision_table[ 4])++ > 0 || (p_collision_table[ 5])++ > 0) goto collide; }\r\n    if (p_src[3]) { if ((p_collision_table[ 6])++ > 0 || (p_collision_table[ 7])++ > 0) goto collide; }\r\n    if (p_src[4]) { if ((p_collision_table[ 8])++ > 0 || (p_collision_table[ 9])++ > 0) goto collide; }\r\n    if (p_src[5]) { if ((p_collision_table[10])++ > 0 || (p_collision_table[11])++ > 0) goto collide; }\r\n    if (p_src[6]) { if ((p_collision_table[12])++ > 0 || (p_collision_table[13])++ > 0) goto collide; }\r\n    if (p_src[7]) { if ((p_collision_table[14])++ > 0 || (p_collision_table[15])++ > 0) goto collide; }\r\n    return;\r\ncollide:\r\n    sms.VDP_Status |= VDP_STATUS_SpriteCollision;\r\n    Do_Collision = FALSE;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Sprite_Draw_Line(const u8 *tile_line, int x)\r\n// Draw a sprite line (8 pixels)\r\n//-----------------------------------------------------------------------------\r\nINLINE void     Sprite_Draw_Line(const u8 *tile_line, int x)\r\n{\r\n    int             color;\r\n    PIXEL_TYPE *    dst;\r\n    u8 *            sprite_mask;\r\n\r\n    dst = &PIXEL_LINE_DST[x];\r\n    sprite_mask = &Sprites_Draw_Mask[x];\r\n\r\n    color = tile_line[0]; if (!sprite_mask[0] && color) dst[0] = PIXEL_PALETTE_TABLE[16 + color]; // Note: PIXEL_PALETTE_TABLE should be a table (not a pointer) so the +16 is free\r\n    color = tile_line[1]; if (!sprite_mask[1] && color) dst[1] = PIXEL_PALETTE_TABLE[16 + color];\r\n    color = tile_line[2]; if (!sprite_mask[2] && color) dst[2] = PIXEL_PALETTE_TABLE[16 + color];\r\n    color = tile_line[3]; if (!sprite_mask[3] && color) dst[3] = PIXEL_PALETTE_TABLE[16 + color];\r\n    color = tile_line[4]; if (!sprite_mask[4] && color) dst[4] = PIXEL_PALETTE_TABLE[16 + color];\r\n    color = tile_line[5]; if (!sprite_mask[5] && color) dst[5] = PIXEL_PALETTE_TABLE[16 + color];\r\n    color = tile_line[6]; if (!sprite_mask[6] && color) dst[6] = PIXEL_PALETTE_TABLE[16 + color];\r\n    color = tile_line[7]; if (!sprite_mask[7] && color) dst[7] = PIXEL_PALETTE_TABLE[16 + color];\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Sprite_Draw_Line_Double(const u8 *tile_line, int x)\r\n// Draw a sprite line where each pixel is repeated twice (8 -> 16 pixels)\r\n//-----------------------------------------------------------------------------\r\nINLINE void     Sprite_Draw_Line_Double(const u8 *tile_line, int x)\r\n{\r\n    int             color;\r\n    PIXEL_TYPE *    dst;\r\n    u8 *            sprite_mask;\r\n\r\n    dst  = &PIXEL_LINE_DST[x];\r\n    sprite_mask = &Sprites_Draw_Mask[x];\r\n\r\n    color = tile_line[0]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[ 0]) dst[ 0] = color; if (!sprite_mask[ 1]) dst[ 1] = color; }\r\n    color = tile_line[1]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[ 2]) dst[ 2] = color; if (!sprite_mask[ 3]) dst[ 3] = color; }\r\n    color = tile_line[2]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[ 4]) dst[ 4] = color; if (!sprite_mask[ 5]) dst[ 5] = color; }\r\n    color = tile_line[3]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[ 6]) dst[ 6] = color; if (!sprite_mask[ 7]) dst[ 7] = color; }\r\n    color = tile_line[4]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[ 8]) dst[ 8] = color; if (!sprite_mask[ 9]) dst[ 9] = color; }\r\n    color = tile_line[5]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[10]) dst[10] = color; if (!sprite_mask[11]) dst[11] = color; }\r\n    color = tile_line[6]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[12]) dst[12] = color; if (!sprite_mask[13]) dst[13] = color; }\r\n    color = tile_line[7]; if (color) { color = PIXEL_PALETTE_TABLE[16 + color]; if (!sprite_mask[14]) dst[14] = color; if (!sprite_mask[15]) dst[15] = color; }\r\n}\r\n\r\nvoid        Refresh_Sprites_5 (bool draw)\r\n{\r\n    // 1. Count the number of sprites to render on this line\r\n    {\r\n        // Calculate Sprite Height\r\n        int height = 8;\r\n        if (Sprites_Double)\r\n            height <<= 1;\r\n        if (Sprites_8x16)\r\n            height <<= 1;\r\n\r\n        Sprite_Last = 0;\r\n        Sprites_on_Line = 0;\r\n        if (Wide_Screen_28)\r\n            Find_Last_Sprite_Wide(height, tsms.VDP_Line);\r\n        else\r\n            Find_Last_Sprite(height, tsms.VDP_Line);\r\n\r\n        // Return if there's no sprite on this line\r\n        if (Sprites_on_Line == 0)\r\n            return;\r\n    }\r\n\r\n    // Check if we have or not to process sprite collisions\r\n    Do_Collision = (!(sms.VDP_Status & VDP_STATUS_SpriteCollision)\r\n        && (Sprites_on_Line > 1));\r\n\r\n    // If sprites do not have to be drawn, only update collisions\r\n    if (draw == FALSE)\r\n    {\r\n        // If we don't have to process collisions, there's no point to continue\r\n        if (Do_Collision == FALSE)\r\n            return;\r\n        // Setting value to 64+9 will never draw sprites (only update collisions)\r\n        // since sprites are drawn only if Sprites_On_Line < 9\r\n        Sprites_on_Line = 64 + 9;\r\n    }\r\n    // Draw all sprites on line if flickering is not enabled\r\n    else if (!(g_config.sprite_flickering & SPRITE_FLICKERING_ENABLED))\r\n    {\r\n        Sprites_on_Line = 0;\r\n    }\r\n\r\n    // Process all sprites in 224 (28*8) lines mode\r\n    // if (Wide_Screen_28)\r\n    //    Sprite_Last = 63;\r\n\r\n    // Clear Sprite Collision Table\r\n    if (Do_Collision)\r\n        memset(Sprites_Collision_Table_Start, 0, sizeof (int) * Sprites_Collision_Table_Len);\r\n\r\n    // 3. Draw sprites\r\n    {\r\n        int     x, y, n;\r\n        byte *  p_src;\r\n        int     j;\r\n        const u8 * spr_map = g_machine.VDP.sprite_attribute_table;\r\n        const u8 * spr_map_xn = &spr_map[0x80];\r\n        int     spr_map_xn_offset;\r\n        int     spr_map_n_mask = 0x01FF;\r\n\r\n        // Bit 0 of Register 5 and Bits 0-1 of Register 6 act as masks on the 315-5124\r\n        if (g_machine.VDP.model == VDP_MODEL_315_5124)\r\n        {\r\n            if ((sms.VDP[5] & 1) == 0)\r\n                spr_map_xn = &spr_map[0x00];\r\n            if ((sms.VDP[6] & 1) == 0)\r\n                spr_map_n_mask &= ~0x0080;\r\n            if ((sms.VDP[6] & 2) == 0)\r\n                spr_map_n_mask &= ~0x0040;\r\n            // FIXME: Should be the same, untested thought\r\n            spr_map_n_mask &= (~0x00C0) | ((sms.VDP[6] & 3) << 6);\r\n        }\r\n\r\n        // Now process actual sprites\r\n        switch (sms.VDP[1] & (1 | 2))\r\n        {\r\n        case 0: // 8x8 sprites\r\n            {\r\n                for (j = Sprite_Last; j >= 0; j --)\r\n                {\r\n                    // Fetch Y & clip\r\n                    y = spr_map[j];\r\n                    // if (y == 224) continue;\r\n                    if (y > 224) y -= 256;\r\n\r\n                    // Now Y will contains the sprite line to render\r\n                    y = tsms.VDP_Line - y - 1;\r\n                    if (y < 0 || y >= 8) continue;\r\n\r\n                    // Fetch N & X\r\n                    spr_map_xn_offset = j << 1;\r\n                    n = ((int)spr_map_xn [spr_map_xn_offset + 1] | g_machine.VDP.sprite_pattern_gen_index) & spr_map_n_mask;\r\n                    x = spr_map_xn [spr_map_xn_offset] - g_machine.VDP.sprite_shift_x;\r\n\r\n                    // Decode tile if it isn't decoded yet\r\n                    if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\r\n                    { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\r\n                    p_src = &tgfx.Tile_Decoded [n] [y << 3];\r\n\r\n                    // Process collision & draw\r\n                    if (Do_Collision)\r\n                        Sprite_Collide_Line(p_src, x);\r\n                    if (Sprites_on_Line-- < 9)\r\n                        Sprite_Draw_Line(p_src, x);\r\n                }\r\n            } break;\r\n        case 1: // 8x8 sprites zoomed\r\n            {\r\n                for (j = Sprite_Last; j >= 0; j --)\r\n                {\r\n                    // Fetch Y & clip\r\n                    y = spr_map[j];\r\n                    // if (y == 224) continue;\r\n                    if (y > 224) y -= 256;\r\n\r\n                    // Now Y will contains the sprite line to render\r\n                    y = tsms.VDP_Line - y - 1;\r\n                    if (y < 0 || y >= 16) continue;\r\n\r\n                    // Fetch N & X\r\n                    spr_map_xn_offset = j << 1;\r\n                    n = ((int)spr_map_xn [spr_map_xn_offset + 1] | g_machine.VDP.sprite_pattern_gen_index) & spr_map_n_mask;\r\n                    x = spr_map_xn [spr_map_xn_offset] - g_machine.VDP.sprite_shift_x;\r\n\r\n                    // Decode tile if it isn't decoded yet\r\n                    if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\r\n                    { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\r\n                    p_src = &tgfx.Tile_Decoded [n] [(y >> 1) << 3];\r\n\r\n                    // Process collision & draw\r\n                    if (Do_Collision)\r\n                        Sprite_Collide_Line_Double (p_src, x);\r\n                    if (Sprites_on_Line-- < 9)\r\n                        Sprite_Draw_Line_Double (p_src, x);\r\n                }\r\n            } break;\r\n        case 2: // 8x16 sprites\r\n            {\r\n                spr_map_n_mask &= ~0x01;\r\n                for (j = Sprite_Last; j >= 0; j --)\r\n                {\r\n                    // Fetch Y & clip\r\n                    y = spr_map[j];\r\n                    // if (y == 224) continue;\r\n                    if (y > 224) y -= 256;\r\n\r\n                    // Now Y will contains the sprite line to render\r\n                    y = tsms.VDP_Line - y - 1;\r\n                    if (y < 0 || y >= 16) continue;\r\n\r\n                    // Fetch N & X\r\n                    // Increase N on the sprite second tile\r\n                    spr_map_xn_offset = j << 1;\r\n                    n = ((int)spr_map_xn [spr_map_xn_offset + 1] | g_machine.VDP.sprite_pattern_gen_index) & spr_map_n_mask;\r\n                    if (y & 8) // >= 8\r\n                    {\r\n                        n ++;\r\n                        y &= 7;\r\n                    }\r\n                    x = spr_map_xn [spr_map_xn_offset] - g_machine.VDP.sprite_shift_x;\r\n\r\n                    // Decode tile if it isn't decoded yet\r\n                    if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\r\n                    { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\r\n                    p_src = &tgfx.Tile_Decoded [n] [y << 3];\r\n\r\n                    // Process collision & draw\r\n                    if (Do_Collision)\r\n                        Sprite_Collide_Line (p_src, x);\r\n                    if (Sprites_on_Line-- < 9)\r\n                        Sprite_Draw_Line(p_src, x);\r\n                }\r\n            } break;\r\n        case 3: // 8x16 sprites zoomed\r\n            {\r\n                spr_map_n_mask &= ~0x01;\r\n                for (j = Sprite_Last; j >= 0; j --)\r\n                {\r\n                    // Fetch Y & clip\r\n                    y = spr_map[j];\r\n                    // if (y == 224) continue;\r\n                    if (y > 224) y -= 256;\r\n\r\n                    // Now Y will contains the sprite line to render\r\n                    y = tsms.VDP_Line - y - 1;\r\n                    if (y < 0 || y >= 32) continue;\r\n\r\n                    // Fetch N & X\r\n                    // Increase N on the sprite second tile\r\n                    spr_map_xn_offset = j << 1;\r\n                    n = ((int)spr_map_xn [spr_map_xn_offset + 1] | g_machine.VDP.sprite_pattern_gen_index) & spr_map_n_mask;\r\n                    if (y & 16) // >= 16\r\n                    {\r\n                        n ++;\r\n                        y &= 15;\r\n                    }\r\n                    x = spr_map_xn [spr_map_xn_offset] - g_machine.VDP.sprite_shift_x;\r\n\r\n                    // Decode tile if it isn't decoded yet\r\n                    if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\r\n                    { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\r\n                    p_src = &tgfx.Tile_Decoded [n] [(y >> 1) << 3];\r\n\r\n                    // Process collision & draw\r\n                    if (Do_Collision)\r\n                        Sprite_Collide_Line_Double (p_src, x);\r\n                    if (Sprites_on_Line-- < 9)\r\n                        Sprite_Draw_Line_Double (p_src, x);\r\n                }\r\n            } break;\r\n        } // end of switch\r\n\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/video_m5.h",
    "content": "//-----------------------------------------------------------------------------\n// Meka - video_m5.h\n// SMS/GG Video Mode Rendering - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid    Decode_Tile_C (int, byte *);\nvoid    Sprite_Collide_Line_C (byte *p_src, int x);\n\nvoid    Find_Last_Sprite(int sprites_height, int VDP_Line);\nvoid    Find_Last_Sprite_Wide(int sprites_height, int VDP_Line);\n\nvoid    Display_BackGround_Line_5();\n\nextern \"C\"\n{\nextern int      Sprite_Last;\nextern int      Sprites_on_Line;\n}\n\nvoid            Refresh_Line_5();\nvoid            Refresh_Sprites_5(bool draw);\n\n//-----------------------------------------------------------------------------\n\nvoid            VDP_Mode4_DrawTile(ALLEGRO_BITMAP *dst, ALLEGRO_LOCKED_REGION* dst_region, const u8 *pixels, const u32 *palette_host, int x, int y, int flip);\n\n//-----------------------------------------------------------------------------\n"
  },
  {
    "path": "meka/srcs/video_sp.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - VIDEO_SP.C\n// SMS/GG Sprite Drawing - Code\n//-----------------------------------------------------------------------------\n// Note:\n//   ** THIS FILE IS INCLUDED TWICE FROM VIDEO_M5.C **\n//   It was made this way because it uses macros that enable/disable\n//   certains checks depending on screen size\n//-----------------------------------------------------------------------------\n\n int    line;\n byte * p_src;\n\n // Now parse the actual sprites ----------------------------------------------\n switch (sms.VDP[1] & (1 + 2))\n   {\n   case 0: // 8x8 sprites\n     {\n     for (j = Sprite_Last; j >= 0; j --)\n         {\n         y = SPR_AREA [j];\n         #ifndef WIDE_SCREEN_28\n           // if (y == 224) continue;\n           if (y > 224) y -= 256;\n         #endif\n         line = tsms.VDP_Line - y - 1;\n         if (line < 0 || line >= 8) continue;\n         Addr_Sprite = 0x80 + (j * 2);\n         n = SPR_AREA [Addr_Sprite + 1] | tgfx.Base_Sprite;\n         x = SPR_AREA [Addr_Sprite] - Sprite_Shift_X;\n         if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\n            { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\n         p_src = &tgfx.Tile_Decoded [n] [line * 8];\n         if (Do_Collision)\n            Sprite_Collide_Line (p_src, x);\n         if (Sprites_on_Line < 9)\n            Sprite_Draw_Line (p_src, x);\n         Sprites_on_Line --;\n         }\n     } break;\n   case 1: // 8x8 sprites zoomed\n     {\n     for (j = Sprite_Last; j >= 0; j --)\n         {\n         y = SPR_AREA [j];\n         #ifndef WIDE_SCREEN_28\n           // if (y == 224) continue;\n           if (y > 224) y -= 256;\n         #endif\n         line = tsms.VDP_Line - y - 1;\n         if (line < 0 || line >= 16) continue;\n         Addr_Sprite = 0x80 + (j * 2);\n         n = SPR_AREA [Addr_Sprite + 1] | tgfx.Base_Sprite;\n         x = SPR_AREA [Addr_Sprite] - Sprite_Shift_X;\n         if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\n            { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\n         p_src = &tgfx.Tile_Decoded [n] [(line / 2) * 8];\n         if (Do_Collision)\n            Sprite_Collide_Line_Double (p_src, x);\n         if (Sprites_on_Line < 9)\n            Sprite_Draw_Line_Double (p_src, x);\n         Sprites_on_Line --;\n         }\n     } break;\n   case 2: // 8x16 sprites\n     {\n     for (j = Sprite_Last; j >= 0; j --)\n         {\n         y = SPR_AREA [j];\n         #ifndef WIDE_SCREEN_28\n           // if (y == 224) continue;\n           if (y > 224) y -= 256;\n         #endif\n         line = tsms.VDP_Line - y - 1;\n         if (line < 0 || line >= 16) continue;\n         Addr_Sprite = 0x80 + (j * 2);\n         n = (SPR_AREA [Addr_Sprite + 1] & 0xFE) | tgfx.Base_Sprite;\n         if (line >= 8)\n            {\n            n ++;\n            line -= 8;\n            y += 8;\n            }\n         x = SPR_AREA [Addr_Sprite] - Sprite_Shift_X;\n         if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\n            { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\n         p_src = &tgfx.Tile_Decoded [n] [line * 8];\n         if (Do_Collision)\n            Sprite_Collide_Line (p_src, x);\n         if (Sprites_on_Line < 9)\n            Sprite_Draw_Line (p_src, x);\n         Sprites_on_Line --;\n         }\n     } break;\n   case 3: // 8x16 sprites zoomed\n     {\n     for (j = Sprite_Last; j >= 0; j --)\n         {\n         y = SPR_AREA [j];\n         #ifndef WIDE_SCREEN_28\n           // if (y == 224) continue;\n           if (y > 224) y -= 256;\n         #endif\n         line = tsms.VDP_Line - y - 1;\n         if (line < 0 || line >= 32) continue;\n         Addr_Sprite = 0x80 + (j * 2);\n         n = (SPR_AREA [Addr_Sprite + 1] & 0xFE) | tgfx.Base_Sprite;\n         if (line >= 16)\n            {\n            n ++;\n            line -= 16;\n            y += 16;\n            }\n         x = SPR_AREA [Addr_Sprite] - Sprite_Shift_X;\n         if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)\n            { Decode_Tile (n); tgfx.Tile_Dirty [n] = TILE_DIRTY_REDRAW; }\n         p_src = &tgfx.Tile_Decoded [n] [(line / 2) * 8];\n         if (Do_Collision)\n            Sprite_Collide_Line_Double (p_src, x);\n         if (Sprites_on_Line < 9)\n            Sprite_Draw_Line_Double (p_src, x);\n         Sprites_on_Line --;\n         }\n     } break;\n   } // end of switch\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/video_t.cpp",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - video_t.c\n// Video Mode Calculated Tables - Code\n//-----------------------------------------------------------------------------\n\n#include \"shared.h\"\n\n//-----------------------------------------------------------------------------\n\nbyte    Table_Mode_0 [16 * 256 * 8]; // 32 kb\n\n// INITIALIZE TABLE FOR VIDEO MODE 0 REFRESH ----------------------------------\nvoid    Init_Table_Video_Mode_0 (void)\n{\n byte * p;\n int    i, j;\n\n p = Table_Mode_0;\n\n for (i = 0; i < 16; i ++)\n     for (j = 0; j < 256; j ++)\n         {\n         *p++ = (j & 128) ? i : 0;\n         *p++ = (j &  64) ? i : 0;\n         *p++ = (j &  32) ? i : 0;\n         *p++ = (j &  16) ? i : 0;\n         *p++ = (j &   8) ? i : 0;\n         *p++ = (j &   4) ? i : 0;\n         *p++ = (j &   2) ? i : 0;\n         *p++ = (j &   1) ? i : 0;\n         }\n}\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/vlfn.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - vlfn.c\r\n// User filenames DB - Code\r\n//-----------------------------------------------------------------------------\r\n// FIXME: rename from vlfn.* to something else?\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"app_filebrowser.h\"\r\n#include \"db.h\"\r\n#include \"vlfn.h\"\r\n#include \"libparse.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nt_vlfn_db VLFN_DataBase;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic t_vlfn_entry *   VLFN_Entry_New(const char *file_name, t_db_entry *db_entry);\r\nstatic void             VLFN_Entry_Delete(t_vlfn_entry *entry);\r\n\r\nstatic void             VLFN_DataBase_Load();\r\nstatic void             VLFN_DataBase_Save();\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid            VLFN_Init()\r\n{\r\n    VLFN_DataBase.entries = NULL;\r\n    VLFN_DataBase_Load();\r\n}\r\n\r\nvoid            VLFN_Close()\r\n{\r\n    VLFN_DataBase_Save();\r\n}\r\n\r\nstatic t_vlfn_entry *   VLFN_Entry_New (const char *file_name, t_db_entry *db_entry)\r\n{\r\n    t_vlfn_entry *entry;\r\n    entry = (t_vlfn_entry *)malloc(sizeof (t_vlfn_entry));\r\n    entry->filename = (char *)file_name;\r\n    entry->db_entry = db_entry;\r\n    return (entry);\r\n}\r\n\r\nstatic void      VLFN_Entry_Delete(t_vlfn_entry *entry)\r\n{\r\n    free (entry->filename);\r\n    free (entry);\r\n}\r\n\r\nstatic int       VLFN_Entries_Compare(t_vlfn_entry *entry1, t_vlfn_entry *entry2)\r\n{\r\n    return (strcmp(entry1->filename, entry2->filename));\r\n}\r\n\r\n// Load VLFN database from MEKA.FDB file.\r\nvoid            VLFN_DataBase_Load()\r\n{\r\n    t_tfile *   tf;\r\n    t_list *    lines;\r\n    char *      line;\r\n    int         line_cnt;\r\n\r\n    ConsolePrint(Msg_Get(MSG_FDB_Loading));\r\n\r\n    // Open and read file\r\n    tf = tfile_read (VLFN_DataBase.filename);\r\n    if (tf == NULL)\r\n    {\r\n        ConsolePrintf (\"%s\\n\", meka_strerror());\r\n        return;\r\n    }\r\n\r\n    // Ok\r\n    ConsolePrint(\"\\n\");\r\n\r\n    // Parse each line\r\n    line_cnt = 0;\r\n    for (lines = tf->data_lines; lines; lines = lines->next)\r\n    {\r\n        line_cnt += 1;\r\n        line = (char*)lines->elem;\r\n\r\n        char* w = parse_getword(NULL, 0, &line, \"/\", ';', PARSE_FLAGS_NONE);\r\n        if (w == NULL)\r\n            continue;\r\n        else\r\n        {\r\n            char            buf[1024];\r\n            char *          file_name;\r\n            u32             crc_crc32;\r\n            t_meka_crc      crc_mekacrc;\r\n\r\n            // Save allocated filename\r\n            file_name = w;\r\n\r\n            // Get CRCs\r\n            crc_crc32 = 0;\r\n            crc_mekacrc.v[0] = crc_mekacrc.v[1] = 0;\r\n            while ((w = parse_getword(buf, 1024, &line, \"/\", ';', PARSE_FLAGS_NONE)) != NULL)\r\n            {\r\n                if (!strncmp(w, \"MEKACRC:\", 8))\r\n                {\r\n                    if (sscanf(w + 8, \"%08X%08X\", &crc_mekacrc.v[0], &crc_mekacrc.v[1]) != 2)\r\n                        continue; // Syntax error\r\n                }\r\n                else if (!strncmp(w, \"CRC32:\", 6))\r\n                {\r\n                    if (sscanf(w + 6, \"%08x\", &crc_crc32) != 1)\r\n                        continue; // Syntax error\r\n                }\r\n            }\r\n\r\n            // Requires at least MekaCRC\r\n            // (to be changed by CRC32 when MekaCRC is dropped)\r\n            if (crc_mekacrc.v[0] == 0 && crc_mekacrc.v[1] == 0)\r\n                continue;\r\n\r\n            {\r\n                // Find DB entry\r\n                t_db_entry *db_entry = DB_Entry_Find (crc_crc32, &crc_mekacrc);\r\n                if (db_entry)\r\n                {\r\n                    // Create VLFN entry\r\n                    t_vlfn_entry *  entry;\r\n                    entry = VLFN_Entry_New (file_name, db_entry);\r\n                    list_add (&VLFN_DataBase.entries, entry);\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    // Free file data\r\n    tfile_free(tf);\r\n}\r\n\r\n// Save VLFN database back to MEKA.FDB file.\r\nvoid        VLFN_DataBase_Save()\r\n{\r\n    FILE *  f;\r\n    t_list *list;\r\n\r\n    if ((f = fopen(VLFN_DataBase.filename, \"wt\")) == 0)\r\n        return; // FIXME: report that somewhere ?\r\n\r\n    // Sort entries by file name before writing, so the output file is more sexy\r\n    list_sort (&VLFN_DataBase.entries, (int (*)(void *, void *))VLFN_Entries_Compare);\r\n\r\n    // Write header\r\n    fprintf(f, \";-----------------------------------------------------------------------------\\n\");\r\n    fprintf(f, \"; \" MEKA_NAME \" \" MEKA_VERSION \" - User Filenames DataBase\\n\");\r\n    fprintf(f, \"; Associate user filenames with MEKA DataBase entries.\\n\");\r\n    fprintf(f, \"; This information is used by the file loader.\\n\");\r\n    fprintf(f, \"; This file is automatically updated and rewritten by the emulator.\\n\");\r\n    fprintf(f, \";-----------------------------------------------------------------------------\\n\\n\");\r\n\r\n    // Write all entries\r\n    for (list = VLFN_DataBase.entries; list != NULL; list = list->next)\r\n    {\r\n        t_vlfn_entry* entry     = (t_vlfn_entry*)list->elem;\r\n        t_db_entry* db_entry    = entry->db_entry;\r\n        fprintf(f, \"%s\", entry->filename);\r\n        if (db_entry->crc_crc32 != 0)\r\n            fprintf(f, \"/CRC32:%08x\", db_entry->crc_crc32);\r\n        // Note: MekaCRC is always written now!\r\n        fprintf(f, \"/MEKACRC:%08X%08X\\n\", db_entry->crc_mekacrc.v[0], db_entry->crc_mekacrc.v[1]);\r\n    }\r\n\r\n    fprintf(f, \"\\n;-----------------------------------------------------------------------------\\n\\n\");\r\n\r\n    // Close write\r\n    fclose (f);\r\n\r\n    // Free all entries\r\n    list_free_custom (&VLFN_DataBase.entries, (t_list_free_handler)VLFN_Entry_Delete);\r\n}\r\n\r\n// Retrieve VLFN entry from filename.\r\nt_vlfn_entry *  VLFN_FindByFileName(const char *file_name)\r\n{\r\n    // Linear find\r\n    for (t_list* list = VLFN_DataBase.entries; list != NULL; list = list->next)\r\n    {\r\n        t_vlfn_entry* entry = (t_vlfn_entry*)list->elem;\r\n        if (!stricmp (file_name, entry->filename))\r\n            return (entry);\r\n    }\r\n    return (NULL);\r\n}\r\n\r\nvoid        VLFN_AddEntry(const char *file_name, t_db_entry *db_entry)\r\n{\r\n    t_vlfn_entry *entry;\r\n\r\n    entry = VLFN_FindByFileName (file_name);\r\n    if (entry)\r\n    {\r\n        // Update existing entry\r\n        entry->db_entry = db_entry;\r\n    }\r\n    else\r\n    {\r\n        // Add new entry\r\n        entry = VLFN_Entry_New (strdup (file_name), db_entry);\r\n        list_add (&VLFN_DataBase.entries, entry);\r\n    }\r\n}\r\n\r\nvoid        VLFN_RemoveEntry(const char *file_name)\r\n{\r\n    t_vlfn_entry *entry = VLFN_FindByFileName (file_name);\r\n    if (entry != NULL)\r\n    {\r\n        // Delete and remove from list\r\n        list_remove(&VLFN_DataBase.entries, entry);\r\n        VLFN_Entry_Delete(entry);\r\n\r\n        // Ask file browser to reload names\r\n        FB_Reload_Names();\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/vlfn.h",
    "content": "//-----------------------------------------------------------------------------\n// MEKA - vlfn.h\n// User filenames DB - Headers\n//-----------------------------------------------------------------------------\n\n//-----------------------------------------------------------------------------\n// Data\n//-----------------------------------------------------------------------------\n\nstruct t_vlfn_entry\n{\n    char *      filename;\n    t_db_entry *db_entry;\n};\n\nstruct t_vlfn_db\n{\n    char        filename [FILENAME_LEN];\n    t_list *    entries;\n};\n\nextern t_vlfn_db VLFN_DataBase;\n\n//-----------------------------------------------------------------------------\n// Functions\n//-----------------------------------------------------------------------------\n\nvoid            VLFN_Init           ();\nvoid            VLFN_Close          ();\n\nt_vlfn_entry *  VLFN_FindByFileName (const char *file_name);\nvoid            VLFN_AddEntry       (const char *file_name, t_db_entry *db_entry);\nvoid            VLFN_RemoveEntry    (const char *file_name);\n\n//-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "meka/srcs/vmachine.cpp",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - vmachine.c\r\n// Virtual Machine - Code\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"vmachine.h\"\r\n#include \"app_game.h\"\r\n#include \"bios.h\"\r\n#include \"db.h\"\r\n#include \"file.h\"\r\n#include \"effects.h\"\r\n#include \"skin_bg.h\"\r\n\r\n//-----------------------------------------------------------------------------\r\n// Data\r\n//-----------------------------------------------------------------------------\r\n\r\nint     g_machine_flags = 0;\r\n\r\n//-----------------------------------------------------------------------------\r\n// Functions\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid    VMachine_Draw()\r\n{\r\n    int    x, y;\r\n\r\n    #ifdef DEBUG_WHOLE\r\n        Msg(MSGT_DEBUG, \"VMachine_Draw();\");\r\n    #endif\r\n\r\n    x = gui.info.screen.x;\r\n    y = 0;\r\n    al_set_target_bitmap(gui_background);\r\n    switch (g_driver->id)\r\n    {\r\n    case DRV_COLECO: //-------------- Draw a Colecovision ---------------------\r\n        x += VMACHINE_COLECO_POS_X;\r\n        y += VMACHINE_COLECO_POS_Y;\r\n        al_draw_bitmap(Graphics.Machines.ColecoVision, x, y, 0);\r\n        break;\r\n    default: //---------------------- Draw a Master System --------------------\r\n        x += VMACHINE_SMS_POS_X;\r\n        y += VMACHINE_SMS_POS_Y;\r\n        al_draw_bitmap(Graphics.Machines.MasterSystem, x, y, 0);\r\n        if (g_machine_flags & MACHINE_POWER_ON)\r\n        {\r\n            al_draw_bitmap(Graphics.Machines.MasterSystem_Light, x + VMACHINE_SMS_LIGHT_POS_X, y + VMACHINE_SMS_LIGHT_POS_Y, 0);\r\n        }\r\n        if (g_machine_flags & MACHINE_CART_INSERTED)\r\n        {\r\n            al_draw_bitmap(Graphics.Machines.MasterSystem_Cart, x + VMACHINE_SMS_CART_POS_X, y + VMACHINE_SMS_CART_POS_Y, 0);\r\n        }\r\n        break;\r\n    }\r\n}\r\n\r\nvoid    Machine_Init()\r\n{\r\n    g_machine_flags = 0;\r\n}\r\n\r\nvoid    Machine_ON()\r\n{\r\n#ifdef DEBUG_WHOLE\r\n    Msg(MSGT_DEBUG, \"Machine_ON()\");\r\n#endif\r\n    if (!(g_machine_flags & MACHINE_POWER_ON))\r\n    {\r\n        g_machine_flags |= MACHINE_POWER_ON;\r\n        CPU_Loop_Stop = TRUE;\r\n        Machine_Reset();\r\n        if (!(g_machine_flags & MACHINE_ROM_LOADED))\r\n        {\r\n#ifdef DEBUG_WHOLE\r\n            Msg(MSGT_DEBUG, \"Machine_ON() : BIOS_Load()\");\r\n#endif\r\n            BIOS_Load();\r\n            Machine_Remove_Cartridge();\r\n        }\r\n        Skins_Background_Redraw();\r\n    }\r\n}\r\n\r\nvoid    Machine_OFF()\r\n{\r\n    if (g_machine_flags & MACHINE_POWER_ON)\r\n    {\r\n        BMemory_Save();\r\n        g_machine_flags &= ~MACHINE_POWER_ON;   // Switch power Off\r\n        CPU_Loop_Stop = TRUE;                   // Setup flag to stop Z80 emulation\r\n        Machine_Reset();\r\n        Skins_Background_Redraw();\r\n        //effects.TV_Start_Line = 0;\r\n        Effects_TV_Reset();\r\n    }\r\n}\r\n\r\nvoid    Machine_Insert_Cartridge()\r\n{\r\n    g_machine_flags |= MACHINE_CART_INSERTED;\r\n    Skins_Background_Redraw();\r\n}\r\n\r\nvoid    Machine_Remove_Cartridge()\r\n{\r\n    if (g_machine_flags & MACHINE_CART_INSERTED)\r\n    {\r\n        memset (Game_ROM, 0, tsms.Size_ROM);\r\n    }\r\n    g_machine_flags &= ~MACHINE_CART_INSERTED;\r\n    Skins_Background_Redraw();\r\n}\r\n\r\nvoid    Free_ROM()\r\n{\r\n    // Call BMemory_Save() only if Machine_Off() won't call it\r\n    // FIXME: this is some crap hack, the whole machine thing need to be rewritten\r\n    if (!(g_machine_flags & MACHINE_POWER_ON))\r\n        BMemory_Save();\r\n    Machine_OFF();\r\n    Machine_Remove_Cartridge();\r\n    g_machine_flags = 0;\r\n    if (Game_ROM)\r\n    {\r\n        free (Game_ROM);\r\n        Game_ROM = NULL;\r\n        tsms.Size_ROM = 0;\r\n        DB.current_entry = NULL;\r\n        BIOS_Load();\r\n    }\r\n    if (g_machine.driver_id != DRV_COLECO)\r\n        g_machine.driver_id = DRV_SMS;\r\n    Machine_Reset();\r\n    gamebox_rename_all();\r\n    Change_System_Misc();\r\n\r\n    // Clear filename data\r\n    strcpy(g_env.Paths.MediaImageFile, \"\");\r\n    Filenames_Init_ROM();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/srcs/vmachine.h",
    "content": "//-----------------------------------------------------------------------------\r\n// MEKA - vmachine.h\r\n// Virtual Machine - Headers\r\n//-----------------------------------------------------------------------------\r\n\r\n// Machine Positions ----------------------------------------------------------\r\n// - machine are relative to (Xmax, 0)\r\n// - machine subparts are relative to the machine itself\r\n#define VMACHINE_SMS_POS_X           (-338)\r\n#define VMACHINE_SMS_POS_Y           (+28)\r\n#define VMACHINE_SMS_CART_POS_X      (+160)\r\n#define VMACHINE_SMS_CART_POS_Y      (+0)\r\n#define VMACHINE_SMS_LIGHT_POS_X     (+151)\r\n#define VMACHINE_SMS_LIGHT_POS_Y     (+49)\r\n#define VMACHINE_COLECO_POS_X        (-320)\r\n#define VMACHINE_COLECO_POS_Y        (+42)\r\n\r\n// Status Simulation ----------------------------------------------------------\r\nvoid    Free_ROM();\r\nvoid    Machine_ON();\r\nvoid    Machine_OFF();\r\nvoid    Machine_Init();\r\nvoid    Machine_Insert_Cartridge();\r\nvoid    Machine_Remove_Cartridge();\r\n\r\n// Graphics -------------------------------------------------------------------\r\nvoid    VMachine_Draw();\r\nvoid    VMachine_Init_Colors();\r\n\r\nextern int g_machine_flags;\r\n\r\n#define MACHINE_POWER_ON        (1 << 0)\r\n#define MACHINE_CART_INSERTED   (1 << 1)\r\n#define MACHINE_ROM_LOADED      (1 << 2)\r\n#define MACHINE_NOT_IN_BIOS     (1 << 3)\r\n#define MACHINE_PAUSED          (1 << 4)\r\n#define MACHINE_DEBUGGING       (1 << 5)\r\n\r\n#define MACHINE_RUN             (MACHINE_POWER_ON | MACHINE_CART_INSERTED | MACHINE_ROM_LOADED)\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Codes.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                          Codes.h                        **/\r\n/**                                                         **/\r\n/** This file contains implementation for the main table of **/\r\n/** Z80 commands. It is included from Z80.c.                **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\ncase JR_NZ:   if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;\r\ncase JR_NC:   if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;\r\ncase JR_Z:    if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;\r\ncase JR_C:    if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;\r\n\r\ncase JP_NZ:   if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;\r\ncase JP_NC:   if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;\r\ncase JP_PO:   if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;\r\ncase JP_P:    if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;\r\ncase JP_Z:    if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;\r\ncase JP_C:    if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;\r\ncase JP_PE:   if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;\r\ncase JP_M:    if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;\r\n\r\ncase RET_NZ:  if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_NC:  if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_PO:  if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_P:   if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_Z:   if(R->AF.B.l&Z_FLAG)    { R->ICount-=6;M_RET; } break;\r\ncase RET_C:   if(R->AF.B.l&C_FLAG)    { R->ICount-=6;M_RET; } break;\r\ncase RET_PE:  if(R->AF.B.l&P_FLAG)    { R->ICount-=6;M_RET; } break;\r\ncase RET_M:   if(R->AF.B.l&S_FLAG)    { R->ICount-=6;M_RET; } break;\r\n\r\ncase CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_P:  if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_Z:  if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\ncase CALL_C:  if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\ncase CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\ncase CALL_M:  if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\n\r\ncase ADD_B:    M_ADD(R->BC.B.h);break;\r\ncase ADD_C:    M_ADD(R->BC.B.l);break;\r\ncase ADD_D:    M_ADD(R->DE.B.h);break;\r\ncase ADD_E:    M_ADD(R->DE.B.l);break;\r\ncase ADD_H:    M_ADD(R->HL.B.h);break;\r\ncase ADD_L:    M_ADD(R->HL.B.l);break;\r\ncase ADD_A:    M_ADD(R->AF.B.h);break;\r\ncase ADD_xHL:  I=RdZ80(R->HL.W);M_ADD(I);break;\r\ncase ADD_BYTE: I=RdZ80(R->PC.W++);M_ADD(I);break;\r\n\r\ncase SUB_B:    M_SUB(R->BC.B.h);break;\r\ncase SUB_C:    M_SUB(R->BC.B.l);break;\r\ncase SUB_D:    M_SUB(R->DE.B.h);break;\r\ncase SUB_E:    M_SUB(R->DE.B.l);break;\r\ncase SUB_H:    M_SUB(R->HL.B.h);break;\r\ncase SUB_L:    M_SUB(R->HL.B.l);break;\r\ncase SUB_A:    R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;\r\ncase SUB_xHL:  I=RdZ80(R->HL.W);M_SUB(I);break;\r\ncase SUB_BYTE: I=RdZ80(R->PC.W++);M_SUB(I);break;\r\n\r\ncase AND_B:    M_AND(R->BC.B.h);break;\r\ncase AND_C:    M_AND(R->BC.B.l);break;\r\ncase AND_D:    M_AND(R->DE.B.h);break;\r\ncase AND_E:    M_AND(R->DE.B.l);break;\r\ncase AND_H:    M_AND(R->HL.B.h);break;\r\ncase AND_L:    M_AND(R->HL.B.l);break;\r\ncase AND_A:    M_AND(R->AF.B.h);break;\r\ncase AND_xHL:  I=RdZ80(R->HL.W);M_AND(I);break;\r\ncase AND_BYTE: I=RdZ80(R->PC.W++);M_AND(I);break;\r\n\r\ncase OR_B:     M_OR(R->BC.B.h);break;\r\ncase OR_C:     M_OR(R->BC.B.l);break;\r\ncase OR_D:     M_OR(R->DE.B.h);break;\r\ncase OR_E:     M_OR(R->DE.B.l);break;\r\ncase OR_H:     M_OR(R->HL.B.h);break;\r\ncase OR_L:     M_OR(R->HL.B.l);break;\r\ncase OR_A:     M_OR(R->AF.B.h);break;\r\ncase OR_xHL:   I=RdZ80(R->HL.W);M_OR(I);break;\r\ncase OR_BYTE:  I=RdZ80(R->PC.W++);M_OR(I);break;\r\n\r\ncase ADC_B:    M_ADC(R->BC.B.h);break;\r\ncase ADC_C:    M_ADC(R->BC.B.l);break;\r\ncase ADC_D:    M_ADC(R->DE.B.h);break;\r\ncase ADC_E:    M_ADC(R->DE.B.l);break;\r\ncase ADC_H:    M_ADC(R->HL.B.h);break;\r\ncase ADC_L:    M_ADC(R->HL.B.l);break;\r\ncase ADC_A:    M_ADC(R->AF.B.h);break;\r\ncase ADC_xHL:  I=RdZ80(R->HL.W);M_ADC(I);break;\r\ncase ADC_BYTE: I=RdZ80(R->PC.W++);M_ADC(I);break;\r\n\r\ncase SBC_B:    M_SBC(R->BC.B.h);break;\r\ncase SBC_C:    M_SBC(R->BC.B.l);break;\r\ncase SBC_D:    M_SBC(R->DE.B.h);break;\r\ncase SBC_E:    M_SBC(R->DE.B.l);break;\r\ncase SBC_H:    M_SBC(R->HL.B.h);break;\r\ncase SBC_L:    M_SBC(R->HL.B.l);break;\r\ncase SBC_A:    M_SBC(R->AF.B.h);break;\r\ncase SBC_xHL:  I=RdZ80(R->HL.W);M_SBC(I);break;\r\ncase SBC_BYTE: I=RdZ80(R->PC.W++);M_SBC(I);break;\r\n\r\ncase XOR_B:    M_XOR(R->BC.B.h);break;\r\ncase XOR_C:    M_XOR(R->BC.B.l);break;\r\ncase XOR_D:    M_XOR(R->DE.B.h);break;\r\ncase XOR_E:    M_XOR(R->DE.B.l);break;\r\ncase XOR_H:    M_XOR(R->HL.B.h);break;\r\ncase XOR_L:    M_XOR(R->HL.B.l);break;\r\ncase XOR_A:    R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;\r\ncase XOR_xHL:  I=RdZ80(R->HL.W);M_XOR(I);break;\r\ncase XOR_BYTE: I=RdZ80(R->PC.W++);M_XOR(I);break;\r\n\r\ncase CP_B:     M_CP(R->BC.B.h);break;\r\ncase CP_C:     M_CP(R->BC.B.l);break;\r\ncase CP_D:     M_CP(R->DE.B.h);break;\r\ncase CP_E:     M_CP(R->DE.B.l);break;\r\ncase CP_H:     M_CP(R->HL.B.h);break;\r\ncase CP_L:     M_CP(R->HL.B.l);break;\r\ncase CP_A:     R->AF.B.l=N_FLAG|Z_FLAG;break;\r\ncase CP_xHL:   I=RdZ80(R->HL.W);M_CP(I);break;\r\ncase CP_BYTE:  I=RdZ80(R->PC.W++);M_CP(I);break;\r\n\r\ncase LD_BC_WORD: M_LDWORD(BC);break;\r\ncase LD_DE_WORD: M_LDWORD(DE);break;\r\ncase LD_HL_WORD: M_LDWORD(HL);break;\r\ncase LD_SP_WORD: M_LDWORD(SP);break;\r\n\r\ncase LD_PC_HL: R->PC.W=R->HL.W;break;\r\ncase LD_SP_HL: R->SP.W=R->HL.W;break;\r\ncase LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;\r\ncase LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;\r\n\r\ncase ADD_HL_BC:  M_ADDW(HL,BC);break;\r\ncase ADD_HL_DE:  M_ADDW(HL,DE);break;\r\ncase ADD_HL_HL:  M_ADDW(HL,HL);break;\r\ncase ADD_HL_SP:  M_ADDW(HL,SP);break;\r\n\r\ncase DEC_BC:   R->BC.W--;break;\r\ncase DEC_DE:   R->DE.W--;break;\r\ncase DEC_HL:   R->HL.W--;break;\r\ncase DEC_SP:   R->SP.W--;break;\r\n\r\ncase INC_BC:   R->BC.W++;break;\r\ncase INC_DE:   R->DE.W++;break;\r\ncase INC_HL:   R->HL.W++;break;\r\ncase INC_SP:   R->SP.W++;break;\r\n\r\ncase DEC_B:    M_DEC(R->BC.B.h);break;\r\ncase DEC_C:    M_DEC(R->BC.B.l);break;\r\ncase DEC_D:    M_DEC(R->DE.B.h);break;\r\ncase DEC_E:    M_DEC(R->DE.B.l);break;\r\ncase DEC_H:    M_DEC(R->HL.B.h);break;\r\ncase DEC_L:    M_DEC(R->HL.B.l);break;\r\ncase DEC_A:    M_DEC(R->AF.B.h);break;\r\ncase DEC_xHL:  I=RdZ80(R->HL.W);M_DEC(I);WrZ80(R->HL.W,I);break;\r\n\r\ncase INC_B:    M_INC(R->BC.B.h);break;\r\ncase INC_C:    M_INC(R->BC.B.l);break;\r\ncase INC_D:    M_INC(R->DE.B.h);break;\r\ncase INC_E:    M_INC(R->DE.B.l);break;\r\ncase INC_H:    M_INC(R->HL.B.h);break;\r\ncase INC_L:    M_INC(R->HL.B.l);break;\r\ncase INC_A:    M_INC(R->AF.B.h);break;\r\ncase INC_xHL:  I=RdZ80(R->HL.W);M_INC(I);WrZ80(R->HL.W,I);break;\r\n\r\ncase RLCA:\r\n  I=R->AF.B.h&0x80? C_FLAG:0;\r\n  R->AF.B.h=(R->AF.B.h<<1)|I;\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\ncase RLA:\r\n  I=R->AF.B.h&0x80? C_FLAG:0;\r\n  R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\ncase RRCA:\r\n  I=R->AF.B.h&0x01;\r\n  R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\ncase RRA:\r\n  I=R->AF.B.h&0x01;\r\n  R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\n\r\ncase RST00:    M_RST(0x0000);break;\r\ncase RST08:    M_RST(0x0008);break;\r\ncase RST10:    M_RST(0x0010);break;\r\ncase RST18:    M_RST(0x0018);break;\r\ncase RST20:    M_RST(0x0020);break;\r\ncase RST28:    M_RST(0x0028);break;\r\ncase RST30:    M_RST(0x0030);break;\r\ncase RST38:    M_RST(0x0038);break;\r\n\r\ncase PUSH_BC:  M_PUSH(BC);break;\r\ncase PUSH_DE:  M_PUSH(DE);break;\r\ncase PUSH_HL:  M_PUSH(HL);break;\r\ncase PUSH_AF:  M_PUSH(AF);break;\r\n\r\ncase POP_BC:   M_POP(BC);break;\r\ncase POP_DE:   M_POP(DE);break;\r\ncase POP_HL:   M_POP(HL);break;\r\ncase POP_AF:   M_POP(AF);break;\r\n\r\ncase DJNZ: if(--R->BC.B.h) {R->ICount-=5;M_JR; } else R->PC.W++;break;\r\ncase JP:   M_JP;break;\r\ncase JR:   M_JR;break;\r\ncase CALL: M_CALL;break;\r\ncase RET:  M_RET;break;\r\ncase SCF:  S(C_FLAG);R(N_FLAG|H_FLAG);break;\r\ncase CPL:  R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;\r\ncase NOP:  break;\r\ncase OUTA: I=RdZ80(R->PC.W++);OutZ80(I,R->AF.B.h);break;\r\ncase INA:  I=RdZ80(R->PC.W++);R->AF.B.h=InZ80(I);break;\r\n\r\ncase HALT:\r\n  R->PC.W--;\r\n  R->IFF|=IFF_HALT;\r\n  if (R->ICount > 0) \r\n  {\r\n\t  // Update R register\r\n\t  // Avoid % on negative numbers\r\n\t  const int cycles = Cycles[I];\r\n\t  R->R += R->ICount / cycles;\r\n\t  R->ICount %= cycles;\r\n\t  R->IBackup = R->ICount;\r\n  } \r\n  break;\r\n\r\ncase DI:\r\n  if (R->IFF & IFF_EI)\r\n     R->ICount += R->IBackup - 1;\r\n  // R->IFF &= 0xDE; /* UPGRADE */\r\n  R->IFF &= ~(IFF_1|IFF_2|IFF_EI);\r\n  break;\r\n\r\ncase EI:\r\n  if(!(R->IFF & (IFF_1|IFF_EI)))\r\n  {\r\n    R->IFF |= IFF_2|IFF_EI;\r\n    R->IBackup = R->ICount;\r\n    R->ICount = 1;\r\n  }\r\n/*\r\n// UPGRADE\r\n  if (!(R->IFF & 0x01))\r\n     {\r\n     R->IFF |= 0x20;\r\n     R->IBackup = R->ICount;\r\n     R->ICount = 1;\r\n     }\r\n  #ifdef MEKA_Z80_INT_NEW\r\n  else\r\n     {\r\n     R->IFF |= 0x40;\r\n     }\r\n  #endif\r\n*/\r\n  break;\r\n\r\ncase CCF:\r\n  R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);\r\n  R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;\r\n  break;\r\n\r\ncase EXX:\r\n  J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;\r\n  J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;\r\n  J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;\r\n  break;\r\n\r\ncase EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;\r\ncase EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;\r\n\r\ncase LD_B_B:   R->BC.B.h=R->BC.B.h;break;\r\ncase LD_C_B:   R->BC.B.l=R->BC.B.h;break;\r\ncase LD_D_B:   R->DE.B.h=R->BC.B.h;break;\r\ncase LD_E_B:   R->DE.B.l=R->BC.B.h;break;\r\ncase LD_H_B:   R->HL.B.h=R->BC.B.h;break;\r\ncase LD_L_B:   R->HL.B.l=R->BC.B.h;break;\r\ncase LD_A_B:   R->AF.B.h=R->BC.B.h;break;\r\ncase LD_xHL_B: WrZ80(R->HL.W,R->BC.B.h);break;\r\n\r\ncase LD_B_C:   R->BC.B.h=R->BC.B.l;break;\r\ncase LD_C_C:   R->BC.B.l=R->BC.B.l;break;\r\ncase LD_D_C:   R->DE.B.h=R->BC.B.l;break;\r\ncase LD_E_C:   R->DE.B.l=R->BC.B.l;break;\r\ncase LD_H_C:   R->HL.B.h=R->BC.B.l;break;\r\ncase LD_L_C:   R->HL.B.l=R->BC.B.l;break;\r\ncase LD_A_C:   R->AF.B.h=R->BC.B.l;break;\r\ncase LD_xHL_C: WrZ80(R->HL.W,R->BC.B.l);break;\r\n\r\ncase LD_B_D:   R->BC.B.h=R->DE.B.h;break;\r\ncase LD_C_D:   R->BC.B.l=R->DE.B.h;break;\r\ncase LD_D_D:   R->DE.B.h=R->DE.B.h;break;\r\ncase LD_E_D:   R->DE.B.l=R->DE.B.h;break;\r\ncase LD_H_D:   R->HL.B.h=R->DE.B.h;break;\r\ncase LD_L_D:   R->HL.B.l=R->DE.B.h;break;\r\ncase LD_A_D:   R->AF.B.h=R->DE.B.h;break;\r\ncase LD_xHL_D: WrZ80(R->HL.W,R->DE.B.h);break;\r\n\r\ncase LD_B_E:   R->BC.B.h=R->DE.B.l;break;\r\ncase LD_C_E:   R->BC.B.l=R->DE.B.l;break;\r\ncase LD_D_E:   R->DE.B.h=R->DE.B.l;break;\r\ncase LD_E_E:   R->DE.B.l=R->DE.B.l;break;\r\ncase LD_H_E:   R->HL.B.h=R->DE.B.l;break;\r\ncase LD_L_E:   R->HL.B.l=R->DE.B.l;break;\r\ncase LD_A_E:   R->AF.B.h=R->DE.B.l;break;\r\ncase LD_xHL_E: WrZ80(R->HL.W,R->DE.B.l);break;\r\n\r\ncase LD_B_H:   R->BC.B.h=R->HL.B.h;break;\r\ncase LD_C_H:   R->BC.B.l=R->HL.B.h;break;\r\ncase LD_D_H:   R->DE.B.h=R->HL.B.h;break;\r\ncase LD_E_H:   R->DE.B.l=R->HL.B.h;break;\r\ncase LD_H_H:   R->HL.B.h=R->HL.B.h;break;\r\ncase LD_L_H:   R->HL.B.l=R->HL.B.h;break;\r\ncase LD_A_H:   R->AF.B.h=R->HL.B.h;break;\r\ncase LD_xHL_H: WrZ80(R->HL.W,R->HL.B.h);break;\r\n\r\ncase LD_B_L:   R->BC.B.h=R->HL.B.l;break;\r\ncase LD_C_L:   R->BC.B.l=R->HL.B.l;break;\r\ncase LD_D_L:   R->DE.B.h=R->HL.B.l;break;\r\ncase LD_E_L:   R->DE.B.l=R->HL.B.l;break;\r\ncase LD_H_L:   R->HL.B.h=R->HL.B.l;break;\r\ncase LD_L_L:   R->HL.B.l=R->HL.B.l;break;\r\ncase LD_A_L:   R->AF.B.h=R->HL.B.l;break;\r\ncase LD_xHL_L: WrZ80(R->HL.W,R->HL.B.l);break;\r\n\r\ncase LD_B_A:   R->BC.B.h=R->AF.B.h;break;\r\ncase LD_C_A:   R->BC.B.l=R->AF.B.h;break;\r\ncase LD_D_A:   R->DE.B.h=R->AF.B.h;break;\r\ncase LD_E_A:   R->DE.B.l=R->AF.B.h;break;\r\ncase LD_H_A:   R->HL.B.h=R->AF.B.h;break;\r\ncase LD_L_A:   R->HL.B.l=R->AF.B.h;break;\r\ncase LD_A_A:   R->AF.B.h=R->AF.B.h;break;\r\ncase LD_xHL_A: WrZ80(R->HL.W,R->AF.B.h);break;\r\n\r\ncase LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;\r\ncase LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;\r\n\r\ncase LD_B_xHL:    R->BC.B.h=RdZ80(R->HL.W);break;\r\ncase LD_C_xHL:    R->BC.B.l=RdZ80(R->HL.W);break;\r\ncase LD_D_xHL:    R->DE.B.h=RdZ80(R->HL.W);break;\r\ncase LD_E_xHL:    R->DE.B.l=RdZ80(R->HL.W);break;\r\ncase LD_H_xHL:    R->HL.B.h=RdZ80(R->HL.W);break;\r\ncase LD_L_xHL:    R->HL.B.l=RdZ80(R->HL.W);break;\r\ncase LD_A_xHL:    R->AF.B.h=RdZ80(R->HL.W);break;\r\n\r\ncase LD_B_BYTE:   R->BC.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_C_BYTE:   R->BC.B.l=RdZ80(R->PC.W++);break;\r\ncase LD_D_BYTE:   R->DE.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_E_BYTE:   R->DE.B.l=RdZ80(R->PC.W++);break;\r\ncase LD_H_BYTE:   R->HL.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_L_BYTE:   R->HL.B.l=RdZ80(R->PC.W++);break;\r\ncase LD_A_BYTE:   R->AF.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_xHL_BYTE: WrZ80(R->HL.W,RdZ80(R->PC.W++));break;\r\n\r\ncase LD_xWORD_HL:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W++,R->HL.B.l);\r\n  WrZ80(J.W,R->HL.B.h);\r\n  break;\r\n\r\ncase LD_HL_xWORD:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->HL.B.l=RdZ80(J.W++);\r\n  R->HL.B.h=RdZ80(J.W);\r\n  break;\r\n\r\ncase LD_A_xWORD:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->AF.B.h=RdZ80(J.W);\r\n  break;\r\n\r\ncase LD_xWORD_A:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W,R->AF.B.h);\r\n  break;\r\n\r\ncase EX_HL_xSP:\r\n  J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->HL.B.l);\r\n  J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->HL.B.h);\r\n  R->HL.W=J.W;\r\n  break;\r\n\r\ncase DAA:\r\n  J.W=R->AF.B.h;\r\n  if(R->AF.B.l&C_FLAG) J.W|=256;\r\n  if(R->AF.B.l&H_FLAG) J.W|=512;\r\n  if(R->AF.B.l&N_FLAG) J.W|=1024;\r\n  R->AF.W=DAATable[J.W];\r\n  break;\r\n\r\ndefault:\r\n  if(R->TrapBadOps)\r\n    printf\r\n    (\r\n      \"[Z80 %lX] Unrecognized instruction: %02X at PC=%04X\\n\",\r\n      (long)R->User,RdZ80(R->PC.W-1),R->PC.W-1\r\n    );\r\n  break;\r\n"
  },
  {
    "path": "meka/srcs/z80marat/CodesCB.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                         CodesCB.h                       **/\r\n/**                                                         **/\r\n/** This file contains implementation for the CB table of   **/\r\n/** Z80 commands. It is included from Z80.c.                **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\ncase RLC_B: M_RLC(R->BC.B.h);break;  case RLC_C: M_RLC(R->BC.B.l);break;\r\ncase RLC_D: M_RLC(R->DE.B.h);break;  case RLC_E: M_RLC(R->DE.B.l);break;\r\ncase RLC_H: M_RLC(R->HL.B.h);break;  case RLC_L: M_RLC(R->HL.B.l);break;\r\ncase RLC_xHL: I=RdZ80(R->HL.W);M_RLC(I);WrZ80(R->HL.W,I);break;\r\ncase RLC_A: M_RLC(R->AF.B.h);break;\r\n\r\ncase RRC_B: M_RRC(R->BC.B.h);break;  case RRC_C: M_RRC(R->BC.B.l);break;\r\ncase RRC_D: M_RRC(R->DE.B.h);break;  case RRC_E: M_RRC(R->DE.B.l);break;\r\ncase RRC_H: M_RRC(R->HL.B.h);break;  case RRC_L: M_RRC(R->HL.B.l);break;\r\ncase RRC_xHL: I=RdZ80(R->HL.W);M_RRC(I);WrZ80(R->HL.W,I);break;\r\ncase RRC_A: M_RRC(R->AF.B.h);break;\r\n\r\ncase RL_B: M_RL(R->BC.B.h);break;  case RL_C: M_RL(R->BC.B.l);break;\r\ncase RL_D: M_RL(R->DE.B.h);break;  case RL_E: M_RL(R->DE.B.l);break;\r\ncase RL_H: M_RL(R->HL.B.h);break;  case RL_L: M_RL(R->HL.B.l);break;\r\ncase RL_xHL: I=RdZ80(R->HL.W);M_RL(I);WrZ80(R->HL.W,I);break;\r\ncase RL_A: M_RL(R->AF.B.h);break;\r\n\r\ncase RR_B: M_RR(R->BC.B.h);break;  case RR_C: M_RR(R->BC.B.l);break;\r\ncase RR_D: M_RR(R->DE.B.h);break;  case RR_E: M_RR(R->DE.B.l);break;\r\ncase RR_H: M_RR(R->HL.B.h);break;  case RR_L: M_RR(R->HL.B.l);break;\r\ncase RR_xHL: I=RdZ80(R->HL.W);M_RR(I);WrZ80(R->HL.W,I);break;\r\ncase RR_A: M_RR(R->AF.B.h);break;\r\n\r\ncase SLA_B: M_SLA(R->BC.B.h);break;  case SLA_C: M_SLA(R->BC.B.l);break;\r\ncase SLA_D: M_SLA(R->DE.B.h);break;  case SLA_E: M_SLA(R->DE.B.l);break;\r\ncase SLA_H: M_SLA(R->HL.B.h);break;  case SLA_L: M_SLA(R->HL.B.l);break;\r\ncase SLA_xHL: I=RdZ80(R->HL.W);M_SLA(I);WrZ80(R->HL.W,I);break;\r\ncase SLA_A: M_SLA(R->AF.B.h);break;\r\n\r\ncase SRA_B: M_SRA(R->BC.B.h);break;  case SRA_C: M_SRA(R->BC.B.l);break;\r\ncase SRA_D: M_SRA(R->DE.B.h);break;  case SRA_E: M_SRA(R->DE.B.l);break;\r\ncase SRA_H: M_SRA(R->HL.B.h);break;  case SRA_L: M_SRA(R->HL.B.l);break;\r\ncase SRA_xHL: I=RdZ80(R->HL.W);M_SRA(I);WrZ80(R->HL.W,I);break;\r\ncase SRA_A: M_SRA(R->AF.B.h);break;\r\n\r\ncase SLL_B: M_SLL(R->BC.B.h);break;  case SLL_C: M_SLL(R->BC.B.l);break;\r\ncase SLL_D: M_SLL(R->DE.B.h);break;  case SLL_E: M_SLL(R->DE.B.l);break;\r\ncase SLL_H: M_SLL(R->HL.B.h);break;  case SLL_L: M_SLL(R->HL.B.l);break;\r\ncase SLL_xHL: I=RdZ80(R->HL.W);M_SLL(I);WrZ80(R->HL.W,I);break;\r\ncase SLL_A: M_SLL(R->AF.B.h);break;\r\n\r\ncase SRL_B: M_SRL(R->BC.B.h);break;  case SRL_C: M_SRL(R->BC.B.l);break;\r\ncase SRL_D: M_SRL(R->DE.B.h);break;  case SRL_E: M_SRL(R->DE.B.l);break;\r\ncase SRL_H: M_SRL(R->HL.B.h);break;  case SRL_L: M_SRL(R->HL.B.l);break;\r\ncase SRL_xHL: I=RdZ80(R->HL.W);M_SRL(I);WrZ80(R->HL.W,I);break;\r\ncase SRL_A: M_SRL(R->AF.B.h);break;\r\n\r\ncase BIT0_B: M_BIT(0,R->BC.B.h);break;  case BIT0_C: M_BIT(0,R->BC.B.l);break;\r\ncase BIT0_D: M_BIT(0,R->DE.B.h);break;  case BIT0_E: M_BIT(0,R->DE.B.l);break;\r\ncase BIT0_H: M_BIT(0,R->HL.B.h);break;  case BIT0_L: M_BIT(0,R->HL.B.l);break;\r\ncase BIT0_xHL: I=RdZ80(R->HL.W);M_BIT(0,I);break;\r\ncase BIT0_A: M_BIT(0,R->AF.B.h);break;\r\n\r\ncase BIT1_B: M_BIT(1,R->BC.B.h);break;  case BIT1_C: M_BIT(1,R->BC.B.l);break;\r\ncase BIT1_D: M_BIT(1,R->DE.B.h);break;  case BIT1_E: M_BIT(1,R->DE.B.l);break;\r\ncase BIT1_H: M_BIT(1,R->HL.B.h);break;  case BIT1_L: M_BIT(1,R->HL.B.l);break;\r\ncase BIT1_xHL: I=RdZ80(R->HL.W);M_BIT(1,I);break;\r\ncase BIT1_A: M_BIT(1,R->AF.B.h);break;\r\n\r\ncase BIT2_B: M_BIT(2,R->BC.B.h);break;  case BIT2_C: M_BIT(2,R->BC.B.l);break;\r\ncase BIT2_D: M_BIT(2,R->DE.B.h);break;  case BIT2_E: M_BIT(2,R->DE.B.l);break;\r\ncase BIT2_H: M_BIT(2,R->HL.B.h);break;  case BIT2_L: M_BIT(2,R->HL.B.l);break;\r\ncase BIT2_xHL: I=RdZ80(R->HL.W);M_BIT(2,I);break;\r\ncase BIT2_A: M_BIT(2,R->AF.B.h);break;\r\n\r\ncase BIT3_B: M_BIT(3,R->BC.B.h);break;  case BIT3_C: M_BIT(3,R->BC.B.l);break;\r\ncase BIT3_D: M_BIT(3,R->DE.B.h);break;  case BIT3_E: M_BIT(3,R->DE.B.l);break;\r\ncase BIT3_H: M_BIT(3,R->HL.B.h);break;  case BIT3_L: M_BIT(3,R->HL.B.l);break;\r\ncase BIT3_xHL: I=RdZ80(R->HL.W);M_BIT(3,I);break;\r\ncase BIT3_A: M_BIT(3,R->AF.B.h);break;\r\n\r\ncase BIT4_B: M_BIT(4,R->BC.B.h);break;  case BIT4_C: M_BIT(4,R->BC.B.l);break;\r\ncase BIT4_D: M_BIT(4,R->DE.B.h);break;  case BIT4_E: M_BIT(4,R->DE.B.l);break;\r\ncase BIT4_H: M_BIT(4,R->HL.B.h);break;  case BIT4_L: M_BIT(4,R->HL.B.l);break;\r\ncase BIT4_xHL: I=RdZ80(R->HL.W);M_BIT(4,I);break;\r\ncase BIT4_A: M_BIT(4,R->AF.B.h);break;\r\n\r\ncase BIT5_B: M_BIT(5,R->BC.B.h);break;  case BIT5_C: M_BIT(5,R->BC.B.l);break;\r\ncase BIT5_D: M_BIT(5,R->DE.B.h);break;  case BIT5_E: M_BIT(5,R->DE.B.l);break;\r\ncase BIT5_H: M_BIT(5,R->HL.B.h);break;  case BIT5_L: M_BIT(5,R->HL.B.l);break;\r\ncase BIT5_xHL: I=RdZ80(R->HL.W);M_BIT(5,I);break;\r\ncase BIT5_A: M_BIT(5,R->AF.B.h);break;\r\n\r\ncase BIT6_B: M_BIT(6,R->BC.B.h);break;  case BIT6_C: M_BIT(6,R->BC.B.l);break;\r\ncase BIT6_D: M_BIT(6,R->DE.B.h);break;  case BIT6_E: M_BIT(6,R->DE.B.l);break;\r\ncase BIT6_H: M_BIT(6,R->HL.B.h);break;  case BIT6_L: M_BIT(6,R->HL.B.l);break;\r\ncase BIT6_xHL: I=RdZ80(R->HL.W);M_BIT(6,I);break;\r\ncase BIT6_A: M_BIT(6,R->AF.B.h);break;\r\n\r\ncase BIT7_B: M_BIT(7,R->BC.B.h);break;  case BIT7_C: M_BIT(7,R->BC.B.l);break;\r\ncase BIT7_D: M_BIT(7,R->DE.B.h);break;  case BIT7_E: M_BIT(7,R->DE.B.l);break;\r\ncase BIT7_H: M_BIT(7,R->HL.B.h);break;  case BIT7_L: M_BIT(7,R->HL.B.l);break;\r\ncase BIT7_xHL: I=RdZ80(R->HL.W);M_BIT(7,I);break;\r\ncase BIT7_A: M_BIT(7,R->AF.B.h);break;\r\n\r\ncase RES0_B: M_RES(0,R->BC.B.h);break;  case RES0_C: M_RES(0,R->BC.B.l);break;\r\ncase RES0_D: M_RES(0,R->DE.B.h);break;  case RES0_E: M_RES(0,R->DE.B.l);break;\r\ncase RES0_H: M_RES(0,R->HL.B.h);break;  case RES0_L: M_RES(0,R->HL.B.l);break;\r\ncase RES0_xHL: I=RdZ80(R->HL.W);M_RES(0,I);WrZ80(R->HL.W,I);break;\r\ncase RES0_A: M_RES(0,R->AF.B.h);break;\r\n\r\ncase RES1_B: M_RES(1,R->BC.B.h);break;  case RES1_C: M_RES(1,R->BC.B.l);break;\r\ncase RES1_D: M_RES(1,R->DE.B.h);break;  case RES1_E: M_RES(1,R->DE.B.l);break;\r\ncase RES1_H: M_RES(1,R->HL.B.h);break;  case RES1_L: M_RES(1,R->HL.B.l);break;\r\ncase RES1_xHL: I=RdZ80(R->HL.W);M_RES(1,I);WrZ80(R->HL.W,I);break;\r\ncase RES1_A: M_RES(1,R->AF.B.h);break;\r\n\r\ncase RES2_B: M_RES(2,R->BC.B.h);break;  case RES2_C: M_RES(2,R->BC.B.l);break;\r\ncase RES2_D: M_RES(2,R->DE.B.h);break;  case RES2_E: M_RES(2,R->DE.B.l);break;\r\ncase RES2_H: M_RES(2,R->HL.B.h);break;  case RES2_L: M_RES(2,R->HL.B.l);break;\r\ncase RES2_xHL: I=RdZ80(R->HL.W);M_RES(2,I);WrZ80(R->HL.W,I);break;\r\ncase RES2_A: M_RES(2,R->AF.B.h);break;\r\n\r\ncase RES3_B: M_RES(3,R->BC.B.h);break;  case RES3_C: M_RES(3,R->BC.B.l);break;\r\ncase RES3_D: M_RES(3,R->DE.B.h);break;  case RES3_E: M_RES(3,R->DE.B.l);break;\r\ncase RES3_H: M_RES(3,R->HL.B.h);break;  case RES3_L: M_RES(3,R->HL.B.l);break;\r\ncase RES3_xHL: I=RdZ80(R->HL.W);M_RES(3,I);WrZ80(R->HL.W,I);break;\r\ncase RES3_A: M_RES(3,R->AF.B.h);break;\r\n\r\ncase RES4_B: M_RES(4,R->BC.B.h);break;  case RES4_C: M_RES(4,R->BC.B.l);break;\r\ncase RES4_D: M_RES(4,R->DE.B.h);break;  case RES4_E: M_RES(4,R->DE.B.l);break;\r\ncase RES4_H: M_RES(4,R->HL.B.h);break;  case RES4_L: M_RES(4,R->HL.B.l);break;\r\ncase RES4_xHL: I=RdZ80(R->HL.W);M_RES(4,I);WrZ80(R->HL.W,I);break;\r\ncase RES4_A: M_RES(4,R->AF.B.h);break;\r\n\r\ncase RES5_B: M_RES(5,R->BC.B.h);break;  case RES5_C: M_RES(5,R->BC.B.l);break;\r\ncase RES5_D: M_RES(5,R->DE.B.h);break;  case RES5_E: M_RES(5,R->DE.B.l);break;\r\ncase RES5_H: M_RES(5,R->HL.B.h);break;  case RES5_L: M_RES(5,R->HL.B.l);break;\r\ncase RES5_xHL: I=RdZ80(R->HL.W);M_RES(5,I);WrZ80(R->HL.W,I);break;\r\ncase RES5_A: M_RES(5,R->AF.B.h);break;\r\n\r\ncase RES6_B: M_RES(6,R->BC.B.h);break;  case RES6_C: M_RES(6,R->BC.B.l);break;\r\ncase RES6_D: M_RES(6,R->DE.B.h);break;  case RES6_E: M_RES(6,R->DE.B.l);break;\r\ncase RES6_H: M_RES(6,R->HL.B.h);break;  case RES6_L: M_RES(6,R->HL.B.l);break;\r\ncase RES6_xHL: I=RdZ80(R->HL.W);M_RES(6,I);WrZ80(R->HL.W,I);break;\r\ncase RES6_A: M_RES(6,R->AF.B.h);break;\r\n\r\ncase RES7_B: M_RES(7,R->BC.B.h);break;  case RES7_C: M_RES(7,R->BC.B.l);break;\r\ncase RES7_D: M_RES(7,R->DE.B.h);break;  case RES7_E: M_RES(7,R->DE.B.l);break;\r\ncase RES7_H: M_RES(7,R->HL.B.h);break;  case RES7_L: M_RES(7,R->HL.B.l);break;\r\ncase RES7_xHL: I=RdZ80(R->HL.W);M_RES(7,I);WrZ80(R->HL.W,I);break;\r\ncase RES7_A: M_RES(7,R->AF.B.h);break;\r\n\r\ncase SET0_B: M_SET(0,R->BC.B.h);break;  case SET0_C: M_SET(0,R->BC.B.l);break;\r\ncase SET0_D: M_SET(0,R->DE.B.h);break;  case SET0_E: M_SET(0,R->DE.B.l);break;\r\ncase SET0_H: M_SET(0,R->HL.B.h);break;  case SET0_L: M_SET(0,R->HL.B.l);break;\r\ncase SET0_xHL: I=RdZ80(R->HL.W);M_SET(0,I);WrZ80(R->HL.W,I);break;\r\ncase SET0_A: M_SET(0,R->AF.B.h);break;\r\n\r\ncase SET1_B: M_SET(1,R->BC.B.h);break;  case SET1_C: M_SET(1,R->BC.B.l);break;\r\ncase SET1_D: M_SET(1,R->DE.B.h);break;  case SET1_E: M_SET(1,R->DE.B.l);break;\r\ncase SET1_H: M_SET(1,R->HL.B.h);break;  case SET1_L: M_SET(1,R->HL.B.l);break;\r\ncase SET1_xHL: I=RdZ80(R->HL.W);M_SET(1,I);WrZ80(R->HL.W,I);break;\r\ncase SET1_A: M_SET(1,R->AF.B.h);break;\r\n\r\ncase SET2_B: M_SET(2,R->BC.B.h);break;  case SET2_C: M_SET(2,R->BC.B.l);break;\r\ncase SET2_D: M_SET(2,R->DE.B.h);break;  case SET2_E: M_SET(2,R->DE.B.l);break;\r\ncase SET2_H: M_SET(2,R->HL.B.h);break;  case SET2_L: M_SET(2,R->HL.B.l);break;\r\ncase SET2_xHL: I=RdZ80(R->HL.W);M_SET(2,I);WrZ80(R->HL.W,I);break;\r\ncase SET2_A: M_SET(2,R->AF.B.h);break;\r\n\r\ncase SET3_B: M_SET(3,R->BC.B.h);break;  case SET3_C: M_SET(3,R->BC.B.l);break;\r\ncase SET3_D: M_SET(3,R->DE.B.h);break;  case SET3_E: M_SET(3,R->DE.B.l);break;\r\ncase SET3_H: M_SET(3,R->HL.B.h);break;  case SET3_L: M_SET(3,R->HL.B.l);break;\r\ncase SET3_xHL: I=RdZ80(R->HL.W);M_SET(3,I);WrZ80(R->HL.W,I);break;\r\ncase SET3_A: M_SET(3,R->AF.B.h);break;\r\n\r\ncase SET4_B: M_SET(4,R->BC.B.h);break;  case SET4_C: M_SET(4,R->BC.B.l);break;\r\ncase SET4_D: M_SET(4,R->DE.B.h);break;  case SET4_E: M_SET(4,R->DE.B.l);break;\r\ncase SET4_H: M_SET(4,R->HL.B.h);break;  case SET4_L: M_SET(4,R->HL.B.l);break;\r\ncase SET4_xHL: I=RdZ80(R->HL.W);M_SET(4,I);WrZ80(R->HL.W,I);break;\r\ncase SET4_A: M_SET(4,R->AF.B.h);break;\r\n\r\ncase SET5_B: M_SET(5,R->BC.B.h);break;  case SET5_C: M_SET(5,R->BC.B.l);break;\r\ncase SET5_D: M_SET(5,R->DE.B.h);break;  case SET5_E: M_SET(5,R->DE.B.l);break;\r\ncase SET5_H: M_SET(5,R->HL.B.h);break;  case SET5_L: M_SET(5,R->HL.B.l);break;\r\ncase SET5_xHL: I=RdZ80(R->HL.W);M_SET(5,I);WrZ80(R->HL.W,I);break;\r\ncase SET5_A: M_SET(5,R->AF.B.h);break;\r\n\r\ncase SET6_B: M_SET(6,R->BC.B.h);break;  case SET6_C: M_SET(6,R->BC.B.l);break;\r\ncase SET6_D: M_SET(6,R->DE.B.h);break;  case SET6_E: M_SET(6,R->DE.B.l);break;\r\ncase SET6_H: M_SET(6,R->HL.B.h);break;  case SET6_L: M_SET(6,R->HL.B.l);break;\r\ncase SET6_xHL: I=RdZ80(R->HL.W);M_SET(6,I);WrZ80(R->HL.W,I);break;\r\ncase SET6_A: M_SET(6,R->AF.B.h);break;\r\n\r\ncase SET7_B: M_SET(7,R->BC.B.h);break;  case SET7_C: M_SET(7,R->BC.B.l);break;\r\ncase SET7_D: M_SET(7,R->DE.B.h);break;  case SET7_E: M_SET(7,R->DE.B.l);break;\r\ncase SET7_H: M_SET(7,R->HL.B.h);break;  case SET7_L: M_SET(7,R->HL.B.l);break;\r\ncase SET7_xHL: I=RdZ80(R->HL.W);M_SET(7,I);WrZ80(R->HL.W,I);break;\r\ncase SET7_A: M_SET(7,R->AF.B.h);break;\r\n"
  },
  {
    "path": "meka/srcs/z80marat/CodesED.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                         CodesED.h                       **/\r\n/**                                                         **/\r\n/** This file contains implementation for the ED table of   **/\r\n/** Z80 commands. It is included from Z80.c.                **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\n/** This is a special patch for emulating BIOS calls: ********/\r\ncase DB_FE:     PatchZ80(R);break;\r\n/*************************************************************/\r\n\r\ncase ADC_HL_BC: M_ADCW(BC);break;\r\ncase ADC_HL_DE: M_ADCW(DE);break;\r\ncase ADC_HL_HL: M_ADCW(HL);break;\r\ncase ADC_HL_SP: M_ADCW(SP);break;\r\n\r\ncase SBC_HL_BC: M_SBCW(BC);break;\r\ncase SBC_HL_DE: M_SBCW(DE);break;\r\ncase SBC_HL_HL: M_SBCW(HL);break;\r\ncase SBC_HL_SP: M_SBCW(SP);break;\r\n\r\ncase LD_xWORDe_HL:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W++,R->HL.B.l);\r\n  WrZ80(J.W,R->HL.B.h);\r\n  break;\r\ncase LD_xWORDe_DE:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W++,R->DE.B.l);\r\n  WrZ80(J.W,R->DE.B.h);\r\n  break;\r\ncase LD_xWORDe_BC:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W++,R->BC.B.l);\r\n  WrZ80(J.W,R->BC.B.h);\r\n  break;\r\ncase LD_xWORDe_SP:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W++,R->SP.B.l);\r\n  WrZ80(J.W,R->SP.B.h);\r\n  break;\r\n\r\ncase LD_HL_xWORDe:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->HL.B.l=RdZ80(J.W++);\r\n  R->HL.B.h=RdZ80(J.W);\r\n  break;\r\ncase LD_DE_xWORDe:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->DE.B.l=RdZ80(J.W++);\r\n  R->DE.B.h=RdZ80(J.W);\r\n  break;\r\ncase LD_BC_xWORDe:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->BC.B.l=RdZ80(J.W++);\r\n  R->BC.B.h=RdZ80(J.W);\r\n  break;\r\ncase LD_SP_xWORDe:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->SP.B.l=RdZ80(J.W++);\r\n  R->SP.B.h=RdZ80(J.W);\r\n  break;\r\n\r\ncase RRD:\r\n  I=RdZ80(R->HL.W);\r\n  J.B.l=(I>>4)|(R->AF.B.h<<4);\r\n  WrZ80(R->HL.W,J.B.l);\r\n  R->AF.B.h=(I&0x0F)|(R->AF.B.h&0xF0);\r\n  R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);\r\n  break;\r\ncase RLD:\r\n  I=RdZ80(R->HL.W);\r\n  J.B.l=(I<<4)|(R->AF.B.h&0x0F);\r\n  WrZ80(R->HL.W,J.B.l);\r\n  R->AF.B.h=(I>>4)|(R->AF.B.h&0xF0);\r\n  R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);\r\n  break;\r\n\r\ncase LD_A_I:\r\n  R->AF.B.h=R->I;\r\n  R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];\r\n  break;\r\n\r\ncase LD_A_R:\r\n  R->AF.B.h = R->R7 | (R->R & 0x7f); \r\n  // Msg(0, \"At PC=%04X: LD A,R, returning %02X\", R->PC.W, R->AF.B.h);\r\n  R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];\r\n  break;\r\n\r\ncase LD_I_A:   R->I=R->AF.B.h;break;\r\ncase LD_R_A:   \r\n  R->R = R->AF.B.h; // We can do & 0x7f here but we're ignoring 7th bit of this register anyways so it doesn't matter\r\n  R->R7 = R->AF.B.h & 0x80;\r\n  break;\r\n\r\ncase DB_4E: case DB_66: case DB_6E: // Undocumented\r\ncase IM_0:     R->IFF&=~(IFF_IM1|IFF_IM2);break;\r\ncase DB_76: // Undocumented\r\ncase IM_1:     R->IFF=(R->IFF&~IFF_IM2)|IFF_IM1;break;\r\ncase DB_7E: // Undocumented\r\ncase IM_2:     R->IFF=(R->IFF&~IFF_IM1)|IFF_IM2;break;\r\n\r\ncase DB_77: case DB_7F: // Undocumented NOP\r\n               break;\r\n\r\ncase RETI:     if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1;\r\n               M_RET;break;\r\n\r\ncase DB_55: case DB_5D: case DB_65: case DB_6D: case DB_75: case DB_7D: // Undocumented\r\ncase RETN:     if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1;\r\n               M_RET;break;\r\n\r\ncase DB_4C: case DB_54: case DB_5C: case DB_64: case DB_6C: case DB_74: case DB_7C: // Undocumented\r\ncase NEG:      I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break;\r\n\r\ncase IN_B_xC:  M_IN(R->BC.B.h);break;\r\ncase IN_C_xC:  M_IN(R->BC.B.l);break;\r\ncase IN_D_xC:  M_IN(R->DE.B.h);break;\r\ncase IN_E_xC:  M_IN(R->DE.B.l);break;\r\ncase IN_H_xC:  M_IN(R->HL.B.h);break;\r\ncase IN_L_xC:  M_IN(R->HL.B.l);break;\r\ncase IN_A_xC:  M_IN(R->AF.B.h);break;\r\ncase IN_F_xC:  M_IN(J.B.l);break;\r\n\r\ncase OUT_xC_B: OutZ80(R->BC.B.l,R->BC.B.h);break;\r\ncase OUT_xC_C: OutZ80(R->BC.B.l,R->BC.B.l);break;\r\ncase OUT_xC_D: OutZ80(R->BC.B.l,R->DE.B.h);break;\r\ncase OUT_xC_E: OutZ80(R->BC.B.l,R->DE.B.l);break;\r\ncase OUT_xC_H: OutZ80(R->BC.B.l,R->HL.B.h);break;\r\ncase OUT_xC_L: OutZ80(R->BC.B.l,R->HL.B.l);break;\r\ncase OUT_xC_A: OutZ80(R->BC.B.l,R->AF.B.h);break;\r\ncase OUT_xC_0: OutZ80(R->BC.B.l,0); break; // Undocumented OUT (C), A\r\n\r\ncase INI:\r\n  WrZ80(R->HL.W++,InZ80(R->BC.B.l));\r\n  R->BC.B.h--;\r\n  R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);\r\n  break;\r\n\r\ncase INIR:\r\n   R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    WrZ80(R->HL.W++,InZ80(R->BC.B.l));\r\n    R->BC.B.h--;R->ICount-=21;\r\n  }\r\n  while(R->BC.B.h&&(R->ICount>0));\r\n  if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }\r\n  else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }\r\n  break;\r\n\r\ncase IND:\r\n  WrZ80(R->HL.W--,InZ80(R->BC.B.l));\r\n  R->BC.B.h--;\r\n  R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);\r\n  break;\r\n\r\ncase INDR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    WrZ80(R->HL.W--,InZ80(R->BC.B.l));\r\n    R->BC.B.h--;R->ICount-=21;\r\n  }\r\n  while(R->BC.B.h&&(R->ICount>0));\r\n  if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }\r\n  else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }\r\n  break;\r\n\r\ncase OUTI:\r\n  I = RdZ80(R->HL.W++);\r\n  OutZ80(R->BC.B.l, I);\r\n  R->BC.B.h--;\r\n  R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);\r\n  break;\r\n\r\ncase OTIR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    I=RdZ80(R->HL.W++);\r\n    OutZ80(R->BC.B.l,I);\r\n    R->BC.B.h--;\r\n    R->ICount-=21;\r\n  }\r\n  while(R->BC.B.h&&(R->ICount>0));\r\n  if(R->BC.B.h)\r\n  {\r\n    R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);\r\n    R->PC.W-=2;\r\n  }\r\n  else\r\n  {\r\n    R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);\r\n    R->ICount+=5;\r\n  }\r\n  break;\r\n\r\ncase OUTD:\r\n  I=RdZ80(R->HL.W--);\r\n  OutZ80(R->BC.B.l,I);\r\n  R->BC.B.h--;\r\n  R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);\r\n  break;\r\n\r\ncase OTDR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    I=RdZ80(R->HL.W--);\r\n    OutZ80(R->BC.B.l,I);\r\n    R->BC.B.h--;\r\n    R->ICount-=21;\r\n  }\r\n  while(R->BC.B.h&&(R->ICount>0));\r\n  if(R->BC.B.h)\r\n  {\r\n    R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);\r\n    R->PC.W-=2;\r\n  }\r\n  else\r\n  {\r\n    R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);\r\n    R->ICount+=5;\r\n  }\r\n  break;\r\n\r\ncase LDI:\r\n  WrZ80(R->DE.W++,RdZ80(R->HL.W++));\r\n  R->BC.W--;\r\n  R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);\r\n  break;\r\n\r\ncase LDIR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    WrZ80(R->DE.W++, RdZ80(R->HL.W++));\r\n    R->BC.W--; R->ICount -= 21;\r\n  }\r\n  while (R->BC.W && (R->ICount > 0));\r\n  R->AF.B.l &=~ (N_FLAG | H_FLAG | P_FLAG);\r\n  if (R->BC.W) { R->AF.B.l |= N_FLAG; R->PC.W -= 2; }\r\n  else R->ICount += 5;\r\n  break;\r\n\r\ncase LDD:\r\n  WrZ80(R->DE.W--,RdZ80(R->HL.W--));\r\n  R->BC.W--;\r\n  R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);\r\n  break;\r\n\r\ncase LDDR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    WrZ80(R->DE.W--,RdZ80(R->HL.W--));\r\n    R->BC.W--;R->ICount-=21;\r\n  }\r\n  while(R->BC.W&&(R->ICount>0));\r\n  R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);\r\n  if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }\r\n  else R->ICount+=5; // FIXME! Official Z80 docs says it's always 21 T States\r\n  break;\r\n\r\ncase CPI:\r\n  I=RdZ80(R->HL.W++);\r\n  J.B.l=R->AF.B.h-I;\r\n  R->BC.W--;\r\n  R->AF.B.l =\r\n    N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|\r\n    ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);\r\n  break;\r\n\r\ncase CPIR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    I=RdZ80(R->HL.W++);\r\n    J.B.l=R->AF.B.h-I;\r\n    R->BC.W--;R->ICount-=21;\r\n  }\r\n  while(R->BC.W&&J.B.l&&(R->ICount>0));\r\n  R->AF.B.l =\r\n    N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|\r\n    ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);\r\n  if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;\r\n  break;\r\n\r\ncase CPD:\r\n  I=RdZ80(R->HL.W--);\r\n  J.B.l=R->AF.B.h-I;\r\n  R->BC.W--;\r\n  R->AF.B.l =\r\n    N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|\r\n    ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);\r\n  break;\r\n\r\ncase CPDR:\r\n  R->R += 2 * (R->ICount / 21); \r\n  do\r\n  {\r\n    I=RdZ80(R->HL.W--);\r\n    J.B.l=R->AF.B.h-I;\r\n    R->BC.W--;R->ICount-=21;\r\n  }\r\n  while(R->BC.W&&J.B.l&&(R->ICount>0)); \r\n  R->AF.B.l =\r\n    N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|\r\n    ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);\r\n  if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;\r\n  break;\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/CodesXCB.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                         CodesXCB.h                      **/\r\n/**                                                         **/\r\n/** This file contains implementation for FD/DD-CB tables   **/\r\n/** of Z80 commands. It is included from Z80.c.             **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\ncase RLC_xHL: I=RdZ80(J.W);M_RLC(I);WrZ80(J.W,I);break;\r\ncase RRC_xHL: I=RdZ80(J.W);M_RRC(I);WrZ80(J.W,I);break;\r\ncase RL_xHL:  I=RdZ80(J.W);M_RL(I);WrZ80(J.W,I);break;\r\ncase RR_xHL:  I=RdZ80(J.W);M_RR(I);WrZ80(J.W,I);break;\r\ncase SLA_xHL: I=RdZ80(J.W);M_SLA(I);WrZ80(J.W,I);break;\r\ncase SRA_xHL: I=RdZ80(J.W);M_SRA(I);WrZ80(J.W,I);break;\r\ncase SLL_xHL: I=RdZ80(J.W);M_SLL(I);WrZ80(J.W,I);break;\r\ncase SRL_xHL: I=RdZ80(J.W);M_SRL(I);WrZ80(J.W,I);break;\r\n\r\ncase BIT0_B: case BIT0_C: case BIT0_D: case BIT0_E:\r\ncase BIT0_H: case BIT0_L: case BIT0_A:\r\ncase BIT0_xHL: I=RdZ80(J.W);M_BIT(0,I);break;\r\ncase BIT1_B: case BIT1_C: case BIT1_D: case BIT1_E:\r\ncase BIT1_H: case BIT1_L: case BIT1_A:\r\ncase BIT1_xHL: I=RdZ80(J.W);M_BIT(1,I);break;\r\ncase BIT2_B: case BIT2_C: case BIT2_D: case BIT2_E:\r\ncase BIT2_H: case BIT2_L: case BIT2_A:\r\ncase BIT2_xHL: I=RdZ80(J.W);M_BIT(2,I);break;\r\ncase BIT3_B: case BIT3_C: case BIT3_D: case BIT3_E:\r\ncase BIT3_H: case BIT3_L: case BIT3_A:\r\ncase BIT3_xHL: I=RdZ80(J.W);M_BIT(3,I);break;\r\ncase BIT4_B: case BIT4_C: case BIT4_D: case BIT4_E:\r\ncase BIT4_H: case BIT4_L: case BIT4_A:\r\ncase BIT4_xHL: I=RdZ80(J.W);M_BIT(4,I);break;\r\ncase BIT5_B: case BIT5_C: case BIT5_D: case BIT5_E:\r\ncase BIT5_H: case BIT5_L: case BIT5_A:\r\ncase BIT5_xHL: I=RdZ80(J.W);M_BIT(5,I);break;\r\ncase BIT6_B: case BIT6_C: case BIT6_D: case BIT6_E:\r\ncase BIT6_H: case BIT6_L: case BIT6_A:\r\ncase BIT6_xHL: I=RdZ80(J.W);M_BIT(6,I);break;\r\ncase BIT7_B: case BIT7_C: case BIT7_D: case BIT7_E:\r\ncase BIT7_H: case BIT7_L: case BIT7_A:\r\ncase BIT7_xHL: I=RdZ80(J.W);M_BIT(7,I);break;\r\n\r\ncase RES0_xHL: I=RdZ80(J.W);M_RES(0,I);WrZ80(J.W,I);break;\r\ncase RES1_xHL: I=RdZ80(J.W);M_RES(1,I);WrZ80(J.W,I);break;   \r\ncase RES2_xHL: I=RdZ80(J.W);M_RES(2,I);WrZ80(J.W,I);break;   \r\ncase RES3_xHL: I=RdZ80(J.W);M_RES(3,I);WrZ80(J.W,I);break;   \r\ncase RES4_xHL: I=RdZ80(J.W);M_RES(4,I);WrZ80(J.W,I);break;   \r\ncase RES5_xHL: I=RdZ80(J.W);M_RES(5,I);WrZ80(J.W,I);break;   \r\ncase RES6_xHL: I=RdZ80(J.W);M_RES(6,I);WrZ80(J.W,I);break;   \r\ncase RES7_xHL: I=RdZ80(J.W);M_RES(7,I);WrZ80(J.W,I);break;   \r\n\r\ncase SET0_xHL: I=RdZ80(J.W);M_SET(0,I);WrZ80(J.W,I);break;   \r\ncase SET1_xHL: I=RdZ80(J.W);M_SET(1,I);WrZ80(J.W,I);break; \r\ncase SET2_xHL: I=RdZ80(J.W);M_SET(2,I);WrZ80(J.W,I);break; \r\ncase SET3_xHL: I=RdZ80(J.W);M_SET(3,I);WrZ80(J.W,I);break; \r\ncase SET4_xHL: I=RdZ80(J.W);M_SET(4,I);WrZ80(J.W,I);break; \r\ncase SET5_xHL: I=RdZ80(J.W);M_SET(5,I);WrZ80(J.W,I);break; \r\ncase SET6_xHL: I=RdZ80(J.W);M_SET(6,I);WrZ80(J.W,I);break; \r\ncase SET7_xHL: I=RdZ80(J.W);M_SET(7,I);WrZ80(J.W,I);break; \r\n"
  },
  {
    "path": "meka/srcs/z80marat/CodesXX.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                         CodesXX.h                       **/\r\n/**                                                         **/\r\n/** This file contains implementation for FD/DD tables of   **/\r\n/** Z80 commands. It is included from Z80.c.                **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\ncase JR_NZ:    if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;\r\ncase JR_NC:    if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;\r\ncase JR_Z:     if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;\r\ncase JR_C:     if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;\r\n\r\ncase JP_NZ:    if(R->AF.B.l&Z_FLAG)  R->PC.W+=2; else { M_JP; }  break;\r\ncase JP_NC:    if(R->AF.B.l&C_FLAG)  R->PC.W+=2; else { M_JP; }  break;\r\ncase JP_PO:    if(R->AF.B.l&P_FLAG)  R->PC.W+=2; else { M_JP; }  break;\r\ncase JP_P:     if(R->AF.B.l&S_FLAG)  R->PC.W+=2; else { M_JP; }  break;\r\ncase JP_Z:     if(R->AF.B.l&Z_FLAG)  { M_JP; }  else R->PC.W+=2; break;\r\ncase JP_C:     if(R->AF.B.l&C_FLAG)  { M_JP; }  else R->PC.W+=2; break;\r\ncase JP_PE:    if(R->AF.B.l&P_FLAG)  { M_JP; }  else R->PC.W+=2; break;\r\ncase JP_M:     if(R->AF.B.l&S_FLAG)  { M_JP; }  else R->PC.W+=2; break;\r\n\r\ncase RET_NZ:  if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_NC:  if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_PO:  if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_P:   if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;\r\ncase RET_Z:   if(R->AF.B.l&Z_FLAG)    { R->ICount-=6;M_RET; } break;\r\ncase RET_C:   if(R->AF.B.l&C_FLAG)    { R->ICount-=6;M_RET; } break;\r\ncase RET_PE:  if(R->AF.B.l&P_FLAG)    { R->ICount-=6;M_RET; } break;\r\ncase RET_M:   if(R->AF.B.l&S_FLAG)    { R->ICount-=6;M_RET; } break;\r\n\r\ncase CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_P:  if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;\r\ncase CALL_Z:  if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\ncase CALL_C:  if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\ncase CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\ncase CALL_M:  if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;\r\n\r\ncase ADD_B:    M_ADD(R->BC.B.h);break;\r\ncase ADD_C:    M_ADD(R->BC.B.l);break;\r\ncase ADD_D:    M_ADD(R->DE.B.h);break;\r\ncase ADD_E:    M_ADD(R->DE.B.l);break;\r\ncase ADD_H:    M_ADD(R->XX.B.h);break;\r\ncase ADD_L:    M_ADD(R->XX.B.l);break;\r\ncase ADD_A:    M_ADD(R->AF.B.h);break;\r\ncase ADD_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_ADD(I);break;\r\ncase ADD_BYTE: I=RdZ80(R->PC.W++);M_ADD(I);break;\r\n\r\ncase SUB_B:    M_SUB(R->BC.B.h);break;\r\ncase SUB_C:    M_SUB(R->BC.B.l);break;\r\ncase SUB_D:    M_SUB(R->DE.B.h);break;\r\ncase SUB_E:    M_SUB(R->DE.B.l);break;\r\ncase SUB_H:    M_SUB(R->XX.B.h);break;\r\ncase SUB_L:    M_SUB(R->XX.B.l);break;\r\ncase SUB_A:    R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;\r\ncase SUB_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_SUB(I);break;\r\ncase SUB_BYTE: I=RdZ80(R->PC.W++);M_SUB(I);break;\r\n\r\ncase AND_B:    M_AND(R->BC.B.h);break;\r\ncase AND_C:    M_AND(R->BC.B.l);break;\r\ncase AND_D:    M_AND(R->DE.B.h);break;\r\ncase AND_E:    M_AND(R->DE.B.l);break;\r\ncase AND_H:    M_AND(R->XX.B.h);break;\r\ncase AND_L:    M_AND(R->XX.B.l);break;\r\ncase AND_A:    M_AND(R->AF.B.h);break;\r\ncase AND_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_AND(I);break;\r\ncase AND_BYTE: I=RdZ80(R->PC.W++);M_AND(I);break;\r\n\r\ncase OR_B:     M_OR(R->BC.B.h);break;\r\ncase OR_C:     M_OR(R->BC.B.l);break;\r\ncase OR_D:     M_OR(R->DE.B.h);break;\r\ncase OR_E:     M_OR(R->DE.B.l);break;\r\ncase OR_H:     M_OR(R->XX.B.h);break;\r\ncase OR_L:     M_OR(R->XX.B.l);break;\r\ncase OR_A:     M_OR(R->AF.B.h);break;\r\ncase OR_xHL:   I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_OR(I);break;\r\ncase OR_BYTE:  I=RdZ80(R->PC.W++);M_OR(I);break;\r\n\r\ncase ADC_B:    M_ADC(R->BC.B.h);break;\r\ncase ADC_C:    M_ADC(R->BC.B.l);break;\r\ncase ADC_D:    M_ADC(R->DE.B.h);break;\r\ncase ADC_E:    M_ADC(R->DE.B.l);break;\r\ncase ADC_H:    M_ADC(R->XX.B.h);break;\r\ncase ADC_L:    M_ADC(R->XX.B.l);break;\r\ncase ADC_A:    M_ADC(R->AF.B.h);break;\r\ncase ADC_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_ADC(I);break;\r\ncase ADC_BYTE: I=RdZ80(R->PC.W++);M_ADC(I);break;\r\n\r\ncase SBC_B:    M_SBC(R->BC.B.h);break;\r\ncase SBC_C:    M_SBC(R->BC.B.l);break;\r\ncase SBC_D:    M_SBC(R->DE.B.h);break;\r\ncase SBC_E:    M_SBC(R->DE.B.l);break;\r\ncase SBC_H:    M_SBC(R->XX.B.h);break;\r\ncase SBC_L:    M_SBC(R->XX.B.l);break;\r\ncase SBC_A:    M_SBC(R->AF.B.h);break;\r\ncase SBC_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_SBC(I);break;\r\ncase SBC_BYTE: I=RdZ80(R->PC.W++);M_SBC(I);break;\r\n\r\ncase XOR_B:    M_XOR(R->BC.B.h);break;\r\ncase XOR_C:    M_XOR(R->BC.B.l);break;\r\ncase XOR_D:    M_XOR(R->DE.B.h);break;\r\ncase XOR_E:    M_XOR(R->DE.B.l);break;\r\ncase XOR_H:    M_XOR(R->XX.B.h);break;\r\ncase XOR_L:    M_XOR(R->XX.B.l);break;\r\ncase XOR_A:    R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;\r\ncase XOR_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_XOR(I);break;\r\ncase XOR_BYTE: I=RdZ80(R->PC.W++);M_XOR(I);break;\r\n\r\ncase CP_B:     M_CP(R->BC.B.h);break;\r\ncase CP_C:     M_CP(R->BC.B.l);break;\r\ncase CP_D:     M_CP(R->DE.B.h);break;\r\ncase CP_E:     M_CP(R->DE.B.l);break;\r\ncase CP_H:     M_CP(R->XX.B.h);break;\r\ncase CP_L:     M_CP(R->XX.B.l);break;\r\ncase CP_A:     R->AF.B.l=N_FLAG|Z_FLAG;break;\r\ncase CP_xHL:   I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));\r\n               M_CP(I);break;\r\ncase CP_BYTE:  I=RdZ80(R->PC.W++);M_CP(I);break;\r\n\r\ncase LD_BC_WORD: M_LDWORD(BC);break;\r\ncase LD_DE_WORD: M_LDWORD(DE);break;\r\ncase LD_HL_WORD: M_LDWORD(XX);break;\r\ncase LD_SP_WORD: M_LDWORD(SP);break;\r\n\r\ncase LD_PC_HL: R->PC.W=R->XX.W;break;\r\ncase LD_SP_HL: R->SP.W=R->XX.W;break;\r\ncase LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;\r\ncase LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;\r\n\r\ncase ADD_HL_BC:  M_ADDW(XX,BC);break;\r\ncase ADD_HL_DE:  M_ADDW(XX,DE);break;\r\ncase ADD_HL_HL:  M_ADDW(XX,XX);break;\r\ncase ADD_HL_SP:  M_ADDW(XX,SP);break;\r\n\r\ncase DEC_BC:   R->BC.W--;break;\r\ncase DEC_DE:   R->DE.W--;break;\r\ncase DEC_HL:   R->XX.W--;break;\r\ncase DEC_SP:   R->SP.W--;break;\r\n\r\ncase INC_BC:   R->BC.W++;break;\r\ncase INC_DE:   R->DE.W++;break;\r\ncase INC_HL:   R->XX.W++;break;\r\ncase INC_SP:   R->SP.W++;break;\r\n\r\ncase DEC_B:    M_DEC(R->BC.B.h);break;\r\ncase DEC_C:    M_DEC(R->BC.B.l);break;\r\ncase DEC_D:    M_DEC(R->DE.B.h);break;\r\ncase DEC_E:    M_DEC(R->DE.B.l);break;\r\ncase DEC_H:    M_DEC(R->XX.B.h);break;\r\ncase DEC_L:    M_DEC(R->XX.B.l);break;\r\ncase DEC_A:    M_DEC(R->AF.B.h);break;\r\ncase DEC_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_DEC(I);\r\n               WrZ80(R->XX.W+(offset)RdZ80(R->PC.W++),I);\r\n               break;\r\n\r\ncase INC_B:    M_INC(R->BC.B.h);break;\r\ncase INC_C:    M_INC(R->BC.B.l);break;\r\ncase INC_D:    M_INC(R->DE.B.h);break;\r\ncase INC_E:    M_INC(R->DE.B.l);break;\r\ncase INC_H:    M_INC(R->XX.B.h);break;\r\ncase INC_L:    M_INC(R->XX.B.l);break;\r\ncase INC_A:    M_INC(R->AF.B.h);break;\r\ncase INC_xHL:  I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_INC(I);\r\n               WrZ80(R->XX.W+(offset)RdZ80(R->PC.W++),I);\r\n               break;\r\n\r\ncase RLCA:\r\n  I=(R->AF.B.h&0x80? C_FLAG:0);\r\n  R->AF.B.h=(R->AF.B.h<<1)|I;\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\ncase RLA:\r\n  I=(R->AF.B.h&0x80? C_FLAG:0);\r\n  R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\ncase RRCA:\r\n  I=R->AF.B.h&0x01;\r\n  R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\ncase RRA:\r\n  I=R->AF.B.h&0x01;\r\n  R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);\r\n  R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;\r\n  break;\r\n\r\ncase RST00:    M_RST(0x0000);break;\r\ncase RST08:    M_RST(0x0008);break;\r\ncase RST10:    M_RST(0x0010);break;\r\ncase RST18:    M_RST(0x0018);break;\r\ncase RST20:    M_RST(0x0020);break;\r\ncase RST28:    M_RST(0x0028);break;\r\ncase RST30:    M_RST(0x0030);break;\r\ncase RST38:    M_RST(0x0038);break;\r\n\r\ncase PUSH_BC:  M_PUSH(BC);break;\r\ncase PUSH_DE:  M_PUSH(DE);break;\r\ncase PUSH_HL:  M_PUSH(XX);break;\r\ncase PUSH_AF:  M_PUSH(AF);break;\r\n\r\ncase POP_BC:   M_POP(BC);break;\r\ncase POP_DE:   M_POP(DE);break;\r\ncase POP_HL:   M_POP(XX);break;\r\ncase POP_AF:   M_POP(AF);break;\r\n\r\ncase DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break;\r\ncase JP:   M_JP;break;\r\ncase JR:   M_JR;break;\r\ncase CALL: M_CALL;break;\r\ncase RET:  M_RET;break;\r\ncase SCF:  S(C_FLAG);R(N_FLAG|H_FLAG);break;\r\ncase CPL:  R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;\r\ncase NOP:  break;\r\ncase OUTA: OutZ80(RdZ80(R->PC.W++),R->AF.B.h);break;\r\ncase INA:  R->AF.B.h=InZ80(RdZ80(R->PC.W++));break;\r\n\r\ncase HALT:\r\n  R->PC.W--;\r\n  R->IFF|=IFF_HALT;\r\n  R->IBackup=0;\r\n  R->ICount=0;\r\n  break;\r\n\r\ncase DI:\r\n  if (R->IFF & IFF_EI)\r\n     R->ICount += R->IBackup - 1;\r\n  // R->IFF &= 0xDE; /* UPGRADE */\r\n  R->IFF&=~(IFF_1|IFF_2|IFF_EI);\r\n  break;\r\n\r\ncase EI:\r\n  if(!(R->IFF & (IFF_1|IFF_EI)))\r\n  {\r\n    R->IFF |= IFF_2|IFF_EI;\r\n    R->IBackup = R->ICount;\r\n    R->ICount = 1;\r\n  }\r\n\r\n/*\r\n// UPGRADE\r\n  if (!(R->IFF & 0x01))\r\n     {\r\n     R->IFF |= 0x20;\r\n     R->IBackup = R->ICount;\r\n     R->ICount = 1;\r\n     }\r\n*/\r\n  break;\r\n\r\ncase CCF:\r\n  R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);\r\n  R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;\r\n  break;\r\n\r\ncase EXX:\r\n  J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;\r\n  J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;\r\n  J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;\r\n  break;\r\n\r\ncase EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;\r\ncase EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;\r\n\r\ncase LD_B_B:   R->BC.B.h=R->BC.B.h;break;\r\ncase LD_C_B:   R->BC.B.l=R->BC.B.h;break;\r\ncase LD_D_B:   R->DE.B.h=R->BC.B.h;break;\r\ncase LD_E_B:   R->DE.B.l=R->BC.B.h;break;\r\ncase LD_H_B:   R->XX.B.h=R->BC.B.h;break;\r\ncase LD_L_B:   R->XX.B.l=R->BC.B.h;break;\r\ncase LD_A_B:   R->AF.B.h=R->BC.B.h;break;\r\ncase LD_xHL_B: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->BC.B.h);break;\r\n\r\ncase LD_B_C:   R->BC.B.h=R->BC.B.l;break;\r\ncase LD_C_C:   R->BC.B.l=R->BC.B.l;break;\r\ncase LD_D_C:   R->DE.B.h=R->BC.B.l;break;\r\ncase LD_E_C:   R->DE.B.l=R->BC.B.l;break;\r\ncase LD_H_C:   R->XX.B.h=R->BC.B.l;break;\r\ncase LD_L_C:   R->XX.B.l=R->BC.B.l;break;\r\ncase LD_A_C:   R->AF.B.h=R->BC.B.l;break;\r\ncase LD_xHL_C: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->BC.B.l);break;\r\n\r\ncase LD_B_D:   R->BC.B.h=R->DE.B.h;break;\r\ncase LD_C_D:   R->BC.B.l=R->DE.B.h;break;\r\ncase LD_D_D:   R->DE.B.h=R->DE.B.h;break;\r\ncase LD_E_D:   R->DE.B.l=R->DE.B.h;break;\r\ncase LD_H_D:   R->XX.B.h=R->DE.B.h;break;\r\ncase LD_L_D:   R->XX.B.l=R->DE.B.h;break;\r\ncase LD_A_D:   R->AF.B.h=R->DE.B.h;break;\r\ncase LD_xHL_D: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->DE.B.h);break;\r\n\r\ncase LD_B_E:   R->BC.B.h=R->DE.B.l;break;\r\ncase LD_C_E:   R->BC.B.l=R->DE.B.l;break;\r\ncase LD_D_E:   R->DE.B.h=R->DE.B.l;break;\r\ncase LD_E_E:   R->DE.B.l=R->DE.B.l;break;\r\ncase LD_H_E:   R->XX.B.h=R->DE.B.l;break;\r\ncase LD_L_E:   R->XX.B.l=R->DE.B.l;break;\r\ncase LD_A_E:   R->AF.B.h=R->DE.B.l;break;\r\ncase LD_xHL_E: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->DE.B.l);break;\r\n\r\ncase LD_B_H:   R->BC.B.h=R->XX.B.h;break;\r\ncase LD_C_H:   R->BC.B.l=R->XX.B.h;break;\r\ncase LD_D_H:   R->DE.B.h=R->XX.B.h;break;\r\ncase LD_E_H:   R->DE.B.l=R->XX.B.h;break;\r\ncase LD_H_H:   R->XX.B.h=R->XX.B.h;break;\r\ncase LD_L_H:   R->XX.B.l=R->XX.B.h;break;\r\ncase LD_A_H:   R->AF.B.h=R->XX.B.h;break;\r\ncase LD_xHL_H: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->HL.B.h);break;\r\n\r\ncase LD_B_L:   R->BC.B.h=R->XX.B.l;break;\r\ncase LD_C_L:   R->BC.B.l=R->XX.B.l;break;\r\ncase LD_D_L:   R->DE.B.h=R->XX.B.l;break;\r\ncase LD_E_L:   R->DE.B.l=R->XX.B.l;break;\r\ncase LD_H_L:   R->XX.B.h=R->XX.B.l;break;\r\ncase LD_L_L:   R->XX.B.l=R->XX.B.l;break;\r\ncase LD_A_L:   R->AF.B.h=R->XX.B.l;break;\r\ncase LD_xHL_L: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->HL.B.l);break;\r\n\r\ncase LD_B_A:   R->BC.B.h=R->AF.B.h;break;\r\ncase LD_C_A:   R->BC.B.l=R->AF.B.h;break;\r\ncase LD_D_A:   R->DE.B.h=R->AF.B.h;break;\r\ncase LD_E_A:   R->DE.B.l=R->AF.B.h;break;\r\ncase LD_H_A:   R->XX.B.h=R->AF.B.h;break;\r\ncase LD_L_A:   R->XX.B.l=R->AF.B.h;break;\r\ncase LD_A_A:   R->AF.B.h=R->AF.B.h;break;\r\ncase LD_xHL_A: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n               WrZ80(J.W,R->AF.B.h);break;\r\n\r\ncase LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;\r\ncase LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;\r\n\r\ncase LD_B_xHL:    R->BC.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\ncase LD_C_xHL:    R->BC.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\ncase LD_D_xHL:    R->DE.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\ncase LD_E_xHL:    R->DE.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\ncase LD_H_xHL:    R->HL.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\ncase LD_L_xHL:    R->HL.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\ncase LD_A_xHL:    R->AF.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;\r\n\r\ncase LD_B_BYTE:   R->BC.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_C_BYTE:   R->BC.B.l=RdZ80(R->PC.W++);break;\r\ncase LD_D_BYTE:   R->DE.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_E_BYTE:   R->DE.B.l=RdZ80(R->PC.W++);break;\r\ncase LD_H_BYTE:   R->XX.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_L_BYTE:   R->XX.B.l=RdZ80(R->PC.W++);break;\r\ncase LD_A_BYTE:   R->AF.B.h=RdZ80(R->PC.W++);break;\r\ncase LD_xHL_BYTE: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);\r\n                  WrZ80(J.W,RdZ80(R->PC.W++));break;\r\n\r\ncase LD_xWORD_HL:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W++,R->XX.B.l);\r\n  WrZ80(J.W,R->XX.B.h);\r\n  break;\r\n\r\ncase LD_HL_xWORD:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->XX.B.l=RdZ80(J.W++);\r\n  R->XX.B.h=RdZ80(J.W);\r\n  break;\r\n\r\ncase LD_A_xWORD:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  R->AF.B.h=RdZ80(J.W);\r\n  break;\r\n\r\ncase LD_xWORD_A:\r\n  J.B.l=RdZ80(R->PC.W++);\r\n  J.B.h=RdZ80(R->PC.W++);\r\n  WrZ80(J.W,R->AF.B.h);\r\n  break;\r\n\r\ncase EX_HL_xSP:\r\n  J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->XX.B.l);\r\n  J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->XX.B.h);\r\n  R->XX.W=J.W;\r\n  break;\r\n\r\ncase DAA:\r\n  J.W=R->AF.B.h;\r\n  if(R->AF.B.l&C_FLAG) J.W|=256;\r\n  if(R->AF.B.l&H_FLAG) J.W|=512;\r\n  if(R->AF.B.l&N_FLAG) J.W|=1024;\r\n  R->AF.W=DAATable[J.W];\r\n  break;\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Debug.cpp",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                         Debug.c                         **/\r\n/**                                                         **/\r\n/** This file contains the built-in debugging routine for   **/\r\n/** the Z80 emulator which is called on each Z80 step when  **/\r\n/** Trap!=0.                                                **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1995-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\n// #define DEBUG\r\n// define changed from \"DEBUG\" to \"MEKA_Z80_DEBUGGER\"\r\n#include \"shared.h\"\r\n\r\n#ifdef MEKA_Z80_DEBUGGER\r\n\r\n#include \"Z80.h\"\r\n#include \"debugger.h\"\r\n\r\n//\r\n// Syntax in mnemonics strings: [OMAR-20050416]\r\n//\r\n//   #h   2-bytes direct value\r\n//   *h   1-byte direct value\r\n//   @h   1-byte relative offset\r\n//   I%   IX/IY\r\n//   ^h   IX/IY 1-byte relative offset\r\n// ???\r\n//\r\n// I'm not sure to understand everything. The code is hell to decipher.\r\n//\r\n\r\nstatic const char *Mnemonics[256] =\r\n{\r\n  \"NOP\",\"LD BC,#h\",\"LD (BC),A\",\"INC BC\",\"INC B\",\"DEC B\",\"LD B,*h\",\"RLCA\",\r\n  \"EX AF,AF'\",\"ADD HL,BC\",\"LD A,(BC)\",\"DEC BC\",\"INC C\",\"DEC C\",\"LD C,*h\",\"RRCA\",\r\n  \"DJNZ @h\",\"LD DE,#h\",\"LD (DE),A\",\"INC DE\",\"INC D\",\"DEC D\",\"LD D,*h\",\"RLA\",\r\n  \"JR @h\",\"ADD HL,DE\",\"LD A,(DE)\",\"DEC DE\",\"INC E\",\"DEC E\",\"LD E,*h\",\"RRA\",\r\n  \"JR NZ,@h\",\"LD HL,#h\",\"LD (#h),HL\",\"INC HL\",\"INC H\",\"DEC H\",\"LD H,*h\",\"DAA\",\r\n  \"JR Z,@h\",\"ADD HL,HL\",\"LD HL,(#h)\",\"DEC HL\",\"INC L\",\"DEC L\",\"LD L,*h\",\"CPL\",\r\n  \"JR NC,@h\",\"LD SP,#h\",\"LD (#h),A\",\"INC SP\",\"INC (HL)\",\"DEC (HL)\",\"LD (HL),*h\",\"SCF\",\r\n  \"JR C,@h\",\"ADD HL,SP\",\"LD A,(#h)\",\"DEC SP\",\"INC A\",\"DEC A\",\"LD A,*h\",\"CCF\",\r\n  \"LD B,B\",\"LD B,C\",\"LD B,D\",\"LD B,E\",\"LD B,H\",\"LD B,L\",\"LD B,(HL)\",\"LD B,A\",\r\n  \"LD C,B\",\"LD C,C\",\"LD C,D\",\"LD C,E\",\"LD C,H\",\"LD C,L\",\"LD C,(HL)\",\"LD C,A\",\r\n  \"LD D,B\",\"LD D,C\",\"LD D,D\",\"LD D,E\",\"LD D,H\",\"LD D,L\",\"LD D,(HL)\",\"LD D,A\",\r\n  \"LD E,B\",\"LD E,C\",\"LD E,D\",\"LD E,E\",\"LD E,H\",\"LD E,L\",\"LD E,(HL)\",\"LD E,A\",\r\n  \"LD H,B\",\"LD H,C\",\"LD H,D\",\"LD H,E\",\"LD H,H\",\"LD H,L\",\"LD H,(HL)\",\"LD H,A\",\r\n  \"LD L,B\",\"LD L,C\",\"LD L,D\",\"LD L,E\",\"LD L,H\",\"LD L,L\",\"LD L,(HL)\",\"LD L,A\",\r\n  \"LD (HL),B\",\"LD (HL),C\",\"LD (HL),D\",\"LD (HL),E\",\"LD (HL),H\",\"LD (HL),L\",\"HALT\",\"LD (HL),A\",\r\n  \"LD A,B\",\"LD A,C\",\"LD A,D\",\"LD A,E\",\"LD A,H\",\"LD A,L\",\"LD A,(HL)\",\"LD A,A\",\r\n  \"ADD B\",\"ADD C\",\"ADD D\",\"ADD E\",\"ADD H\",\"ADD L\",\"ADD (HL)\",\"ADD A\",\r\n  \"ADC B\",\"ADC C\",\"ADC D\",\"ADC E\",\"ADC H\",\"ADC L\",\"ADC (HL)\",\"ADC A\",\r\n  \"SUB B\",\"SUB C\",\"SUB D\",\"SUB E\",\"SUB H\",\"SUB L\",\"SUB (HL)\",\"SUB A\",\r\n  \"SBC B\",\"SBC C\",\"SBC D\",\"SBC E\",\"SBC H\",\"SBC L\",\"SBC (HL)\",\"SBC A\",\r\n  \"AND B\",\"AND C\",\"AND D\",\"AND E\",\"AND H\",\"AND L\",\"AND (HL)\",\"AND A\",\r\n  \"XOR B\",\"XOR C\",\"XOR D\",\"XOR E\",\"XOR H\",\"XOR L\",\"XOR (HL)\",\"XOR A\",\r\n  \"OR B\",\"OR C\",\"OR D\",\"OR E\",\"OR H\",\"OR L\",\"OR (HL)\",\"OR A\",\r\n  \"CP B\",\"CP C\",\"CP D\",\"CP E\",\"CP H\",\"CP L\",\"CP (HL)\",\"CP A\",\r\n  \"RET NZ\",\"POP BC\",\"JP NZ,#h\",\"JP #h\",\"CALL NZ,#h\",\"PUSH BC\",\"ADD *h\",\"RST 00h\",\r\n  \"RET Z\",\"RET\",\"JP Z,#h\",\"PFX_CB\",\"CALL Z,#h\",\"CALL #h\",\"ADC *h\",\"RST 08h\",\r\n  \"RET NC\",\"POP DE\",\"JP NC,#h\",\"OUTA (*h)\",\"CALL NC,#h\",\"PUSH DE\",\"SUB *h\",\"RST 10h\",\r\n  \"RET C\",\"EXX\",\"JP C,#h\",\"INA (*h)\",\"CALL C,#h\",\"PFX_DD\",\"SBC *h\",\"RST 18h\",\r\n  \"RET PO\",\"POP HL\",\"JP PO,#h\",\"EX HL,(SP)\",\"CALL PO,#h\",\"PUSH HL\",\"AND *h\",\"RST 20h\",\r\n  \"RET PE\",\"LD PC,HL\",\"JP PE,#h\",\"EX DE,HL\",\"CALL PE,#h\",\"PFX_ED\",\"XOR *h\",\"RST 28h\",\r\n  \"RET P\",\"POP AF\",\"JP P,#h\",\"DI\",\"CALL P,#h\",\"PUSH AF\",\"OR *h\",\"RST 30h\",\r\n  \"RET M\",\"LD SP,HL\",\"JP M,#h\",\"EI\",\"CALL M,#h\",\"PFX_FD\",\"CP *h\",\"RST 38h\"\r\n};\r\n\r\n\r\n\r\nstatic const char *MnemonicsCB[256] =\r\n{\r\n  \"RLC B\",\"RLC C\",\"RLC D\",\"RLC E\",\"RLC H\",\"RLC L\",\"RLC (HL)\",\"RLC A\",\r\n  \"RRC B\",\"RRC C\",\"RRC D\",\"RRC E\",\"RRC H\",\"RRC L\",\"RRC (HL)\",\"RRC A\",\r\n  \"RL B\",\"RL C\",\"RL D\",\"RL E\",\"RL H\",\"RL L\",\"RL (HL)\",\"RL A\",\r\n  \"RR B\",\"RR C\",\"RR D\",\"RR E\",\"RR H\",\"RR L\",\"RR (HL)\",\"RR A\",\r\n  \"SLA B\",\"SLA C\",\"SLA D\",\"SLA E\",\"SLA H\",\"SLA L\",\"SLA (HL)\",\"SLA A\",\r\n  \"SRA B\",\"SRA C\",\"SRA D\",\"SRA E\",\"SRA H\",\"SRA L\",\"SRA (HL)\",\"SRA A\",\r\n  \"SLL B\",\"SLL C\",\"SLL D\",\"SLL E\",\"SLL H\",\"SLL L\",\"SLL (HL)\",\"SLL A\",\r\n  \"SRL B\",\"SRL C\",\"SRL D\",\"SRL E\",\"SRL H\",\"SRL L\",\"SRL (HL)\",\"SRL A\",\r\n  \"BIT 0,B\",\"BIT 0,C\",\"BIT 0,D\",\"BIT 0,E\",\"BIT 0,H\",\"BIT 0,L\",\"BIT 0,(HL)\",\"BIT 0,A\",\r\n  \"BIT 1,B\",\"BIT 1,C\",\"BIT 1,D\",\"BIT 1,E\",\"BIT 1,H\",\"BIT 1,L\",\"BIT 1,(HL)\",\"BIT 1,A\",\r\n  \"BIT 2,B\",\"BIT 2,C\",\"BIT 2,D\",\"BIT 2,E\",\"BIT 2,H\",\"BIT 2,L\",\"BIT 2,(HL)\",\"BIT 2,A\",\r\n  \"BIT 3,B\",\"BIT 3,C\",\"BIT 3,D\",\"BIT 3,E\",\"BIT 3,H\",\"BIT 3,L\",\"BIT 3,(HL)\",\"BIT 3,A\",\r\n  \"BIT 4,B\",\"BIT 4,C\",\"BIT 4,D\",\"BIT 4,E\",\"BIT 4,H\",\"BIT 4,L\",\"BIT 4,(HL)\",\"BIT 4,A\",\r\n  \"BIT 5,B\",\"BIT 5,C\",\"BIT 5,D\",\"BIT 5,E\",\"BIT 5,H\",\"BIT 5,L\",\"BIT 5,(HL)\",\"BIT 5,A\",\r\n  \"BIT 6,B\",\"BIT 6,C\",\"BIT 6,D\",\"BIT 6,E\",\"BIT 6,H\",\"BIT 6,L\",\"BIT 6,(HL)\",\"BIT 6,A\",\r\n  \"BIT 7,B\",\"BIT 7,C\",\"BIT 7,D\",\"BIT 7,E\",\"BIT 7,H\",\"BIT 7,L\",\"BIT 7,(HL)\",\"BIT 7,A\",\r\n  \"RES 0,B\",\"RES 0,C\",\"RES 0,D\",\"RES 0,E\",\"RES 0,H\",\"RES 0,L\",\"RES 0,(HL)\",\"RES 0,A\",\r\n  \"RES 1,B\",\"RES 1,C\",\"RES 1,D\",\"RES 1,E\",\"RES 1,H\",\"RES 1,L\",\"RES 1,(HL)\",\"RES 1,A\",\r\n  \"RES 2,B\",\"RES 2,C\",\"RES 2,D\",\"RES 2,E\",\"RES 2,H\",\"RES 2,L\",\"RES 2,(HL)\",\"RES 2,A\",\r\n  \"RES 3,B\",\"RES 3,C\",\"RES 3,D\",\"RES 3,E\",\"RES 3,H\",\"RES 3,L\",\"RES 3,(HL)\",\"RES 3,A\",\r\n  \"RES 4,B\",\"RES 4,C\",\"RES 4,D\",\"RES 4,E\",\"RES 4,H\",\"RES 4,L\",\"RES 4,(HL)\",\"RES 4,A\",\r\n  \"RES 5,B\",\"RES 5,C\",\"RES 5,D\",\"RES 5,E\",\"RES 5,H\",\"RES 5,L\",\"RES 5,(HL)\",\"RES 5,A\",\r\n  \"RES 6,B\",\"RES 6,C\",\"RES 6,D\",\"RES 6,E\",\"RES 6,H\",\"RES 6,L\",\"RES 6,(HL)\",\"RES 6,A\",\r\n  \"RES 7,B\",\"RES 7,C\",\"RES 7,D\",\"RES 7,E\",\"RES 7,H\",\"RES 7,L\",\"RES 7,(HL)\",\"RES 7,A\",\r\n  \"SET 0,B\",\"SET 0,C\",\"SET 0,D\",\"SET 0,E\",\"SET 0,H\",\"SET 0,L\",\"SET 0,(HL)\",\"SET 0,A\",\r\n  \"SET 1,B\",\"SET 1,C\",\"SET 1,D\",\"SET 1,E\",\"SET 1,H\",\"SET 1,L\",\"SET 1,(HL)\",\"SET 1,A\",\r\n  \"SET 2,B\",\"SET 2,C\",\"SET 2,D\",\"SET 2,E\",\"SET 2,H\",\"SET 2,L\",\"SET 2,(HL)\",\"SET 2,A\",\r\n  \"SET 3,B\",\"SET 3,C\",\"SET 3,D\",\"SET 3,E\",\"SET 3,H\",\"SET 3,L\",\"SET 3,(HL)\",\"SET 3,A\",\r\n  \"SET 4,B\",\"SET 4,C\",\"SET 4,D\",\"SET 4,E\",\"SET 4,H\",\"SET 4,L\",\"SET 4,(HL)\",\"SET 4,A\",\r\n  \"SET 5,B\",\"SET 5,C\",\"SET 5,D\",\"SET 5,E\",\"SET 5,H\",\"SET 5,L\",\"SET 5,(HL)\",\"SET 5,A\",\r\n  \"SET 6,B\",\"SET 6,C\",\"SET 6,D\",\"SET 6,E\",\"SET 6,H\",\"SET 6,L\",\"SET 6,(HL)\",\"SET 6,A\",\r\n  \"SET 7,B\",\"SET 7,C\",\"SET 7,D\",\"SET 7,E\",\"SET 7,H\",\"SET 7,L\",\"SET 7,(HL)\",\"SET 7,A\"\r\n};\r\n\r\nstatic const char *MnemonicsED[256] =\r\n{\r\n  \"DB EDh,00h\",\"DB EDh,01h\",\"DB EDh,02h\",\"DB EDh,03h\",\r\n  \"DB EDh,04h\",\"DB EDh,05h\",\"DB EDh,06h\",\"DB EDh,07h\",\r\n  \"DB EDh,08h\",\"DB EDh,09h\",\"DB EDh,0Ah\",\"DB EDh,0Bh\",\r\n  \"DB EDh,0Ch\",\"DB EDh,0Dh\",\"DB EDh,0Eh\",\"DB EDh,0Fh\",\r\n  \"DB EDh,10h\",\"DB EDh,11h\",\"DB EDh,12h\",\"DB EDh,13h\",\r\n  \"DB EDh,14h\",\"DB EDh,15h\",\"DB EDh,16h\",\"DB EDh,17h\",\r\n  \"DB EDh,18h\",\"DB EDh,19h\",\"DB EDh,1Ah\",\"DB EDh,1Bh\",\r\n  \"DB EDh,1Ch\",\"DB EDh,1Dh\",\"DB EDh,1Eh\",\"DB EDh,1Fh\",\r\n  \"DB EDh,20h\",\"DB EDh,21h\",\"DB EDh,22h\",\"DB EDh,23h\",\r\n  \"DB EDh,24h\",\"DB EDh,25h\",\"DB EDh,26h\",\"DB EDh,27h\",\r\n  \"DB EDh,28h\",\"DB EDh,29h\",\"DB EDh,2Ah\",\"DB EDh,2Bh\",\r\n  \"DB EDh,2Ch\",\"DB EDh,2Dh\",\"DB EDh,2Eh\",\"DB EDh,2Fh\",\r\n  \"DB EDh,30h\",\"DB EDh,31h\",\"DB EDh,32h\",\"DB EDh,33h\",\r\n  \"DB EDh,34h\",\"DB EDh,35h\",\"DB EDh,36h\",\"DB EDh,37h\",\r\n  \"DB EDh,38h\",\"DB EDh,39h\",\"DB EDh,3Ah\",\"DB EDh,3Bh\",\r\n  \"DB EDh,3Ch\",\"DB EDh,3Dh\",\"DB EDh,3Eh\",\"DB EDh,3Fh\",\r\n  \"IN B,(C)\",\"OUT (C),B\",\"SBC HL,BC\",\"LD (#h),BC\",\r\n  \"NEG\",\"RETN\",\"IM 0\",\"LD I,A\",\r\n  \"IN C,(C)\",\"OUT (C),C\",\"ADC HL,BC\",\"LD BC,(#h)\",\r\n  \"DB EDh,4Ch\",\"RETI\",\"DB EDh,4Eh\",\"LD R,A\",\r\n  \"IN D,(C)\",\"OUT (C),D\",\"SBC HL,DE\",\"LD (#h),DE\",\r\n  \"DB EDh,54h\",\"DB EDh,55h\",\"IM 1\",\"LD A,I\",\r\n  \"IN E,(C)\",\"OUT (C),E\",\"ADC HL,DE\",\"LD DE,(#h)\",\r\n  \"DB EDh,5Ch\",\"DB EDh,5Dh\",\"IM 2\",\"LD A,R\",\r\n  \"IN H,(C)\",\"OUT (C),H\",\"SBC HL,HL\",\"LD (#h),HL\",\r\n  \"DB EDh,64h\",\"DB EDh,65h\",\"DB EDh,66h\",\"RRD\",\r\n  \"IN L,(C)\",\"OUT (C),L\",\"ADC HL,HL\",\"LD HL,(#h)\",\r\n  \"DB EDh,6Ch\",\"DB EDh,6Dh\",\"DB EDh,6Eh\",\"RLD\",\r\n  \"IN F,(C)\",\"DB EDh,71h\",\"SBC HL,SP\",\"LD (#h),SP\",\r\n  \"DB EDh,74h\",\"DB EDh,75h\",\"DB EDh,76h\",\"DB EDh,77h\",\r\n  \"IN A,(C)\",\"OUT (C),A\",\"ADC HL,SP\",\"LD SP,(#h)\",\r\n  \"DB EDh,7Ch\",\"DB EDh,7Dh\",\"DB EDh,7Eh\",\"DB EDh,7Fh\",\r\n  \"DB EDh,80h\",\"DB EDh,81h\",\"DB EDh,82h\",\"DB EDh,83h\",\r\n  \"DB EDh,84h\",\"DB EDh,85h\",\"DB EDh,86h\",\"DB EDh,87h\",\r\n  \"DB EDh,88h\",\"DB EDh,89h\",\"DB EDh,8Ah\",\"DB EDh,8Bh\",\r\n  \"DB EDh,8Ch\",\"DB EDh,8Dh\",\"DB EDh,8Eh\",\"DB EDh,8Fh\",\r\n  \"DB EDh,90h\",\"DB EDh,91h\",\"DB EDh,92h\",\"DB EDh,93h\",\r\n  \"DB EDh,94h\",\"DB EDh,95h\",\"DB EDh,96h\",\"DB EDh,97h\",\r\n  \"DB EDh,98h\",\"DB EDh,99h\",\"DB EDh,9Ah\",\"DB EDh,9Bh\",\r\n  \"DB EDh,9Ch\",\"DB EDh,9Dh\",\"DB EDh,9Eh\",\"DB EDh,9Fh\",\r\n  \"LDI\",\"CPI\",\"INI\",\"OUTI\",\r\n  \"DB EDh,A4h\",\"DB EDh,A5h\",\"DB EDh,A6h\",\"DB EDh,A7h\",\r\n  \"LDD\",\"CPD\",\"IND\",\"OUTD\",\r\n  \"DB EDh,ACh\",\"DB EDh,ADh\",\"DB EDh,AEh\",\"DB EDh,AFh\",\r\n  \"LDIR\",\"CPIR\",\"INIR\",\"OTIR\",\r\n  \"DB EDh,B4h\",\"DB EDh,B5h\",\"DB EDh,B6h\",\"DB EDh,B7h\",\r\n  \"LDDR\",\"CPDR\",\"INDR\",\"OTDR\",\r\n  \"DB EDh,BCh\",\"DB EDh,BDh\",\"DB EDh,BEh\",\"DB EDh,BFh\",\r\n  \"DB EDh,C0h\",\"DB EDh,C1h\",\"DB EDh,C2h\",\"DB EDh,C3h\",\r\n  \"DB EDh,C4h\",\"DB EDh,C5h\",\"DB EDh,C6h\",\"DB EDh,C7h\",\r\n  \"DB EDh,C8h\",\"DB EDh,C9h\",\"DB EDh,CAh\",\"DB EDh,CBh\",\r\n  \"DB EDh,CCh\",\"DB EDh,CDh\",\"DB EDh,CEh\",\"DB EDh,CFh\",\r\n  \"DB EDh,D0h\",\"DB EDh,D1h\",\"DB EDh,D2h\",\"DB EDh,D3h\",\r\n  \"DB EDh,D4h\",\"DB EDh,D5h\",\"DB EDh,D6h\",\"DB EDh,D7h\",\r\n  \"DB EDh,D8h\",\"DB EDh,D9h\",\"DB EDh,DAh\",\"DB EDh,DBh\",\r\n  \"DB EDh,DCh\",\"DB EDh,DDh\",\"DB EDh,DEh\",\"DB EDh,DFh\",\r\n  \"DB EDh,E0h\",\"DB EDh,E1h\",\"DB EDh,E2h\",\"DB EDh,E3h\",\r\n  \"DB EDh,E4h\",\"DB EDh,E5h\",\"DB EDh,E6h\",\"DB EDh,E7h\",\r\n  \"DB EDh,E8h\",\"DB EDh,E9h\",\"DB EDh,EAh\",\"DB EDh,EBh\",\r\n  \"DB EDh,ECh\",\"DB EDh,EDh\",\"DB EDh,EEh\",\"DB EDh,EFh\",\r\n  \"DB EDh,F0h\",\"DB EDh,F1h\",\"DB EDh,F2h\",\"DB EDh,F3h\",\r\n  \"DB EDh,F4h\",\"DB EDh,F5h\",\"DB EDh,F6h\",\"DB EDh,F7h\",\r\n  \"DB EDh,F8h\",\"DB EDh,F9h\",\"DB EDh,FAh\",\"DB EDh,FBh\",\r\n  \"DB EDh,FCh\",\"DB EDh,FDh\",\"DB EDh,FEh\",\"DB EDh,FFh\"\r\n};\r\n\r\nstatic const char *MnemonicsXX[256] =\r\n{\r\n  \"NOP\",\"LD BC,#h\",\"LD (BC),A\",\"INC BC\",\"INC B\",\"DEC B\",\"LD B,*h\",\"RLCA\",\r\n  \"EX AF,AF'\",\"ADD I%,BC\",\"LD A,(BC)\",\"DEC BC\",\"INC C\",\"DEC C\",\"LD C,*h\",\"RRCA\",\r\n  \"DJNZ @h\",\"LD DE,#h\",\"LD (DE),A\",\"INC DE\",\"INC D\",\"DEC D\",\"LD D,*h\",\"RLA\",\r\n  \"JR @h\",\"ADD I%,DE\",\"LD A,(DE)\",\"DEC DE\",\"INC E\",\"DEC E\",\"LD E,*h\",\"RRA\",\r\n  \"JR NZ,@h\",\"LD I%,#h\",\"LD (#h),I%\",\"INC I%\",\"INC I%h\",\"DEC I%h\",\"LD I%h,*h\",\"DAA\",\r\n  \"JR Z,@h\",\"ADD I%,I%\",\"LD I%,(#h)\",\"DEC I%\",\"INC I%l\",\"DEC I%l\",\"LD I%l,*h\",\"CPL\",\r\n  \"JR NC,@h\",\"LD SP,#h\",\"LD (#h),A\",\"INC SP\",\"INC (I%^h)\",\"DEC (I%^h)\",\"LD (I%^h),*h\",\"SCF\",\r\n  \"JR C,@h\",\"ADD I%,SP\",\"LD A,(#h)\",\"DEC SP\",\"INC A\",\"DEC A\",\"LD A,*h\",\"CCF\",\r\n  \"LD B,B\",\"LD B,C\",\"LD B,D\",\"LD B,E\",\"LD B,I%h\",\"LD B,I%l\",\"LD B,(I%^h)\",\"LD B,A\",\r\n  \"LD C,B\",\"LD C,C\",\"LD C,D\",\"LD C,E\",\"LD C,I%h\",\"LD C,I%l\",\"LD C,(I%^h)\",\"LD C,A\",\r\n  \"LD D,B\",\"LD D,C\",\"LD D,D\",\"LD D,E\",\"LD D,I%h\",\"LD D,I%l\",\"LD D,(I%^h)\",\"LD D,A\",\r\n  \"LD E,B\",\"LD E,C\",\"LD E,D\",\"LD E,E\",\"LD E,I%h\",\"LD E,I%l\",\"LD E,(I%^h)\",\"LD E,A\",\r\n  \"LD I%h,B\",\"LD I%h,C\",\"LD I%h,D\",\"LD I%h,E\",\"LD I%h,I%h\",\"LD I%h,I%l\",\"LD H,(I%^h)\",\"LD I%h,A\",\r\n  \"LD I%l,B\",\"LD I%l,C\",\"LD I%l,D\",\"LD I%l,E\",\"LD I%l,I%h\",\"LD I%l,I%l\",\"LD L,(I%^h)\",\"LD I%l,A\",\r\n  \"LD (I%^h),B\",\"LD (I%^h),C\",\"LD (I%^h),D\",\"LD (I%^h),E\",\"LD (I%^h),H\",\"LD (I%^h),L\",\"HALT\",\"LD (I%^h),A\",\r\n  \"LD A,B\",\"LD A,C\",\"LD A,D\",\"LD A,E\",\"LD A,I%h\",\"LD A,I%l\",\"LD A,(I%^h)\",\"LD A,A\",\r\n  \"ADD B\",\"ADD C\",\"ADD D\",\"ADD E\",\"ADD I%h\",\"ADD I%l\",\"ADD (I%^h)\",\"ADD A\",\r\n  \"ADC B\",\"ADC C\",\"ADC D\",\"ADC E\",\"ADC I%h\",\"ADC I%l\",\"ADC (I%^h)\",\"ADC,A\",\r\n  \"SUB B\",\"SUB C\",\"SUB D\",\"SUB E\",\"SUB I%h\",\"SUB I%l\",\"SUB (I%^h)\",\"SUB A\",\r\n  \"SBC B\",\"SBC C\",\"SBC D\",\"SBC E\",\"SBC I%h\",\"SBC I%l\",\"SBC (I%^h)\",\"SBC A\",\r\n  \"AND B\",\"AND C\",\"AND D\",\"AND E\",\"AND I%h\",\"AND I%l\",\"AND (I%^h)\",\"AND A\",\r\n  \"XOR B\",\"XOR C\",\"XOR D\",\"XOR E\",\"XOR I%h\",\"XOR I%l\",\"XOR (I%^h)\",\"XOR A\",\r\n  \"OR B\",\"OR C\",\"OR D\",\"OR E\",\"OR I%h\",\"OR I%l\",\"OR (I%^h)\",\"OR A\",\r\n  \"CP B\",\"CP C\",\"CP D\",\"CP E\",\"CP I%h\",\"CP I%l\",\"CP (I%^h)\",\"CP A\",\r\n  \"RET NZ\",\"POP BC\",\"JP NZ,#h\",\"JP #h\",\"CALL NZ,#h\",\"PUSH BC\",\"ADD *h\",\"RST 00h\",\r\n  \"RET Z\",\"RET\",\"JP Z,#h\",\"PFX_CB\",\"CALL Z,#h\",\"CALL #h\",\"ADC *h\",\"RST 08h\",\r\n  \"RET NC\",\"POP DE\",\"JP NC,#h\",\"OUTA (*h)\",\"CALL NC,#h\",\"PUSH DE\",\"SUB *h\",\"RST 10h\",\r\n  \"RET C\",\"EXX\",\"JP C,#h\",\"INA (*h)\",\"CALL C,#h\",\"PFX_DD\",\"SBC *h\",\"RST 18h\",\r\n  \"RET PO\",\"POP I%\",\"JP PO,#h\",\"EX I%,(SP)\",\"CALL PO,#h\",\"PUSH I%\",\"AND *h\",\"RST 20h\",\r\n  \"RET PE\",\"LD PC,I%\",\"JP PE,#h\",\"EX DE,I%\",\"CALL PE,#h\",\"PFX_ED\",\"XOR *h\",\"RST 28h\",\r\n  \"RET P\",\"POP AF\",\"JP P,#h\",\"DI\",\"CALL P,#h\",\"PUSH AF\",\"OR *h\",\"RST 30h\",\r\n  \"RET M\",\"LD SP,I%\",\"JP M,#h\",\"EI\",\"CALL M,#h\",\"PFX_FD\",\"CP *h\",\"RST 38h\"\r\n};\r\n\r\nstatic const char *MnemonicsXCB[256] =\r\n{\r\n  \"RLC B\",\"RLC C\",\"RLC D\",\"RLC E\",\"RLC H\",\"RLC L\",\"RLC (I%@h)\",\"RLC A\",\r\n  \"RRC B\",\"RRC C\",\"RRC D\",\"RRC E\",\"RRC H\",\"RRC L\",\"RRC (I%@h)\",\"RRC A\",\r\n  \"RL B\",\"RL C\",\"RL D\",\"RL E\",\"RL H\",\"RL L\",\"RL (I%@h)\",\"RL A\",\r\n  \"RR B\",\"RR C\",\"RR D\",\"RR E\",\"RR H\",\"RR L\",\"RR (I%@h)\",\"RR A\",\r\n  \"SLA B\",\"SLA C\",\"SLA D\",\"SLA E\",\"SLA H\",\"SLA L\",\"SLA (I%@h)\",\"SLA A\",\r\n  \"SRA B\",\"SRA C\",\"SRA D\",\"SRA E\",\"SRA H\",\"SRA L\",\"SRA (I%@h)\",\"SRA A\",\r\n  \"SLL B\",\"SLL C\",\"SLL D\",\"SLL E\",\"SLL H\",\"SLL L\",\"SLL (I%@h)\",\"SLL A\",\r\n  \"SRL B\",\"SRL C\",\"SRL D\",\"SRL E\",\"SRL H\",\"SRL L\",\"SRL (I%@h)\",\"SRL A\",\r\n  \"BIT 0,B\",\"BIT 0,C\",\"BIT 0,D\",\"BIT 0,E\",\"BIT 0,H\",\"BIT 0,L\",\"BIT 0,(I%@h)\",\"BIT 0,A\",\r\n  \"BIT 1,B\",\"BIT 1,C\",\"BIT 1,D\",\"BIT 1,E\",\"BIT 1,H\",\"BIT 1,L\",\"BIT 1,(I%@h)\",\"BIT 1,A\",\r\n  \"BIT 2,B\",\"BIT 2,C\",\"BIT 2,D\",\"BIT 2,E\",\"BIT 2,H\",\"BIT 2,L\",\"BIT 2,(I%@h)\",\"BIT 2,A\",\r\n  \"BIT 3,B\",\"BIT 3,C\",\"BIT 3,D\",\"BIT 3,E\",\"BIT 3,H\",\"BIT 3,L\",\"BIT 3,(I%@h)\",\"BIT 3,A\",\r\n  \"BIT 4,B\",\"BIT 4,C\",\"BIT 4,D\",\"BIT 4,E\",\"BIT 4,H\",\"BIT 4,L\",\"BIT 4,(I%@h)\",\"BIT 4,A\",\r\n  \"BIT 5,B\",\"BIT 5,C\",\"BIT 5,D\",\"BIT 5,E\",\"BIT 5,H\",\"BIT 5,L\",\"BIT 5,(I%@h)\",\"BIT 5,A\",\r\n  \"BIT 6,B\",\"BIT 6,C\",\"BIT 6,D\",\"BIT 6,E\",\"BIT 6,H\",\"BIT 6,L\",\"BIT 6,(I%@h)\",\"BIT 6,A\",\r\n  \"BIT 7,B\",\"BIT 7,C\",\"BIT 7,D\",\"BIT 7,E\",\"BIT 7,H\",\"BIT 7,L\",\"BIT 7,(I%@h)\",\"BIT 7,A\",\r\n  \"RES 0,B\",\"RES 0,C\",\"RES 0,D\",\"RES 0,E\",\"RES 0,H\",\"RES 0,L\",\"RES 0,(I%@h)\",\"RES 0,A\",\r\n  \"RES 1,B\",\"RES 1,C\",\"RES 1,D\",\"RES 1,E\",\"RES 1,H\",\"RES 1,L\",\"RES 1,(I%@h)\",\"RES 1,A\",\r\n  \"RES 2,B\",\"RES 2,C\",\"RES 2,D\",\"RES 2,E\",\"RES 2,H\",\"RES 2,L\",\"RES 2,(I%@h)\",\"RES 2,A\",\r\n  \"RES 3,B\",\"RES 3,C\",\"RES 3,D\",\"RES 3,E\",\"RES 3,H\",\"RES 3,L\",\"RES 3,(I%@h)\",\"RES 3,A\",\r\n  \"RES 4,B\",\"RES 4,C\",\"RES 4,D\",\"RES 4,E\",\"RES 4,H\",\"RES 4,L\",\"RES 4,(I%@h)\",\"RES 4,A\",\r\n  \"RES 5,B\",\"RES 5,C\",\"RES 5,D\",\"RES 5,E\",\"RES 5,H\",\"RES 5,L\",\"RES 5,(I%@h)\",\"RES 5,A\",\r\n  \"RES 6,B\",\"RES 6,C\",\"RES 6,D\",\"RES 6,E\",\"RES 6,H\",\"RES 6,L\",\"RES 6,(I%@h)\",\"RES 6,A\",\r\n  \"RES 7,B\",\"RES 7,C\",\"RES 7,D\",\"RES 7,E\",\"RES 7,H\",\"RES 7,L\",\"RES 7,(I%@h)\",\"RES 7,A\",\r\n  \"SET 0,B\",\"SET 0,C\",\"SET 0,D\",\"SET 0,E\",\"SET 0,H\",\"SET 0,L\",\"SET 0,(I%@h)\",\"SET 0,A\",\r\n  \"SET 1,B\",\"SET 1,C\",\"SET 1,D\",\"SET 1,E\",\"SET 1,H\",\"SET 1,L\",\"SET 1,(I%@h)\",\"SET 1,A\",\r\n  \"SET 2,B\",\"SET 2,C\",\"SET 2,D\",\"SET 2,E\",\"SET 2,H\",\"SET 2,L\",\"SET 2,(I%@h)\",\"SET 2,A\",\r\n  \"SET 3,B\",\"SET 3,C\",\"SET 3,D\",\"SET 3,E\",\"SET 3,H\",\"SET 3,L\",\"SET 3,(I%@h)\",\"SET 3,A\",\r\n  \"SET 4,B\",\"SET 4,C\",\"SET 4,D\",\"SET 4,E\",\"SET 4,H\",\"SET 4,L\",\"SET 4,(I%@h)\",\"SET 4,A\",\r\n  \"SET 5,B\",\"SET 5,C\",\"SET 5,D\",\"SET 5,E\",\"SET 5,H\",\"SET 5,L\",\"SET 5,(I%@h)\",\"SET 5,A\",\r\n  \"SET 6,B\",\"SET 6,C\",\"SET 6,D\",\"SET 6,E\",\"SET 6,H\",\"SET 6,L\",\"SET 6,(I%@h)\",\"SET 6,A\",\r\n  \"SET 7,B\",\"SET 7,C\",\"SET 7,D\",\"SET 7,E\",\"SET 7,H\",\"SET 7,L\",\"SET 7,(I%@h)\",\"SET 7,A\"\r\n};\r\n\r\nstatic bool Z80_IsModifyingPC(const char* m)\r\n{\r\n\tif (*m == 'j')\r\n\t\treturn true;\r\n\tif (strncmp(m, \"djnz\", 4)==0) \r\n\t\treturn true;\r\n\tif (strncmp(m, \"call\", 4)==0) \r\n\t\treturn true;\r\n\tif (strncmp(m, \"ret\", 3)==0)\r\n\t\treturn true;\r\n\treturn false;\r\n}\r\n\r\nvoid Z80_Disassemble_GetDecoratedSymbolFromAddress(const char* mnemonic, u16 addr, char* buf, int buf_len, bool display_symbols, bool display_addr)\r\n{\r\n\tconst t_debugger_symbol* symbol = NULL;\r\n\tif (display_symbols)\r\n\t{\r\n\t\tif (mnemonic && Z80_IsModifyingPC(mnemonic))\r\n\t\t\tsymbol = Debugger_Symbols_GetClosestPreviousByAddr(addr, 64);\t\t// too misleading for data address so only use for code address\r\n\t\telse\r\n\t\t\tsymbol = Debugger_Symbols_GetLastByAddr(addr);\r\n\t}\r\n\r\n\tif (symbol != NULL)\r\n\t{\r\n\t\tif (display_addr)\r\n\t\t{\r\n\t\t\tif (symbol->cpu_addr != addr)\r\n\t\t\t\tsnprintf(buf, buf_len,\"%s+%Xh/%04Xh\", symbol->name, addr-symbol->cpu_addr, addr);\r\n\t\t\telse\r\n\t\t\t\tsnprintf(buf, buf_len,\"%s/%04Xh\", symbol->name, addr);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (symbol->cpu_addr != addr)\r\n\t\t\t\tsnprintf(buf, buf_len,\"%s+%Xh\", symbol->name, addr-symbol->cpu_addr);\r\n\t\t\telse\r\n\t\t\t\tsnprintf(buf, buf_len,\"%s\", symbol->name);\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsnprintf(buf, buf_len,\"%04Xh\", addr);\r\n\t}\r\n}\r\n\r\n/** DAsm() ***************************************************/\r\n/** DAsm() will disassemble the code at adress A and put    **/\r\n/** the output text into S. It will return the number of    **/\r\n/** bytes disassembled.                                     **/\r\n/*************************************************************/\r\nint     Z80_Disassemble(char *S, word A, bool display_symbols, bool display_symbols_for_current_index_registers, bool resolve_indirect_offsets)\r\n{\r\n    char  R[256], H[256], C;\r\n    byte  Offset = 0;\r\n\tbool  has_offset = false;\r\n    word  B;\r\n    int   relative_offset_base = 0;  // 0 : from PC, 1 : from IX, 2 : from IY\r\n\r\n    B = A;\r\n    C = '\\0';\r\n    \r\n\tconst char *T_const = NULL;\r\n    switch (RdZ80_NoHook(B))\r\n    {\r\n    case 0xCB: B++;T_const=MnemonicsCB[RdZ80_NoHook(B++&0xFFFF)];break;\r\n    case 0xED: B++;T_const=MnemonicsED[RdZ80_NoHook(B++&0xFFFF)];break;\r\n    case 0xDD: B++;C='x';\r\n        if (RdZ80_NoHook(B&0xFFFF)!=0xCB) \r\n            T_const=MnemonicsXX[RdZ80_NoHook(B++&0xFFFF)];\r\n        else\r\n        { B++;Offset=RdZ80_NoHook(B++&0xFFFF);has_offset=true;T_const=MnemonicsXCB[RdZ80_NoHook(B++&0xFFFF)]; }\r\n        break;\r\n    case 0xFD: B++;C='y';\r\n        if(RdZ80_NoHook(B&0xFFFF)!=0xCB) \r\n            T_const=MnemonicsXX[RdZ80_NoHook(B++&0xFFFF)];\r\n        else\r\n        { B++;Offset=RdZ80_NoHook(B++&0xFFFF);has_offset=true;T_const=MnemonicsXCB[RdZ80_NoHook(B++&0xFFFF)]; }\r\n        break;\r\n    default:   \r\n        T_const=Mnemonics[RdZ80_NoHook(B++&0xFFFF)];\r\n        break;\r\n    }\r\n\tchar T[32];\r\n\tstrcpy(T, T_const);\r\n\tStrLower(T);\r\n\r\n\tchar *P;\r\n    if ((P=strchr(T,'^')) != NULL)\r\n    {\r\n\t\tassert(!has_offset);\t// Should never get a ^ in the DD CB and FD CB paths\r\n\t\tif (S != NULL)\r\n\t\t{\r\n\t\t\tOffset = RdZ80_NoHook(B&0xFFFF);\r\n\r\n\t\t\t// convert 0xFF to -0x01 for nicer display\r\n\t\t\tconst char offset_sign = (Offset & 0x80) ? '-' : '+';\r\n\t\t\tconst byte offset_abs = (Offset & 0x80) ? 256 - Offset : Offset;\r\n\r\n\t\t\tif (resolve_indirect_offsets)\r\n\t\t\t{\r\n\t\t\t\tif (display_symbols_for_current_index_registers)\r\n\t\t\t\t{\r\n\t\t\t\t\t// P+2: skip the 'h' in the instruction\r\n\t\t\t\t\tconst u16 addr = ((C == 'x') ? sms.R.IX.W : sms.R.IY.W) + (signed char)Offset;\r\n\t\t\t\t\tZ80_Disassemble_GetDecoratedSymbolFromAddress(NULL, addr, H, 256, display_symbols, false);\t\t// Don't display full address because it is obvious (for IX/IY being typically stable)\r\n\t\t\t\t\tsnprintf(R, 256, \"%.*s%c%d=%s%s\", (int)(P-T), T, offset_sign, offset_abs, H, P+2);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// P+2: skip the 'h' in the instruction\r\n\t\t\t\t\tsnprintf(R, 256, \"%.*s%c%d%s\", (int)(P-T), T, offset_sign, offset_abs, P+2);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsnprintf(R, 256, \"%.*s%c%d%s\", (int)(P-T), T, offset_sign, offset_abs, P+2);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tstrcpy(R,T);\r\n\t\t}\r\n\t\tB++;\r\n\t}\r\n    else \r\n\t{\r\n        strcpy(R,T);\r\n\t}\r\n\r\n    if ((P=strchr(R,'%')) != NULL) \r\n    {\r\n        *P=C;\r\n        if (C == 'x')\r\n            relative_offset_base = 1;\r\n        else if (C == 'y')\r\n            relative_offset_base = 2;\r\n    }\r\n\r\n    if ((P=strchr(R,'*')) != NULL)\r\n    {\r\n        if (S != NULL)\r\n        {\r\n            strncpy(S,R,P-R);S[P-R]='\\0';\r\n            sprintf(H,\"%02Xh\",RdZ80_NoHook(B&0xFFFF));\r\n            strcat(S,H);strcat(S,P+2);\r\n        }\r\n        B++;\r\n    }\r\n    else\r\n\t{\r\n        if ((P=strchr(R,'@')) != NULL)\r\n        {\r\n            if (S != NULL)\r\n            {\r\n                if(!has_offset) \r\n                    Offset=RdZ80_NoHook(B&0xFFFF);\r\n\r\n\t\t\t\t// convert 0xFF to -0x01 for nicer display\r\n\t\t\t\tconst char offset_sign = (Offset & 0x80) ? '-' : '+';\r\n\t\t\t\tconst byte offset_abs = (Offset & 0x80) ? 256 - Offset : Offset;\r\n\r\n                if (resolve_indirect_offsets)\r\n                {\r\n\t\t\t\t\t// P+2: skip the 'h' in the instruction\r\n\t\t\t\t\tif (relative_offset_base == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst u16 addr = (B+1) + (signed char)Offset;\r\n\t\t\t\t\t\tZ80_Disassemble_GetDecoratedSymbolFromAddress(R, addr, H, 256, display_symbols, true);\r\n\t\t\t\t\t\tsnprintf(S, 255, \"%.*s%c%02Xh (%s)%s\", (int)(P-R), R, offset_sign, offset_abs, H, P+2);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst u16 addr = ((relative_offset_base == 1) ? sms.R.IX.W : sms.R.IY.W) + (signed char)Offset;\r\n\t\t\t\t\t\tZ80_Disassemble_GetDecoratedSymbolFromAddress(R, addr, H, 256, display_symbols, false);\t// Don't display full address because it is obvious (for IX/IY being typically stable)\r\n\t\t\t\t\t\tsnprintf(S, 255, \"%.*s%c%d=%s%s\", (int)(P-R), R, offset_sign, offset_abs, H, P+2);\r\n\t\t\t\t\t}\r\n                }\r\n                else\r\n                {\r\n\t\t\t\t\t// P+2: skip the 'h' in the instruction\r\n\t\t\t\t\tsnprintf(S, 256, \"%.*s%c%02Xh%s\", (int)(P-R), R, offset_sign, offset_abs, P+2);\r\n                }\r\n            }\r\n\t\t\tif(!has_offset)\r\n\t\t\t\tB++;\r\n        }\r\n\t\telse if((P=strchr(R,'#')) != NULL)\r\n\t\t{\r\n\t\t\tif (S != NULL)\r\n\t\t\t{\r\n\t\t\t\tconst u16 addr = RdZ80_NoHook(B&0xFFFF)+256*RdZ80_NoHook((B+1)&0xFFFF);\r\n\t\t\t\tZ80_Disassemble_GetDecoratedSymbolFromAddress(R, addr, H, 256, display_symbols, true);\r\n\t\t\t\tsnprintf(S, 256, \"%.*s%s%s\", (int)(P-R), R, H, P+2);\r\n\t\t\t}\r\n\t\t\tB += 2;\r\n\t\t}\r\n\t\telse if(strncmp(R,\"rst \",4)==0)\r\n\t\t{\r\n\t\t\tif (S != NULL)\r\n\t\t\t{\r\n\t\t\t\tconst u16 addr = (u16)Debugger_Eval_ParseIntegerHex(R+4);\r\n\t\t\t\tconst t_debugger_symbol* symbol = display_symbols ? Debugger_Symbols_GetLastByAddr(addr) : NULL;\r\n\t\t\t\tif (symbol != NULL)\r\n\t\t\t\t{\r\n\t\t\t\t\tsprintf(S,\"rst %s/%02Xh\", symbol->name, addr);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tstrcpy(S, R);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif (S != NULL)\r\n\t\t\t\tstrcpy(S, R);\r\n\t\t}\r\n\t}\r\n\r\n    // MEKA-START: needed so it works properly when the instruction wrap at 0xffff\r\n    if (B < A)\r\n        return ((int)B+0x10000 - (int)A);\r\n    // MEKA-END\r\n\r\n    return (B-A);\r\n}\r\n\r\nint     Z80_Assemble(const char *src, byte dst[8])\r\n{\r\n    return (0);\r\n}\r\n\r\n#endif /* MEKA_Z80_DEBUGGER */\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Tables.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                          Tables.h                       **/\r\n/**                                                         **/\r\n/** This file contains tables of used by Z80 emulation to   **/\r\n/** compute SIGN,ZERO, PARITY flags, and decimal correction **/\r\n/** There are also timing tables for Z80 opcodes. This file **/\r\n/** is included from Z80.c.                                 **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n\r\nstatic byte Cycles[256] =\r\n{\r\n   //---------------------------\r\n   // [0x]\r\n   //---------------------------\r\n   4,   // 00: NOP\r\n   10,  // 01: LD bc, nn\r\n   7,   // 02: LD (bc), a\r\n   6,   // 03: INC bc\r\n   4,   // 04: INC b\r\n   4,   // 05: DEC b\r\n   7,   // 06: LD b, n\r\n   4,   // 07: RLCA\r\n   4,   // 08: EX af, af'\r\n   11,  // 09: ADD hl, bc\r\n   7,   // 0A: LD a, (bc)\r\n   6,   // 0B: DEC bc\r\n   4,   // 0C: INC c\r\n   4,   // 0D: DEC c\r\n   7,   // 0E: LD c, n\r\n   4,   // 0F: RRCA\r\n   //---------------------------\r\n   // [1x]\r\n   //---------------------------\r\n   8,   // 10: DJNZ\r\n   10,  // 11: LD de, nn\r\n   7,   // 12: LD (de), a\r\n   6,   // 13: INC de\r\n   4,   // 14: INC d\r\n   4,   // 15: DEC d\r\n   7,   // 16: LD d, n\r\n   4,   // 17: RLA\r\n   12,  // 18: JR\r\n   11,  // 19: ADD hl, de\r\n   7,   // 1A: LD a, (de)\r\n   6,   // 1B: DEC de\r\n   4,   // 1C: INC e\r\n   4,   // 1D: DEC e\r\n   7,   // 1E: LD e, n\r\n   4,   // 1F: RRA\r\n   //---------------------------\r\n   // [2x]\r\n   //---------------------------\r\n   7,   // 20: JR nz\r\n   10,  // 21: LD hl, nn\r\n   16,  // 22: LD (nn), hl      ?\r\n   6,   // 23: INC hl\r\n   4,   // 24: INC h\r\n   4,   // 25: DEC h\r\n   7,   // 26: LD h, n\r\n   4,   // 27: DAA\r\n   7,   // 28: JR z\r\n   11,  // 29: ADD hl, hl\r\n   16,  // 2A: LD hl, (nn)      ?\r\n   6,   // 2B: DEC hl\r\n   4,   // 2C: INC l\r\n   4,   // 2D: DEC l\r\n   7,   // 2E: LD l, n\r\n   4,   // 2F: CPL\r\n   //---------------------------\r\n   // [3x]\r\n   //---------------------------\r\n   7,   // 30: JR nc\r\n   10,  // 31: LD sp, nn\r\n   13,  // 32: LD (nn), a\r\n   6,   // 33: INC sp\r\n   11,  // 34: INC (hl)\r\n   11,  // 35: DEC (hl)\r\n   10,  // 36: LD (hl), n\r\n   4,   // 37: SCF\r\n   7,   // 38: JR c\r\n   11,  // 39: ADD hl, sp\r\n   13,  // 3A: LD a, (nn)\r\n   6,   // 3B: DEC sp\r\n   4,   // 3C: INC a\r\n   4,   // 3D: DEC a\r\n   7,   // 3E: LD a, n\r\n   4,   // 3F: CCF\r\n   //---------------------------\r\n   // [4x] LD b, xx / LD c, xx\r\n   //---------------------------\r\n   4,   // 40: LD b, b\r\n   4,   // 41: LD b, c\r\n   4,   // 42: LD b, d\r\n   4,   // 43: LD b, e\r\n   4,   // 44: LD b, h\r\n   4,   // 45: LD b, l\r\n   7,   // 46: LD b, (hl)\r\n   4,   // 47: LD b, a\r\n   4,   // 48: LD c, b\r\n   4,   // 49: LD c, c\r\n   4,   // 4A: LD c, d\r\n   4,   // 4B: LD c, e\r\n   4,   // 4C: LD c, h\r\n   4,   // 4D: LD c, l\r\n   7,   // 4E: LD c, (hl)\r\n   4,   // 4F: LD c, a\r\n   //---------------------------\r\n   // [5x] LD d, xx / LD e, xx\r\n   //---------------------------\r\n   4,   // 50: LD d, b\r\n   4,   // 51: LD d, c\r\n   4,   // 52: LD d, d\r\n   4,   // 53: LD d, e\r\n   4,   // 54: LD d, h\r\n   4,   // 55: LD d, l\r\n   7,   // 56: LD d, (hl)\r\n   4,   // 57: LD d, a\r\n   4,   // 58: LD e, b\r\n   4,   // 59: LD e, c\r\n   4,   // 5A: LD e, d\r\n   4,   // 5B: LD e, e\r\n   4,   // 5C: LD e, h\r\n   4,   // 5D: LD e, l\r\n   7,   // 5E: LD e, (hl)\r\n   4,   // 5F: LD e, a\r\n   //---------------------------\r\n   // [6x] LD h, xx / LD l, xx\r\n   //---------------------------\r\n   4,   // 60: LD h, b\r\n   4,   // 61: LD h, c\r\n   4,   // 62: LD h, d\r\n   4,   // 63: LD h, e\r\n   4,   // 64: LD h, h\r\n   4,   // 65: LD h, l\r\n   7,   // 66: LD h, (hl)\r\n   4,   // 67: LD h, a\r\n   4,   // 68: LD l, b\r\n   4,   // 69: LD l, c\r\n   4,   // 6A: LD l, d\r\n   4,   // 6B: LD l, e\r\n   4,   // 6C: LD l, h\r\n   4,   // 6D: LD l, l\r\n   7,   // 6E: LD l, (hl)\r\n   4,   // 6F: LD l, a\r\n   //---------------------------\r\n   // [7x] LD (hl), xx / LD a, xx / HALT\r\n   //---------------------------\r\n   7,   // 70: LD (hl), b\r\n   7,   // 71: LD (hl), c\r\n   7,   // 72: LD (hl), d\r\n   7,   // 73: LD (hl), e\r\n   7,   // 74: LD (hl), h\r\n   7,   // 75: LD (hl), l\r\n   4,   // 76: HALT\r\n   7,   // 77: LD (hl), a\r\n   4,   // 78: LD a, b\r\n   4,   // 79: LD a, c\r\n   4,   // 7A: LD a, d\r\n   4,   // 7B: LD a, e\r\n   4,   // 7C: LD a, h\r\n   4,   // 7D: LD a, l\r\n   7,   // 7E: LD a, (hl)\r\n   4,   // 7F: LD a, a\r\n   //---------------------------\r\n   // [8x] ADD / ADC\r\n   //---------------------------\r\n   4,   // 80: ADD a, b\r\n   4,   // 81: ADD a, c\r\n   4,   // 82: ADD a, d\r\n   4,   // 83: ADD a, e\r\n   4,   // 84: ADD a, h\r\n   4,   // 85: ADD a, l\r\n   7,   // 86: ADD a, (hl)\r\n   4,   // 87: ADD a, a\r\n   4,   // 88: ADC a, b\r\n   4,   // 89: ADC a, c\r\n   4,   // 8A: ADC a, d\r\n   4,   // 8B: ADC a, e\r\n   4,   // 8C: ADC a, h\r\n   4,   // 8D: ADC a, l\r\n   7,   // 8E: ADC a, (hl)\r\n   4,   // 8F: ADC a, a\r\n   //---------------------------\r\n   // [9x] SUB / SBC\r\n   //---------------------------\r\n   4,   // 90: SUB b\r\n   4,   // 91: SUB c\r\n   4,   // 92: SUB d\r\n   4,   // 93: SUB e\r\n   4,   // 94: SUB h\r\n   4,   // 95: SUB l\r\n   7,   // 96: SUB (hl)\r\n   4,   // 97: SUB a\r\n   4,   // 98: SBC a, b\r\n   4,   // 99: SBC a, c\r\n   4,   // 9A: SBC a, d\r\n   4,   // 9B: SBC a, e\r\n   4,   // 9C: SBC a, h\r\n   4,   // 9D: SBC a, l\r\n   7,   // 9E: SBC a, (hl)\r\n   4,   // 9F: SBC a, a\r\n   //---------------------------\r\n   // [Ax] AND / XOR\r\n   //---------------------------\r\n   4,   // A0: AND b\r\n   4,   // A1: AND c\r\n   4,   // A2: AND d\r\n   4,   // A3: AND e\r\n   4,   // A4: AND h\r\n   4,   // A5: AND l\r\n   7,   // A6: AND (hl)\r\n   4,   // A7: AND a\r\n   4,   // A8: XOR b\r\n   4,   // A9: XOR c\r\n   4,   // AA: XOR d\r\n   4,   // AB: XOR e\r\n   4,   // AC: XOR h\r\n   4,   // AD: XOR l\r\n   7,   // AE: XOR (hl)\r\n   4,   // AF: XOR a\r\n   //---------------------------\r\n   // [Bx] OR / CP\r\n   //---------------------------\r\n   4,   // B0: OR b\r\n   4,   // B1: OR c\r\n   4,   // B2: OR d\r\n   4,   // B3: OR e\r\n   4,   // B4: OR h\r\n   4,   // B5: OR l\r\n   7,   // B6: OR (hl)\r\n   4,   // B7: OR a\r\n   4,   // B8: CP b\r\n   4,   // B9: CP c\r\n   4,   // BA: CP d\r\n   4,   // BB: CP e\r\n   4,   // BC: CP h\r\n   4,   // BD: CP l\r\n   7,   // BE: CP (hl)\r\n   4,   // BF: CP a\r\n   //---------------------------\r\n   // [Cx]\r\n   //---------------------------\r\n   5,   // C0: RET nz\r\n   10,  // C1: POP bc\r\n   10,  // C2: JP nz\r\n   10,  // C3: JP\r\n   10,  // C4: CALL nz\r\n   11,  // C5: PUSH bc\r\n   7,   // C6: ADD a, n\r\n   11,  // C7: RST 0h\r\n   5,   // C8: RET z\r\n   10,  // C9: RET\r\n   10,  // CA: JP z\r\n   0,   // CB: ** CB prefix **\r\n   10,  // CC: CALL z\r\n   17,  // CD: CALL\r\n   7,   // CE: ADC a, n\r\n   11,  // CF: RST 8h\r\n   //---------------------------\r\n   // [Dx]\r\n   //---------------------------\r\n   5,   // D0: RET nc\r\n   10,  // D1: POP de\r\n   10,  // D2: JP nc\r\n   11,  // D3: OUT (n), a\r\n   10,  // D4: CALL nc\r\n   11,  // D5: PUSH de\r\n   7,   // D6: SUB n\r\n   11,  // D7: RST 10h\r\n   5,   // D8: RET c\r\n   4,   // D9: EXX\r\n   10,  // DA: JP c\r\n   11,  // DB: IN a, (n)\r\n   10,  // DC: CALL c\r\n   0,   // DD: ** DD prefix **\r\n   7,   // DE: SBC a, n\r\n   11,  // DF: RST 18h\r\n   //---------------------------\r\n   // [Ex]\r\n   //---------------------------\r\n   5,   // E0: RET po\r\n   10,  // E1: POP hl\r\n   10,  // E2: JP po\r\n   19,  // E3: EX (sp), hl\r\n   10,  // E4: CALL po\r\n   11,  // E5: PUSH hl\r\n   7,   // E6: AND n\r\n   11,  // E7: RST 20h\r\n   5,   // E8: RET pe\r\n   4,   // E9: JP (hl) // Also called 'LD PC, HL'\r\n   10,  // EA: JE pe\r\n   4,   // EB: EX de, hl\r\n   10,  // EC: CALL pe\r\n   0,   // ED: ** ED prefix **\r\n   7,   // EE: XOR n\r\n   11,  // EF: RST 28h\r\n   //---------------------------\r\n   // [Fx]\r\n   //---------------------------\r\n   5,   // F0: RET p\r\n   10,  // F1: POP af\r\n   10,  // F2: JP p\r\n   4,   // F3: DI\r\n   10,  // F4: CALL p\r\n   11,  // F5: PUSH af\r\n   7,   // F6: OR n\r\n   11,  // F7: RST 30h\r\n   5,   // F8: RET m\r\n   6,   // F9: LD sp, hl\r\n   10,  // FA: JP m\r\n   4,   // FB: EI\r\n   10,  // FC: CALL m\r\n   0,   // FD: ** FD prefix **\r\n   7,   // FE: CP n\r\n   11   // FF: RST 38h :)\r\n   //---------------------------\r\n};\r\n\r\nstatic byte CyclesCB[256] =\r\n{\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // 00-0F\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // 10-1F\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // 20-2F\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // 30-3F\r\n   8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, // 40-4F\r\n   8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, // 50-5F\r\n   8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, // 60-6F\r\n   8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, // 70-7F\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // 80-8F\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // 90-9F\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // A0-AF\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // B0-BF\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // C0-CF\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // D0-DF\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, // E0-EF\r\n   8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8  // F0-FF\r\n};\r\n\r\nstatic byte CyclesED[256] =\r\n{\r\n#define NP      (8)\r\n/*\r\n  12,12,15,20, 8,14, 8, 9,12,12,15,20, 0,14, 0, 9,\r\n  12,12,15,20, 0, 0, 8, 9,12,12,15,20, 0, 0, 8, 9,\r\n  12,12,15,20, 0, 0, 0,18,12,12,15,20, 0, 0, 0,18,\r\n  12, 0,15,20, 0, 0, 0, 0,12,12,15,20, 0, 0, 0, 0,\r\n  [...]\r\n  16,16,16,16, 0, 0, 0, 0,16,16,16,16, 0, 0, 0, 0,\r\n*/\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // 00-0F (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // 10-1F (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // 20-2F (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // 30-3F (All NOP)\r\n  12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9, // 40-4F\r\n  12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9, // 50-5F\r\n  12,12,15,20, 8,14, 8,18,12,12,15,20, 8,14, 8,18, // 60-6F\r\n  12,12,15,20, 8,14, 8, 4,12,12,15,20, 8,14, 8, 4, // 70-7F\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // 80-8F (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // 90-9F (All NOP)\r\n  16,16,16,16,NP,NP,NP,NP,16,16,16,16,NP,NP,NP,NP, // A0-AF\r\n   0, 0, 0, 0,NP,NP,NP,NP, 0, 0, 0, 0,NP,NP,NP,NP, // B0-BF\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // C0-CF (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // D0-DF (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // E0-EF (All NOP)\r\n  NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP,NP, // F0-FF (All NOP)\r\n#undef NP\r\n};\r\n\r\nstatic byte CyclesXX[256] =\r\n{\r\n   0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,\r\n   0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,\r\n   0,14,20,10, 9, 9, 9, 0, 0,15,20,10, 9, 9, 9, 0,\r\n   0, 0, 0, 0,23,23,19, 0, 0,15, 0, 0, 0, 0, 0, 0,\r\n   0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,\r\n   0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,\r\n   9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9,\r\n  19,19,19,19,19,19,19,19, 0, 0, 0, 0, 9, 9,19, 0,\r\n   0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,\r\n   0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,\r\n   0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,\r\n   0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,\r\n   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n   0,14, 0,23, 0,15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,\r\n   0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0, 0, 0, 0, 0\r\n};\r\n\r\nstatic byte CyclesXXCB[256] =\r\n{\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,\r\n  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,\r\n  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,\r\n  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,\r\n   0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0\r\n};\r\n\r\nstatic byte ZSTable[256] =\r\n{\r\n  Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG,\r\n  S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG, S_FLAG\r\n};\r\n\r\nstatic byte PZSTable[256] =\r\n{\r\n  Z_FLAG|P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,\r\n  0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,\r\n  0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,\r\n  0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,\r\n  P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,\r\n  0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,\r\n  P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,\r\n  P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,\r\n  0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,\r\n  S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG\r\n};\r\n\r\nstatic word DAATable[2048] =\r\n{\r\n  0x0044, 0x0100, 0x0200, 0x0304, 0x0400, 0x0504, 0x0604, 0x0700,\r\n  0x0808, 0x090C, 0x1010, 0x1114, 0x1214, 0x1310, 0x1414, 0x1510,\r\n  0x1000, 0x1104, 0x1204, 0x1300, 0x1404, 0x1500, 0x1600, 0x1704,\r\n  0x180C, 0x1908, 0x2030, 0x2134, 0x2234, 0x2330, 0x2434, 0x2530,\r\n  0x2020, 0x2124, 0x2224, 0x2320, 0x2424, 0x2520, 0x2620, 0x2724,\r\n  0x282C, 0x2928, 0x3034, 0x3130, 0x3230, 0x3334, 0x3430, 0x3534,\r\n  0x3024, 0x3120, 0x3220, 0x3324, 0x3420, 0x3524, 0x3624, 0x3720,\r\n  0x3828, 0x392C, 0x4010, 0x4114, 0x4214, 0x4310, 0x4414, 0x4510,\r\n  0x4000, 0x4104, 0x4204, 0x4300, 0x4404, 0x4500, 0x4600, 0x4704,\r\n  0x480C, 0x4908, 0x5014, 0x5110, 0x5210, 0x5314, 0x5410, 0x5514,\r\n  0x5004, 0x5100, 0x5200, 0x5304, 0x5400, 0x5504, 0x5604, 0x5700,\r\n  0x5808, 0x590C, 0x6034, 0x6130, 0x6230, 0x6334, 0x6430, 0x6534,\r\n  0x6024, 0x6120, 0x6220, 0x6324, 0x6420, 0x6524, 0x6624, 0x6720,\r\n  0x6828, 0x692C, 0x7030, 0x7134, 0x7234, 0x7330, 0x7434, 0x7530,\r\n  0x7020, 0x7124, 0x7224, 0x7320, 0x7424, 0x7520, 0x7620, 0x7724,\r\n  0x782C, 0x7928, 0x8090, 0x8194, 0x8294, 0x8390, 0x8494, 0x8590,\r\n  0x8080, 0x8184, 0x8284, 0x8380, 0x8484, 0x8580, 0x8680, 0x8784,\r\n  0x888C, 0x8988, 0x9094, 0x9190, 0x9290, 0x9394, 0x9490, 0x9594,\r\n  0x9084, 0x9180, 0x9280, 0x9384, 0x9480, 0x9584, 0x9684, 0x9780,\r\n  0x9888, 0x998C, 0x0055, 0x0111, 0x0211, 0x0315, 0x0411, 0x0515,\r\n  0x0045, 0x0101, 0x0201, 0x0305, 0x0401, 0x0505, 0x0605, 0x0701,\r\n  0x0809, 0x090D, 0x1011, 0x1115, 0x1215, 0x1311, 0x1415, 0x1511,\r\n  0x1001, 0x1105, 0x1205, 0x1301, 0x1405, 0x1501, 0x1601, 0x1705,\r\n  0x180D, 0x1909, 0x2031, 0x2135, 0x2235, 0x2331, 0x2435, 0x2531,\r\n  0x2021, 0x2125, 0x2225, 0x2321, 0x2425, 0x2521, 0x2621, 0x2725,\r\n  0x282D, 0x2929, 0x3035, 0x3131, 0x3231, 0x3335, 0x3431, 0x3535,\r\n  0x3025, 0x3121, 0x3221, 0x3325, 0x3421, 0x3525, 0x3625, 0x3721,\r\n  0x3829, 0x392D, 0x4011, 0x4115, 0x4215, 0x4311, 0x4415, 0x4511,\r\n  0x4001, 0x4105, 0x4205, 0x4301, 0x4405, 0x4501, 0x4601, 0x4705,\r\n  0x480D, 0x4909, 0x5015, 0x5111, 0x5211, 0x5315, 0x5411, 0x5515,\r\n  0x5005, 0x5101, 0x5201, 0x5305, 0x5401, 0x5505, 0x5605, 0x5701,\r\n  0x5809, 0x590D, 0x6035, 0x6131, 0x6231, 0x6335, 0x6431, 0x6535,\r\n  0x6025, 0x6121, 0x6221, 0x6325, 0x6421, 0x6525, 0x6625, 0x6721,\r\n  0x6829, 0x692D, 0x7031, 0x7135, 0x7235, 0x7331, 0x7435, 0x7531,\r\n  0x7021, 0x7125, 0x7225, 0x7321, 0x7425, 0x7521, 0x7621, 0x7725,\r\n  0x782D, 0x7929, 0x8091, 0x8195, 0x8295, 0x8391, 0x8495, 0x8591,\r\n  0x8081, 0x8185, 0x8285, 0x8381, 0x8485, 0x8581, 0x8681, 0x8785,\r\n  0x888D, 0x8989, 0x9095, 0x9191, 0x9291, 0x9395, 0x9491, 0x9595,\r\n  0x9085, 0x9181, 0x9281, 0x9385, 0x9481, 0x9585, 0x9685, 0x9781,\r\n  0x9889, 0x998D, 0xA0B5, 0xA1B1, 0xA2B1, 0xA3B5, 0xA4B1, 0xA5B5,\r\n  0xA0A5, 0xA1A1, 0xA2A1, 0xA3A5, 0xA4A1, 0xA5A5, 0xA6A5, 0xA7A1,\r\n  0xA8A9, 0xA9AD, 0xB0B1, 0xB1B5, 0xB2B5, 0xB3B1, 0xB4B5, 0xB5B1,\r\n  0xB0A1, 0xB1A5, 0xB2A5, 0xB3A1, 0xB4A5, 0xB5A1, 0xB6A1, 0xB7A5,\r\n  0xB8AD, 0xB9A9, 0xC095, 0xC191, 0xC291, 0xC395, 0xC491, 0xC595,\r\n  0xC085, 0xC181, 0xC281, 0xC385, 0xC481, 0xC585, 0xC685, 0xC781,\r\n  0xC889, 0xC98D, 0xD091, 0xD195, 0xD295, 0xD391, 0xD495, 0xD591,\r\n  0xD081, 0xD185, 0xD285, 0xD381, 0xD485, 0xD581, 0xD681, 0xD785,\r\n  0xD88D, 0xD989, 0xE0B1, 0xE1B5, 0xE2B5, 0xE3B1, 0xE4B5, 0xE5B1,\r\n  0xE0A1, 0xE1A5, 0xE2A5, 0xE3A1, 0xE4A5, 0xE5A1, 0xE6A1, 0xE7A5,\r\n  0xE8AD, 0xE9A9, 0xF0B5, 0xF1B1, 0xF2B1, 0xF3B5, 0xF4B1, 0xF5B5,\r\n  0xF0A5, 0xF1A1, 0xF2A1, 0xF3A5, 0xF4A1, 0xF5A5, 0xF6A5, 0xF7A1,\r\n  0xF8A9, 0xF9AD, 0x0055, 0x0111, 0x0211, 0x0315, 0x0411, 0x0515,\r\n  0x0045, 0x0101, 0x0201, 0x0305, 0x0401, 0x0505, 0x0605, 0x0701,\r\n  0x0809, 0x090D, 0x1011, 0x1115, 0x1215, 0x1311, 0x1415, 0x1511,\r\n  0x1001, 0x1105, 0x1205, 0x1301, 0x1405, 0x1501, 0x1601, 0x1705,\r\n  0x180D, 0x1909, 0x2031, 0x2135, 0x2235, 0x2331, 0x2435, 0x2531,\r\n  0x2021, 0x2125, 0x2225, 0x2321, 0x2425, 0x2521, 0x2621, 0x2725,\r\n  0x282D, 0x2929, 0x3035, 0x3131, 0x3231, 0x3335, 0x3431, 0x3535,\r\n  0x3025, 0x3121, 0x3221, 0x3325, 0x3421, 0x3525, 0x3625, 0x3721,\r\n  0x3829, 0x392D, 0x4011, 0x4115, 0x4215, 0x4311, 0x4415, 0x4511,\r\n  0x4001, 0x4105, 0x4205, 0x4301, 0x4405, 0x4501, 0x4601, 0x4705,\r\n  0x480D, 0x4909, 0x5015, 0x5111, 0x5211, 0x5315, 0x5411, 0x5515,\r\n  0x5005, 0x5101, 0x5201, 0x5305, 0x5401, 0x5505, 0x5605, 0x5701,\r\n  0x5809, 0x590D, 0x6035, 0x6131, 0x6231, 0x6335, 0x6431, 0x6535,\r\n  0x0604, 0x0700, 0x0808, 0x090C, 0x0A0C, 0x0B08, 0x0C0C, 0x0D08,\r\n  0x0E08, 0x0F0C, 0x1010, 0x1114, 0x1214, 0x1310, 0x1414, 0x1510,\r\n  0x1600, 0x1704, 0x180C, 0x1908, 0x1A08, 0x1B0C, 0x1C08, 0x1D0C,\r\n  0x1E0C, 0x1F08, 0x2030, 0x2134, 0x2234, 0x2330, 0x2434, 0x2530,\r\n  0x2620, 0x2724, 0x282C, 0x2928, 0x2A28, 0x2B2C, 0x2C28, 0x2D2C,\r\n  0x2E2C, 0x2F28, 0x3034, 0x3130, 0x3230, 0x3334, 0x3430, 0x3534,\r\n  0x3624, 0x3720, 0x3828, 0x392C, 0x3A2C, 0x3B28, 0x3C2C, 0x3D28,\r\n  0x3E28, 0x3F2C, 0x4010, 0x4114, 0x4214, 0x4310, 0x4414, 0x4510,\r\n  0x4600, 0x4704, 0x480C, 0x4908, 0x4A08, 0x4B0C, 0x4C08, 0x4D0C,\r\n  0x4E0C, 0x4F08, 0x5014, 0x5110, 0x5210, 0x5314, 0x5410, 0x5514,\r\n  0x5604, 0x5700, 0x5808, 0x590C, 0x5A0C, 0x5B08, 0x5C0C, 0x5D08,\r\n  0x5E08, 0x5F0C, 0x6034, 0x6130, 0x6230, 0x6334, 0x6430, 0x6534,\r\n  0x6624, 0x6720, 0x6828, 0x692C, 0x6A2C, 0x6B28, 0x6C2C, 0x6D28,\r\n  0x6E28, 0x6F2C, 0x7030, 0x7134, 0x7234, 0x7330, 0x7434, 0x7530,\r\n  0x7620, 0x7724, 0x782C, 0x7928, 0x7A28, 0x7B2C, 0x7C28, 0x7D2C,\r\n  0x7E2C, 0x7F28, 0x8090, 0x8194, 0x8294, 0x8390, 0x8494, 0x8590,\r\n  0x8680, 0x8784, 0x888C, 0x8988, 0x8A88, 0x8B8C, 0x8C88, 0x8D8C,\r\n  0x8E8C, 0x8F88, 0x9094, 0x9190, 0x9290, 0x9394, 0x9490, 0x9594,\r\n  0x9684, 0x9780, 0x9888, 0x998C, 0x9A8C, 0x9B88, 0x9C8C, 0x9D88,\r\n  0x9E88, 0x9F8C, 0x0055, 0x0111, 0x0211, 0x0315, 0x0411, 0x0515,\r\n  0x0605, 0x0701, 0x0809, 0x090D, 0x0A0D, 0x0B09, 0x0C0D, 0x0D09,\r\n  0x0E09, 0x0F0D, 0x1011, 0x1115, 0x1215, 0x1311, 0x1415, 0x1511,\r\n  0x1601, 0x1705, 0x180D, 0x1909, 0x1A09, 0x1B0D, 0x1C09, 0x1D0D,\r\n  0x1E0D, 0x1F09, 0x2031, 0x2135, 0x2235, 0x2331, 0x2435, 0x2531,\r\n  0x2621, 0x2725, 0x282D, 0x2929, 0x2A29, 0x2B2D, 0x2C29, 0x2D2D,\r\n  0x2E2D, 0x2F29, 0x3035, 0x3131, 0x3231, 0x3335, 0x3431, 0x3535,\r\n  0x3625, 0x3721, 0x3829, 0x392D, 0x3A2D, 0x3B29, 0x3C2D, 0x3D29,\r\n  0x3E29, 0x3F2D, 0x4011, 0x4115, 0x4215, 0x4311, 0x4415, 0x4511,\r\n  0x4601, 0x4705, 0x480D, 0x4909, 0x4A09, 0x4B0D, 0x4C09, 0x4D0D,\r\n  0x4E0D, 0x4F09, 0x5015, 0x5111, 0x5211, 0x5315, 0x5411, 0x5515,\r\n  0x5605, 0x5701, 0x5809, 0x590D, 0x5A0D, 0x5B09, 0x5C0D, 0x5D09,\r\n  0x5E09, 0x5F0D, 0x6035, 0x6131, 0x6231, 0x6335, 0x6431, 0x6535,\r\n  0x6625, 0x6721, 0x6829, 0x692D, 0x6A2D, 0x6B29, 0x6C2D, 0x6D29,\r\n  0x6E29, 0x6F2D, 0x7031, 0x7135, 0x7235, 0x7331, 0x7435, 0x7531,\r\n  0x7621, 0x7725, 0x782D, 0x7929, 0x7A29, 0x7B2D, 0x7C29, 0x7D2D,\r\n  0x7E2D, 0x7F29, 0x8091, 0x8195, 0x8295, 0x8391, 0x8495, 0x8591,\r\n  0x8681, 0x8785, 0x888D, 0x8989, 0x8A89, 0x8B8D, 0x8C89, 0x8D8D,\r\n  0x8E8D, 0x8F89, 0x9095, 0x9191, 0x9291, 0x9395, 0x9491, 0x9595,\r\n  0x9685, 0x9781, 0x9889, 0x998D, 0x9A8D, 0x9B89, 0x9C8D, 0x9D89,\r\n  0x9E89, 0x9F8D, 0xA0B5, 0xA1B1, 0xA2B1, 0xA3B5, 0xA4B1, 0xA5B5,\r\n  0xA6A5, 0xA7A1, 0xA8A9, 0xA9AD, 0xAAAD, 0xABA9, 0xACAD, 0xADA9,\r\n  0xAEA9, 0xAFAD, 0xB0B1, 0xB1B5, 0xB2B5, 0xB3B1, 0xB4B5, 0xB5B1,\r\n  0xB6A1, 0xB7A5, 0xB8AD, 0xB9A9, 0xBAA9, 0xBBAD, 0xBCA9, 0xBDAD,\r\n  0xBEAD, 0xBFA9, 0xC095, 0xC191, 0xC291, 0xC395, 0xC491, 0xC595,\r\n  0xC685, 0xC781, 0xC889, 0xC98D, 0xCA8D, 0xCB89, 0xCC8D, 0xCD89,\r\n  0xCE89, 0xCF8D, 0xD091, 0xD195, 0xD295, 0xD391, 0xD495, 0xD591,\r\n  0xD681, 0xD785, 0xD88D, 0xD989, 0xDA89, 0xDB8D, 0xDC89, 0xDD8D,\r\n  0xDE8D, 0xDF89, 0xE0B1, 0xE1B5, 0xE2B5, 0xE3B1, 0xE4B5, 0xE5B1,\r\n  0xE6A1, 0xE7A5, 0xE8AD, 0xE9A9, 0xEAA9, 0xEBAD, 0xECA9, 0xEDAD,\r\n  0xEEAD, 0xEFA9, 0xF0B5, 0xF1B1, 0xF2B1, 0xF3B5, 0xF4B1, 0xF5B5,\r\n  0xF6A5, 0xF7A1, 0xF8A9, 0xF9AD, 0xFAAD, 0xFBA9, 0xFCAD, 0xFDA9,\r\n  0xFEA9, 0xFFAD, 0x0055, 0x0111, 0x0211, 0x0315, 0x0411, 0x0515,\r\n  0x0605, 0x0701, 0x0809, 0x090D, 0x0A0D, 0x0B09, 0x0C0D, 0x0D09,\r\n  0x0E09, 0x0F0D, 0x1011, 0x1115, 0x1215, 0x1311, 0x1415, 0x1511,\r\n  0x1601, 0x1705, 0x180D, 0x1909, 0x1A09, 0x1B0D, 0x1C09, 0x1D0D,\r\n  0x1E0D, 0x1F09, 0x2031, 0x2135, 0x2235, 0x2331, 0x2435, 0x2531,\r\n  0x2621, 0x2725, 0x282D, 0x2929, 0x2A29, 0x2B2D, 0x2C29, 0x2D2D,\r\n  0x2E2D, 0x2F29, 0x3035, 0x3131, 0x3231, 0x3335, 0x3431, 0x3535,\r\n  0x3625, 0x3721, 0x3829, 0x392D, 0x3A2D, 0x3B29, 0x3C2D, 0x3D29,\r\n  0x3E29, 0x3F2D, 0x4011, 0x4115, 0x4215, 0x4311, 0x4415, 0x4511,\r\n  0x4601, 0x4705, 0x480D, 0x4909, 0x4A09, 0x4B0D, 0x4C09, 0x4D0D,\r\n  0x4E0D, 0x4F09, 0x5015, 0x5111, 0x5211, 0x5315, 0x5411, 0x5515,\r\n  0x5605, 0x5701, 0x5809, 0x590D, 0x5A0D, 0x5B09, 0x5C0D, 0x5D09,\r\n  0x5E09, 0x5F0D, 0x6035, 0x6131, 0x6231, 0x6335, 0x6431, 0x6535,\r\n  0x0046, 0x0102, 0x0202, 0x0306, 0x0402, 0x0506, 0x0606, 0x0702,\r\n  0x080A, 0x090E, 0x0402, 0x0506, 0x0606, 0x0702, 0x080A, 0x090E,\r\n  0x1002, 0x1106, 0x1206, 0x1302, 0x1406, 0x1502, 0x1602, 0x1706,\r\n  0x180E, 0x190A, 0x1406, 0x1502, 0x1602, 0x1706, 0x180E, 0x190A,\r\n  0x2022, 0x2126, 0x2226, 0x2322, 0x2426, 0x2522, 0x2622, 0x2726,\r\n  0x282E, 0x292A, 0x2426, 0x2522, 0x2622, 0x2726, 0x282E, 0x292A,\r\n  0x3026, 0x3122, 0x3222, 0x3326, 0x3422, 0x3526, 0x3626, 0x3722,\r\n  0x382A, 0x392E, 0x3422, 0x3526, 0x3626, 0x3722, 0x382A, 0x392E,\r\n  0x4002, 0x4106, 0x4206, 0x4302, 0x4406, 0x4502, 0x4602, 0x4706,\r\n  0x480E, 0x490A, 0x4406, 0x4502, 0x4602, 0x4706, 0x480E, 0x490A,\r\n  0x5006, 0x5102, 0x5202, 0x5306, 0x5402, 0x5506, 0x5606, 0x5702,\r\n  0x580A, 0x590E, 0x5402, 0x5506, 0x5606, 0x5702, 0x580A, 0x590E,\r\n  0x6026, 0x6122, 0x6222, 0x6326, 0x6422, 0x6526, 0x6626, 0x6722,\r\n  0x682A, 0x692E, 0x6422, 0x6526, 0x6626, 0x6722, 0x682A, 0x692E,\r\n  0x7022, 0x7126, 0x7226, 0x7322, 0x7426, 0x7522, 0x7622, 0x7726,\r\n  0x782E, 0x792A, 0x7426, 0x7522, 0x7622, 0x7726, 0x782E, 0x792A,\r\n  0x8082, 0x8186, 0x8286, 0x8382, 0x8486, 0x8582, 0x8682, 0x8786,\r\n  0x888E, 0x898A, 0x8486, 0x8582, 0x8682, 0x8786, 0x888E, 0x898A,\r\n  0x9086, 0x9182, 0x9282, 0x9386, 0x9482, 0x9586, 0x9686, 0x9782,\r\n  0x988A, 0x998E, 0x3423, 0x3527, 0x3627, 0x3723, 0x382B, 0x392F,\r\n  0x4003, 0x4107, 0x4207, 0x4303, 0x4407, 0x4503, 0x4603, 0x4707,\r\n  0x480F, 0x490B, 0x4407, 0x4503, 0x4603, 0x4707, 0x480F, 0x490B,\r\n  0x5007, 0x5103, 0x5203, 0x5307, 0x5403, 0x5507, 0x5607, 0x5703,\r\n  0x580B, 0x590F, 0x5403, 0x5507, 0x5607, 0x5703, 0x580B, 0x590F,\r\n  0x6027, 0x6123, 0x6223, 0x6327, 0x6423, 0x6527, 0x6627, 0x6723,\r\n  0x682B, 0x692F, 0x6423, 0x6527, 0x6627, 0x6723, 0x682B, 0x692F,\r\n  0x7023, 0x7127, 0x7227, 0x7323, 0x7427, 0x7523, 0x7623, 0x7727,\r\n  0x782F, 0x792B, 0x7427, 0x7523, 0x7623, 0x7727, 0x782F, 0x792B,\r\n  0x8083, 0x8187, 0x8287, 0x8383, 0x8487, 0x8583, 0x8683, 0x8787,\r\n  0x888F, 0x898B, 0x8487, 0x8583, 0x8683, 0x8787, 0x888F, 0x898B,\r\n  0x9087, 0x9183, 0x9283, 0x9387, 0x9483, 0x9587, 0x9687, 0x9783,\r\n  0x988B, 0x998F, 0x9483, 0x9587, 0x9687, 0x9783, 0x988B, 0x998F,\r\n  0xA0A7, 0xA1A3, 0xA2A3, 0xA3A7, 0xA4A3, 0xA5A7, 0xA6A7, 0xA7A3,\r\n  0xA8AB, 0xA9AF, 0xA4A3, 0xA5A7, 0xA6A7, 0xA7A3, 0xA8AB, 0xA9AF,\r\n  0xB0A3, 0xB1A7, 0xB2A7, 0xB3A3, 0xB4A7, 0xB5A3, 0xB6A3, 0xB7A7,\r\n  0xB8AF, 0xB9AB, 0xB4A7, 0xB5A3, 0xB6A3, 0xB7A7, 0xB8AF, 0xB9AB,\r\n  0xC087, 0xC183, 0xC283, 0xC387, 0xC483, 0xC587, 0xC687, 0xC783,\r\n  0xC88B, 0xC98F, 0xC483, 0xC587, 0xC687, 0xC783, 0xC88B, 0xC98F,\r\n  0xD083, 0xD187, 0xD287, 0xD383, 0xD487, 0xD583, 0xD683, 0xD787,\r\n  0xD88F, 0xD98B, 0xD487, 0xD583, 0xD683, 0xD787, 0xD88F, 0xD98B,\r\n  0xE0A3, 0xE1A7, 0xE2A7, 0xE3A3, 0xE4A7, 0xE5A3, 0xE6A3, 0xE7A7,\r\n  0xE8AF, 0xE9AB, 0xE4A7, 0xE5A3, 0xE6A3, 0xE7A7, 0xE8AF, 0xE9AB,\r\n  0xF0A7, 0xF1A3, 0xF2A3, 0xF3A7, 0xF4A3, 0xF5A7, 0xF6A7, 0xF7A3,\r\n  0xF8AB, 0xF9AF, 0xF4A3, 0xF5A7, 0xF6A7, 0xF7A3, 0xF8AB, 0xF9AF,\r\n  0x0047, 0x0103, 0x0203, 0x0307, 0x0403, 0x0507, 0x0607, 0x0703,\r\n  0x080B, 0x090F, 0x0403, 0x0507, 0x0607, 0x0703, 0x080B, 0x090F,\r\n  0x1003, 0x1107, 0x1207, 0x1303, 0x1407, 0x1503, 0x1603, 0x1707,\r\n  0x180F, 0x190B, 0x1407, 0x1503, 0x1603, 0x1707, 0x180F, 0x190B,\r\n  0x2023, 0x2127, 0x2227, 0x2323, 0x2427, 0x2523, 0x2623, 0x2727,\r\n  0x282F, 0x292B, 0x2427, 0x2523, 0x2623, 0x2727, 0x282F, 0x292B,\r\n  0x3027, 0x3123, 0x3223, 0x3327, 0x3423, 0x3527, 0x3627, 0x3723,\r\n  0x382B, 0x392F, 0x3423, 0x3527, 0x3627, 0x3723, 0x382B, 0x392F,\r\n  0x4003, 0x4107, 0x4207, 0x4303, 0x4407, 0x4503, 0x4603, 0x4707,\r\n  0x480F, 0x490B, 0x4407, 0x4503, 0x4603, 0x4707, 0x480F, 0x490B,\r\n  0x5007, 0x5103, 0x5203, 0x5307, 0x5403, 0x5507, 0x5607, 0x5703,\r\n  0x580B, 0x590F, 0x5403, 0x5507, 0x5607, 0x5703, 0x580B, 0x590F,\r\n  0x6027, 0x6123, 0x6223, 0x6327, 0x6423, 0x6527, 0x6627, 0x6723,\r\n  0x682B, 0x692F, 0x6423, 0x6527, 0x6627, 0x6723, 0x682B, 0x692F,\r\n  0x7023, 0x7127, 0x7227, 0x7323, 0x7427, 0x7523, 0x7623, 0x7727,\r\n  0x782F, 0x792B, 0x7427, 0x7523, 0x7623, 0x7727, 0x782F, 0x792B,\r\n  0x8083, 0x8187, 0x8287, 0x8383, 0x8487, 0x8583, 0x8683, 0x8787,\r\n  0x888F, 0x898B, 0x8487, 0x8583, 0x8683, 0x8787, 0x888F, 0x898B,\r\n  0x9087, 0x9183, 0x9283, 0x9387, 0x9483, 0x9587, 0x9687, 0x9783,\r\n  0x988B, 0x998F, 0x9483, 0x9587, 0x9687, 0x9783, 0x988B, 0x998F,\r\n  0xFABE, 0xFBBA, 0xFCBE, 0xFDBA, 0xFEBA, 0xFFBE, 0x0046, 0x0102,\r\n  0x0202, 0x0306, 0x0402, 0x0506, 0x0606, 0x0702, 0x080A, 0x090E,\r\n  0x0A1E, 0x0B1A, 0x0C1E, 0x0D1A, 0x0E1A, 0x0F1E, 0x1002, 0x1106,\r\n  0x1206, 0x1302, 0x1406, 0x1502, 0x1602, 0x1706, 0x180E, 0x190A,\r\n  0x1A1A, 0x1B1E, 0x1C1A, 0x1D1E, 0x1E1E, 0x1F1A, 0x2022, 0x2126,\r\n  0x2226, 0x2322, 0x2426, 0x2522, 0x2622, 0x2726, 0x282E, 0x292A,\r\n  0x2A3A, 0x2B3E, 0x2C3A, 0x2D3E, 0x2E3E, 0x2F3A, 0x3026, 0x3122,\r\n  0x3222, 0x3326, 0x3422, 0x3526, 0x3626, 0x3722, 0x382A, 0x392E,\r\n  0x3A3E, 0x3B3A, 0x3C3E, 0x3D3A, 0x3E3A, 0x3F3E, 0x4002, 0x4106,\r\n  0x4206, 0x4302, 0x4406, 0x4502, 0x4602, 0x4706, 0x480E, 0x490A,\r\n  0x4A1A, 0x4B1E, 0x4C1A, 0x4D1E, 0x4E1E, 0x4F1A, 0x5006, 0x5102,\r\n  0x5202, 0x5306, 0x5402, 0x5506, 0x5606, 0x5702, 0x580A, 0x590E,\r\n  0x5A1E, 0x5B1A, 0x5C1E, 0x5D1A, 0x5E1A, 0x5F1E, 0x6026, 0x6122,\r\n  0x6222, 0x6326, 0x6422, 0x6526, 0x6626, 0x6722, 0x682A, 0x692E,\r\n  0x6A3E, 0x6B3A, 0x6C3E, 0x6D3A, 0x6E3A, 0x6F3E, 0x7022, 0x7126,\r\n  0x7226, 0x7322, 0x7426, 0x7522, 0x7622, 0x7726, 0x782E, 0x792A,\r\n  0x7A3A, 0x7B3E, 0x7C3A, 0x7D3E, 0x7E3E, 0x7F3A, 0x8082, 0x8186,\r\n  0x8286, 0x8382, 0x8486, 0x8582, 0x8682, 0x8786, 0x888E, 0x898A,\r\n  0x8A9A, 0x8B9E, 0x8C9A, 0x8D9E, 0x8E9E, 0x8F9A, 0x9086, 0x9182,\r\n  0x9282, 0x9386, 0x3423, 0x3527, 0x3627, 0x3723, 0x382B, 0x392F,\r\n  0x3A3F, 0x3B3B, 0x3C3F, 0x3D3B, 0x3E3B, 0x3F3F, 0x4003, 0x4107,\r\n  0x4207, 0x4303, 0x4407, 0x4503, 0x4603, 0x4707, 0x480F, 0x490B,\r\n  0x4A1B, 0x4B1F, 0x4C1B, 0x4D1F, 0x4E1F, 0x4F1B, 0x5007, 0x5103,\r\n  0x5203, 0x5307, 0x5403, 0x5507, 0x5607, 0x5703, 0x580B, 0x590F,\r\n  0x5A1F, 0x5B1B, 0x5C1F, 0x5D1B, 0x5E1B, 0x5F1F, 0x6027, 0x6123,\r\n  0x6223, 0x6327, 0x6423, 0x6527, 0x6627, 0x6723, 0x682B, 0x692F,\r\n  0x6A3F, 0x6B3B, 0x6C3F, 0x6D3B, 0x6E3B, 0x6F3F, 0x7023, 0x7127,\r\n  0x7227, 0x7323, 0x7427, 0x7523, 0x7623, 0x7727, 0x782F, 0x792B,\r\n  0x7A3B, 0x7B3F, 0x7C3B, 0x7D3F, 0x7E3F, 0x7F3B, 0x8083, 0x8187,\r\n  0x8287, 0x8383, 0x8487, 0x8583, 0x8683, 0x8787, 0x888F, 0x898B,\r\n  0x8A9B, 0x8B9F, 0x8C9B, 0x8D9F, 0x8E9F, 0x8F9B, 0x9087, 0x9183,\r\n  0x9283, 0x9387, 0x9483, 0x9587, 0x9687, 0x9783, 0x988B, 0x998F,\r\n  0x9A9F, 0x9B9B, 0x9C9F, 0x9D9B, 0x9E9B, 0x9F9F, 0xA0A7, 0xA1A3,\r\n  0xA2A3, 0xA3A7, 0xA4A3, 0xA5A7, 0xA6A7, 0xA7A3, 0xA8AB, 0xA9AF,\r\n  0xAABF, 0xABBB, 0xACBF, 0xADBB, 0xAEBB, 0xAFBF, 0xB0A3, 0xB1A7,\r\n  0xB2A7, 0xB3A3, 0xB4A7, 0xB5A3, 0xB6A3, 0xB7A7, 0xB8AF, 0xB9AB,\r\n  0xBABB, 0xBBBF, 0xBCBB, 0xBDBF, 0xBEBF, 0xBFBB, 0xC087, 0xC183,\r\n  0xC283, 0xC387, 0xC483, 0xC587, 0xC687, 0xC783, 0xC88B, 0xC98F,\r\n  0xCA9F, 0xCB9B, 0xCC9F, 0xCD9B, 0xCE9B, 0xCF9F, 0xD083, 0xD187,\r\n  0xD287, 0xD383, 0xD487, 0xD583, 0xD683, 0xD787, 0xD88F, 0xD98B,\r\n  0xDA9B, 0xDB9F, 0xDC9B, 0xDD9F, 0xDE9F, 0xDF9B, 0xE0A3, 0xE1A7,\r\n  0xE2A7, 0xE3A3, 0xE4A7, 0xE5A3, 0xE6A3, 0xE7A7, 0xE8AF, 0xE9AB,\r\n  0xEABB, 0xEBBF, 0xECBB, 0xEDBF, 0xEEBF, 0xEFBB, 0xF0A7, 0xF1A3,\r\n  0xF2A3, 0xF3A7, 0xF4A3, 0xF5A7, 0xF6A7, 0xF7A3, 0xF8AB, 0xF9AF,\r\n  0xFABF, 0xFBBB, 0xFCBF, 0xFDBB, 0xFEBB, 0xFFBF, 0x0047, 0x0103,\r\n  0x0203, 0x0307, 0x0403, 0x0507, 0x0607, 0x0703, 0x080B, 0x090F,\r\n  0x0A1F, 0x0B1B, 0x0C1F, 0x0D1B, 0x0E1B, 0x0F1F, 0x1003, 0x1107,\r\n  0x1207, 0x1303, 0x1407, 0x1503, 0x1603, 0x1707, 0x180F, 0x190B,\r\n  0x1A1B, 0x1B1F, 0x1C1B, 0x1D1F, 0x1E1F, 0x1F1B, 0x2023, 0x2127,\r\n  0x2227, 0x2323, 0x2427, 0x2523, 0x2623, 0x2727, 0x282F, 0x292B,\r\n  0x2A3B, 0x2B3F, 0x2C3B, 0x2D3F, 0x2E3F, 0x2F3B, 0x3027, 0x3123,\r\n  0x3223, 0x3327, 0x3423, 0x3527, 0x3627, 0x3723, 0x382B, 0x392F,\r\n  0x3A3F, 0x3B3B, 0x3C3F, 0x3D3B, 0x3E3B, 0x3F3F, 0x4003, 0x4107,\r\n  0x4207, 0x4303, 0x4407, 0x4503, 0x4603, 0x4707, 0x480F, 0x490B,\r\n  0x4A1B, 0x4B1F, 0x4C1B, 0x4D1F, 0x4E1F, 0x4F1B, 0x5007, 0x5103,\r\n  0x5203, 0x5307, 0x5403, 0x5507, 0x5607, 0x5703, 0x580B, 0x590F,\r\n  0x5A1F, 0x5B1B, 0x5C1F, 0x5D1B, 0x5E1B, 0x5F1F, 0x6027, 0x6123,\r\n  0x6223, 0x6327, 0x6423, 0x6527, 0x6627, 0x6723, 0x682B, 0x692F,\r\n  0x6A3F, 0x6B3B, 0x6C3F, 0x6D3B, 0x6E3B, 0x6F3F, 0x7023, 0x7127,\r\n  0x7227, 0x7323, 0x7427, 0x7523, 0x7623, 0x7727, 0x782F, 0x792B,\r\n  0x7A3B, 0x7B3F, 0x7C3B, 0x7D3F, 0x7E3F, 0x7F3B, 0x8083, 0x8187,\r\n  0x8287, 0x8383, 0x8487, 0x8583, 0x8683, 0x8787, 0x888F, 0x898B,\r\n  0x8A9B, 0x8B9F, 0x8C9B, 0x8D9F, 0x8E9F, 0x8F9B, 0x9087, 0x9183,\r\n  0x9283, 0x9387, 0x9483, 0x9587, 0x9687, 0x9783, 0x988B, 0x998F\r\n};\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/UNDOC.TXT",
    "content": "\r\n[Codes ED]\r\n 4C, 54, 5C, 64, 6C, 74, 7C     --> NEG  (ED 44)        8 cycles\r\n     55, 5D, 65, 6D, 75, 7D     --> RETN (ED 45)       14 cycles\r\n 4E,         66, 6E             --> IM 0 (ED 46)        8 cycles\r\n                     76         --> IM 1 (ED 56)        8 cycles\r\n                     7E         --> IM 2 (ED 5E)        8 cycles\r\n                     77, 7F     --> NOP                 4 cycles\r\n                     71         --> OUT (C), 0         12 cycles\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Z80.cpp",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                           Z80.c                         **/\r\n/**                                                         **/\r\n/** This file contains implementation for Z80 CPU. Don't    **/\r\n/** forget to provide RdZ80(), WrZ80(), InZ80(), OutZ80(),  **/\r\n/** LoopZ80(), and PatchZ80() functions to accomodate the   **/\r\n/** emulated machine's architecture.                        **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n/* Modified for usage in MEKA. */\r\n/*************************************************************/\r\n\r\n\r\n//*** MEKA-START ***\r\n\r\n//-----------------------------------------------------------------------------\r\n// Definitions\r\n//-----------------------------------------------------------------------------\r\n\r\n// Define to enable debugging features\r\n// #define MEKA_Z80_DEBUGGER    // already defined in project\r\n\r\n// Define to enable timing on NMI/Int acceptance\r\n#define MEKA_Z80_INTERRUPTS_TAKES_TIME\r\n\r\n// Define to enable change in interrupt emulation (WIP)\r\n//#define MEKA_Z80_INT_NEW\r\n\r\n//-----------------------------------------------------------------------------\r\n// Includes\r\n//-----------------------------------------------------------------------------\r\n\r\n#include \"shared.h\"\r\n#include \"Z80.h\"\r\n#include \"Tables.h\"\r\n#include \"debugger.h\"\r\n\r\n#include \"Z80Call.cpp\"\r\n\r\nvoid    (*WrZ80)(register word Addr, register byte Value);\r\nbyte    (*RdZ80)(register word Addr);\r\nvoid    (*WrZ80_NoHook)(register word Addr, register byte Value);\r\nbyte    (*RdZ80_NoHook)(register word Addr);\r\nvoid    (*OutZ80)(register word Port, register byte Value);\r\nbyte    (*InZ80)(register word Port);\r\nvoid    (*OutZ80_NoHook)(register word Port, register byte Value);\r\nbyte    (*InZ80_NoHook)(register word Port);\r\nword    (*LoopZ80)(/*register Z80 *R*/ void);\r\n\r\n//-----------------------------------------------------------------------------\r\n// External declaration\r\n//-----------------------------------------------------------------------------\r\n\r\nextern void    Msg(int attr, const char *format, ...);\r\n\r\nextern int     Debugger_Hook(Z80 *R);\r\n\r\n//*** MEKA-END ***\r\n\r\n/** System-Dependent Stuff ***********************************/\r\n/** This is system-dependent code put here to speed things  **/\r\n/** up. It has to stay inlined to be fast.                  **/\r\n/*************************************************************/\r\n//*** MEKA-START ***\r\n// extern byte *Mem_Pages[];\r\n// INLINE byte RdZ80(word A) { return(Mem_Pages[(A)>>13][(A)&0x1FFF]); }\r\n//*** MEKA-END ***\r\n\r\n#define S(Fl)        R->AF.B.l|=Fl\r\n#define R(Fl)        R->AF.B.l&=~(Fl)\r\n#define FLAGS(Rg,Fl) R->AF.B.l=Fl|ZSTable[Rg]\r\n\r\n#define M_RLC(Rg)      \\\r\n  R->AF.B.l=Rg>>7;Rg=(Rg<<1)|R->AF.B.l;R->AF.B.l|=PZSTable[Rg]\r\n#define M_RRC(Rg)      \\\r\n  R->AF.B.l=Rg&0x01;Rg=(Rg>>1)|(R->AF.B.l<<7);R->AF.B.l|=PZSTable[Rg]\r\n#define M_RL(Rg)       \\\r\n  if(Rg&0x80)          \\\r\n  {                    \\\r\n    Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \\\r\n    R->AF.B.l=PZSTable[Rg]|C_FLAG; \\\r\n  }                    \\\r\n  else                 \\\r\n  {                    \\\r\n    Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \\\r\n    R->AF.B.l=PZSTable[Rg];        \\\r\n  }\r\n#define M_RR(Rg)       \\\r\n  if(Rg&0x01)          \\\r\n  {                    \\\r\n    Rg=(Rg>>1)|(R->AF.B.l<<7);     \\\r\n    R->AF.B.l=PZSTable[Rg]|C_FLAG; \\\r\n  }                    \\\r\n  else                 \\\r\n  {                    \\\r\n    Rg=(Rg>>1)|(R->AF.B.l<<7);     \\\r\n    R->AF.B.l=PZSTable[Rg];        \\\r\n  }\r\n\r\n#define M_SLA(Rg)      \\\r\n  R->AF.B.l=Rg>>7;Rg<<=1;R->AF.B.l|=PZSTable[Rg]\r\n#define M_SRA(Rg)      \\\r\n  R->AF.B.l=Rg&C_FLAG;Rg=(Rg>>1)|(Rg&0x80);R->AF.B.l|=PZSTable[Rg]\r\n\r\n#define M_SLL(Rg)      \\\r\n  R->AF.B.l=Rg>>7;Rg=(Rg<<1)|0x01;R->AF.B.l|=PZSTable[Rg]\r\n#define M_SRL(Rg)      \\\r\n  R->AF.B.l=Rg&0x01;Rg>>=1;R->AF.B.l|=PZSTable[Rg]\r\n\r\n#define M_BIT(Bit,Rg)  \\\r\n  R->AF.B.l=(R->AF.B.l&C_FLAG)|H_FLAG|PZSTable[Rg&(1<<Bit)]\r\n\r\n#define M_SET(Bit,Rg) Rg|=1<<Bit\r\n#define M_RES(Bit,Rg) Rg&=~(1<<Bit)\r\n\r\n#define M_POP(Rg)      \\\r\n  R->Rg.B.l=RdZ80(R->SP.W++);R->Rg.B.h=RdZ80(R->SP.W++)\r\n#define M_PUSH(Rg)     \\\r\n  WrZ80(--R->SP.W,R->Rg.B.h);WrZ80(--R->SP.W,R->Rg.B.l)\r\n\r\n#define M_CALL         \\\r\n  J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W++);         \\\r\n  WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l); \\\r\n  R->PC.W=J.W\r\n\r\n#define M_JP  J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W);R->PC.W=J.W\r\n#define M_JR  R->PC.W+=(offset)RdZ80(R->PC.W)+1\r\n#define M_RET R->PC.B.l=RdZ80(R->SP.W++);R->PC.B.h=RdZ80(R->SP.W++)\r\n\r\n#define M_RST(Ad)      \\\r\n  WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l);R->PC.W=Ad\r\n\r\n#define M_LDWORD(Rg)   \\\r\n  R->Rg.B.l=RdZ80(R->PC.W++);R->Rg.B.h=RdZ80(R->PC.W++)\r\n\r\n#define M_ADD(Rg)      \\\r\n  J.W=R->AF.B.h+Rg;     \\\r\n  R->AF.B.l=            \\\r\n    (~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \\\r\n    J.B.h|ZSTable[J.B.l]|                        \\\r\n    ((R->AF.B.h^Rg^J.B.l)&H_FLAG);               \\\r\n  R->AF.B.h=J.B.l\r\n\r\n#define M_SUB(Rg)      \\\r\n  J.W=R->AF.B.h-Rg;    \\\r\n  R->AF.B.l=           \\\r\n    ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \\\r\n    N_FLAG|-J.B.h|ZSTable[J.B.l]|                      \\\r\n    ((R->AF.B.h^Rg^J.B.l)&H_FLAG);                     \\\r\n  R->AF.B.h=J.B.l\r\n\r\n#define M_ADC(Rg)      \\\r\n  J.W=R->AF.B.h+Rg+(R->AF.B.l&C_FLAG); \\\r\n  R->AF.B.l=                           \\\r\n    (~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \\\r\n    J.B.h|ZSTable[J.B.l]|              \\\r\n    ((R->AF.B.h^Rg^J.B.l)&H_FLAG);     \\\r\n  R->AF.B.h=J.B.l\r\n\r\n#define M_SBC(Rg)      \\\r\n  J.W=R->AF.B.h-Rg-(R->AF.B.l&C_FLAG); \\\r\n  R->AF.B.l=                           \\\r\n    ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \\\r\n    N_FLAG|-J.B.h|ZSTable[J.B.l]|      \\\r\n    ((R->AF.B.h^Rg^J.B.l)&H_FLAG);     \\\r\n  R->AF.B.h=J.B.l\r\n\r\n#define M_CP(Rg)       \\\r\n  J.W=R->AF.B.h-Rg;    \\\r\n  R->AF.B.l=           \\\r\n    ((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \\\r\n    N_FLAG|-J.B.h|ZSTable[J.B.l]|                      \\\r\n    ((R->AF.B.h^Rg^J.B.l)&H_FLAG)\r\n\r\n#define M_AND(Rg) R->AF.B.h&=Rg;R->AF.B.l=H_FLAG|PZSTable[R->AF.B.h]\r\n#define M_OR(Rg)  R->AF.B.h|=Rg;R->AF.B.l=PZSTable[R->AF.B.h]\r\n#define M_XOR(Rg) R->AF.B.h^=Rg;R->AF.B.l=PZSTable[R->AF.B.h]\r\n\r\n#define M_IN(Rg)        \\\r\n  Rg=InZ80(R->BC.B.l);  \\\r\n  R->AF.B.l=PZSTable[Rg]|(R->AF.B.l&C_FLAG)\r\n\r\n#define M_INC(Rg)       \\\r\n  Rg++;                 \\\r\n  R->AF.B.l=            \\\r\n    (R->AF.B.l&C_FLAG)|ZSTable[Rg]|           \\\r\n    (Rg==0x80? V_FLAG:0)|(Rg&0x0F? 0:H_FLAG)\r\n\r\n#define M_DEC(Rg)       \\\r\n  Rg--;                 \\\r\n  R->AF.B.l=            \\\r\n    N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \\\r\n    (Rg==0x7F? V_FLAG:0)|((Rg&0x0F)==0x0F? H_FLAG:0)\r\n\r\n#define M_ADDW(Rg1,Rg2) \\\r\n  J.W=(R->Rg1.W+R->Rg2.W)&0xFFFF;                        \\\r\n  R->AF.B.l=                                             \\\r\n    (R->AF.B.l&~(H_FLAG|N_FLAG|C_FLAG))|                 \\\r\n    ((R->Rg1.W^R->Rg2.W^J.W)&0x1000? H_FLAG:0)|          \\\r\n    (((long)R->Rg1.W+(long)R->Rg2.W)&0x10000? C_FLAG:0); \\\r\n  R->Rg1.W=J.W\r\n\r\n#define M_ADCW(Rg)      \\\r\n  I=R->AF.B.l&C_FLAG;J.W=(R->HL.W+R->Rg.W+I)&0xFFFF;           \\\r\n  R->AF.B.l=                                                   \\\r\n    (((long)R->HL.W+(long)R->Rg.W+(long)I)&0x10000? C_FLAG:0)| \\\r\n    (~(R->HL.W^R->Rg.W)&(R->Rg.W^J.W)&0x8000? V_FLAG:0)|       \\\r\n    ((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)|                  \\\r\n    (J.W? 0:Z_FLAG)|(J.B.h&S_FLAG);                            \\\r\n  R->HL.W=J.W\r\n\r\n#define M_SBCW(Rg)      \\\r\n  I=R->AF.B.l&C_FLAG;J.W=(R->HL.W-R->Rg.W-I)&0xFFFF;           \\\r\n  R->AF.B.l=                                                   \\\r\n    N_FLAG|                                                    \\\r\n    (((long)R->HL.W-(long)R->Rg.W-(long)I)&0x10000? C_FLAG:0)| \\\r\n    ((R->HL.W^R->Rg.W)&(R->HL.W^J.W)&0x8000? V_FLAG:0)|        \\\r\n    ((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)|                  \\\r\n    (J.W? 0:Z_FLAG)|(J.B.h&S_FLAG);                            \\\r\n  R->HL.W=J.W\r\n\r\n#include \"Z80OpcodeEnums.h\"\r\n\r\nstatic void CodesCB(register Z80 *R)\r\n{\r\n  register byte I;\r\n\r\n  I = RdZ80(R->PC.W++);\r\n  R->R++;\r\n  R->ICount -= CyclesCB[I];\r\n  #ifdef MEKA_Z80_OPCODES_USAGE\r\n    Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_CB][I]++;\r\n  #endif\r\n  switch (I)\r\n  {\r\n#include \"CodesCB.h\"\r\n    default:\r\n      if (R->TrapBadOps)\r\n        printf\r\n        (\r\n          \"[Z80 %lX] Unrecognized instruction: CB %02X at PC=%04X\\n\",\r\n          (long)(R->User),RdZ80(R->PC.W-1),R->PC.W-2\r\n        );\r\n  }\r\n}\r\n\r\nstatic void CodesDDCB(register Z80 *R)\r\n{\r\n  register pair J;\r\n  register byte I;\r\n\r\n#define XX IX\r\n  J.W = R->XX.W + (offset)RdZ80(R->PC.W++);\r\n  I = RdZ80(R->PC.W++);\r\n  R->ICount -= CyclesXXCB[I];\r\n  #ifdef MEKA_Z80_OPCODES_USAGE\r\n    Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_DDCB][I]++;\r\n  #endif\r\n  switch (I)\r\n  {\r\n#include \"CodesXCB.h\"\r\n    default:\r\n      if (R->TrapBadOps)\r\n        printf\r\n        (\r\n          \"[Z80 %lX] Unrecognized instruction: DD CB %02X %02X at PC=%04X\\n\",\r\n          (long)(R->User),RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4\r\n        );\r\n  }\r\n#undef XX\r\n}\r\n\r\nstatic void CodesFDCB(register Z80 *R)\r\n{\r\n  register pair J;\r\n  register byte I;\r\n\r\n#define XX IY\r\n  J.W = R->XX.W + (offset)RdZ80(R->PC.W++);\r\n  I = RdZ80(R->PC.W++);\r\n  R->ICount -= CyclesXXCB[I];\r\n  #ifdef MEKA_Z80_OPCODES_USAGE\r\n    Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_FDCB][I]++;\r\n  #endif\r\n  switch (I)\r\n  {\r\n#include \"CodesXCB.h\"\r\n    default:\r\n      if (R->TrapBadOps)\r\n        printf\r\n        (\r\n          \"[Z80 %lX] Unrecognized instruction: FD CB %02X %02X at PC=%04X\\n\",\r\n          (long)R->User,RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4\r\n        );\r\n  }\r\n#undef XX\r\n}\r\n\r\nstatic void CodesED(register Z80 *R)\r\n{\r\n  register byte I;\r\n  register pair J;\r\n\r\n  I = RdZ80(R->PC.W++);\r\n  R->R++;\r\n  R->ICount -= CyclesED[I];\r\n  #ifdef MEKA_Z80_OPCODES_USAGE\r\n    Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_ED][I]++;\r\n  #endif\r\n  switch (I)\r\n  {\r\n#include \"CodesED.h\"\r\n    /*\r\n    ** Note: ED cannot be repeated\r\n    case PFX_ED:\r\n      R->PC.W--;\r\n      Msg(0, \"%04x: Repeated ED\", R->PC.W);\r\n      break;\r\n    */\r\n    default:\r\n      if (R->TrapBadOps)\r\n        printf\r\n        (\r\n          \"[Z80 %lX] Unrecognized instruction: ED %02X at PC=%04X\\n\",\r\n          (long)R->User,RdZ80(R->PC.W-1),R->PC.W-2\r\n        );\r\n  }\r\n}\r\n\r\nstatic void CodesDD(register Z80 *R)\r\n{\r\n  register byte I;\r\n  register pair J;\r\n\r\n#define XX IX\r\n  I = RdZ80(R->PC.W++);\r\n  R->R++;\r\n  R->ICount -= CyclesXX[I];\r\n  #ifdef MEKA_Z80_OPCODES_USAGE\r\n    Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_DD][I]++;\r\n  #endif\r\n  switch (I)\r\n  {\r\n#include \"CodesXX.h\"\r\n    case PFX_FD:\r\n    case PFX_DD:\r\n      R->PC.W--;\r\n      // Msg(0, \"%04x: CodesDD() Repeated %02x\", R->PC.W, I);\r\n      break;\r\n    case PFX_CB:\r\n      CodesDDCB(R); break;\r\n    default:\r\n      if (R->TrapBadOps)\r\n        printf\r\n        (\r\n          \"[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\\n\",\r\n          (long)R->User,RdZ80(R->PC.W-1),R->PC.W-2\r\n        );\r\n  }\r\n#undef XX\r\n}\r\n\r\nstatic void CodesFD(register Z80 *R)\r\n{\r\n  register byte I;\r\n  register pair J;\r\n\r\n#define XX IY\r\n  I = RdZ80(R->PC.W++);\r\n  R->R++;\r\n  R->ICount -= CyclesXX[I];\r\n  #ifdef MEKA_Z80_OPCODES_USAGE\r\n    Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_FD][I]++;\r\n  #endif\r\n  switch (I)\r\n  {\r\n#include \"CodesXX.h\"\r\n    case PFX_FD:\r\n    case PFX_DD:\r\n      R->PC.W--;\r\n      // Msg(0, \"%04x: CodesFD() Repeated %02x\", R->PC.W, I);\r\n      break;\r\n    case PFX_CB:\r\n      CodesFDCB(R);break;\r\n    default:\r\n        printf\r\n        (\r\n          \"Unrecognized instruction: FD %02X at PC=%04X\\n\",\r\n          RdZ80(R->PC.W-1),R->PC.W-2\r\n        );\r\n  }\r\n#undef XX\r\n}\r\n\r\n/** ResetZ80() ***********************************************/\r\n/** This function can be used to reset the register struct  **/\r\n/** before starting execution with Z80(). It sets the       **/\r\n/** registers to their supposed initial values.             **/\r\n/*************************************************************/\r\nvoid    ResetZ80(Z80 *R)\r\n{\r\n  R->PC.W     = 0x0000;\r\n  R->SP.W     = 0xDFF0;\r\n  R->AF.W     = 0x0000;\r\n  R->BC.W     = 0x0000;\r\n  R->DE.W     = 0x0000;\r\n  R->HL.W     = 0x0000;\r\n  R->AF1.W    = 0x0000;\r\n  R->BC1.W    = 0x0000;\r\n  R->DE1.W    = 0x0000;\r\n  R->HL1.W    = 0x0000;\r\n  R->IX.W     = 0x0000;\r\n  R->IY.W     = 0x0000;\r\n  R->I        = 0x00;\r\n  R->IFF      = 0x00;\r\n  R->R        = 0x00;\r\n  R->R7       = 0x00;\r\n  R->ICount   = R->IPeriod;\r\n  R->IRequest = INT_NONE;\r\n}\r\n\r\n/** IntZ80() *************************************************/\r\n/** This function will generate interrupt of given vector.  **/\r\n/*************************************************************/\r\nvoid IntZ80(Z80 *R,word Vector)\r\n{\r\n  if((R->IFF&IFF_1)||(Vector==INT_NMI))\r\n  {\r\n    /* If HALTed, take CPU off HALT instruction */\r\n    if(R->IFF&IFF_HALT) { R->PC.W++;R->IFF&=~IFF_HALT; }\r\n\r\n    /* Save PC on stack */\r\n    M_PUSH(PC);\r\n\r\n    /* Automatically reset IRequest if needed */\r\n    //*** MEKA-START : Commented out, Reading VDP Status does that\r\n    // if(R->IAutoReset&&(Vector==R->IRequest)) R->IRequest=INT_NONE;\r\n    //*** MEKA_STOP\r\n\r\n    /* If it is NMI... */\r\n    if(Vector==INT_NMI)\r\n    {\r\n      /* Copy IFF1 to IFF2 */\r\n      //if(R->IFF&IFF_1) R->IFF|=IFF_2; else R->IFF&=~IFF_2;\r\n      /* Clear IFF1 */\r\n      R->IFF&=~(IFF_1|IFF_EI);\r\n      /* Jump to hardwired NMI vector */\r\n      R->PC.W=0x0066;\r\n      /* Takes time ? */\r\n      #ifdef MEKA_Z80_INTERRUPTS_TAKES_TIME\r\n         R->ICount -= 11;\r\n      #endif\r\n      /* Done */\r\n      return;\r\n    }\r\n\r\n    /* Further interrupts off */\r\n    R->IFF&=~(IFF_1|IFF_2|IFF_EI);\r\n\r\n    /* If in IM2 mode... */\r\n    if(R->IFF&IFF_IM2)\r\n    {\r\n      /* Make up the vector address */\r\n      Vector=(Vector&0xFF)|((word)(R->I)<<8);\r\n      /* Read the vector */\r\n      R->PC.B.l=RdZ80(Vector++);\r\n      R->PC.B.h=RdZ80(Vector);\r\n      /* Takes time ? */\r\n      #ifdef MEKA_Z80_INTERRUPTS_TAKES_TIME\r\n         R->ICount -= 19;\r\n      #endif\r\n      /* Done */\r\n      return;\r\n    }\r\n\r\n    /* If in IM1 mode, just jump to hardwired IRQ vector */\r\n    if(R->IFF&IFF_IM1)\r\n    {\r\n      R->PC.W=0x0038;\r\n      /* Takes time ? */\r\n      #ifdef MEKA_Z80_INTERRUPTS_TAKES_TIME\r\n         R->ICount -= 13;\r\n      #endif\r\n      return;\r\n    }\r\n\r\n    /* If in IM0 mode... */\r\n\r\n    /* Takes time ? */\r\n    #ifdef MEKA_Z80_INTERRUPTS_TAKES_TIME\r\n       R->ICount -= 13;\r\n    #endif\r\n\r\n    /* Jump to a vector */\r\n    switch(Vector)\r\n    {\r\n      case INT_RST00: R->PC.W=0x0000;break;\r\n      case INT_RST08: R->PC.W=0x0008;break;\r\n      case INT_RST10: R->PC.W=0x0010;break;\r\n      case INT_RST18: R->PC.W=0x0018;break;\r\n      case INT_RST20: R->PC.W=0x0020;break;\r\n      case INT_RST28: R->PC.W=0x0028;break;\r\n      case INT_RST30: R->PC.W=0x0030;break;\r\n      case INT_RST38: R->PC.W=0x0038;break;\r\n    }\r\n  }\r\n}\r\n\r\n/** RunZ80() *************************************************/\r\n/** This function will run Z80 code until an LoopZ80() call **/\r\n/** returns INT_QUIT. It will return the PC at which        **/\r\n/** emulation stopped, and current register values in R.    **/\r\n/*************************************************************/\r\nword    RunZ80(Z80 *R)\r\n{\r\n  register byte I;\r\n  register pair J;\r\n\r\n  for (;;)\r\n  {\r\n    I = RdZ80 (R->PC.W ++);\r\n    R->ICount -= Cycles[I];\r\n    #ifdef MEKA_Z80_OPCODES_USAGE\r\n       Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_NONE][I]++;\r\n    #endif\r\n    switch (I)\r\n    {\r\n#include \"Codes.h\"\r\n      case PFX_CB: CodesCB(R); break;\r\n      case PFX_ED: CodesED(R); break;\r\n      case PFX_FD: CodesFD(R); break;\r\n      case PFX_DD: CodesDD(R); break;\r\n    }\r\n\r\n    /* If cycle counter expired... */\r\n    if (R->ICount <= 0)\r\n    {\r\n      /* If we have come after EI, get address from IRequest */\r\n      /* Otherwise, get it from the loop handler             */\r\n      if (R->IFF & IFF_EI)\r\n      {\r\n        R->IFF=(R->IFF&~IFF_EI)|IFF_1; /* Done with AfterEI state */\r\n        R->ICount += R->IBackup - 1;   /* Restore the ICount       */\r\n\r\n        /* Call periodic handler or set pending IRQ */\r\n        if (R->ICount > 0) J.W = R->IRequest;\r\n        else\r\n        {\r\n          J.W = LoopZ80(/*R*/);                 /* Call periodic handler    */\r\n          R->ICount+=R->IPeriod;                /* Add up to cycle counter  */\r\n          if (J.W==INT_NONE) J.W=R->IRequest;   /* Pending IRQ */\r\n        }\r\n      }\r\n      else\r\n      {\r\n        J.W = LoopZ80(/*R*/);                   /* Call periodic handler    */\r\n        R->ICount+=R->IPeriod;                  /* Add up to cycle counter  */\r\n        if (J.W==INT_NONE) J.W=R->IRequest;     /* Pending int-rupt */\r\n      }\r\n\r\n      if (J.W == INT_QUIT) return (R->PC.W);    /* Exit if INT_QUIT */\r\n      if (J.W != INT_NONE) IntZ80 (R,J.W);      /* Int-pt if needed */\r\n    }\r\n  }\r\n\r\n  /* Execution stopped */\r\n  // Note: unreachable code\r\n  return (R->PC.W);\r\n}\r\n\r\nword    RunZ80_Debugging(Z80 *R)\r\n{\r\n    register byte I;\r\n    register pair J;\r\n    int icount_before_instruction;\r\n\r\n    for (;;)\r\n    {\r\n        // This is block of code that gets added in RunZ80_Debugging() compared to standard RunZ80()\r\n\r\n#ifdef MEKA_Z80_DEBUGGER\r\n\t\tDebugger.pc_last = R->PC.W;\r\n\r\n        // Log PC execution address\r\n\t\t// This allow us to have backtracking disassembly\r\n\t\tif (Debugger.pc_exec_points[R->PC.W] == 0)\r\n\t\t\tDebugger.pc_exec_points[R->PC.W] = 0xff;\r\n#endif // MEKA_Z80_DEBUGGER\r\n\r\n        // Turn tracing on when reached trap address\r\n        if (R->PC.W == R->Trap)\r\n            R->Trace = 1;\r\n\r\n        // Call single-step debugger, exit if requested\r\n#ifdef MEKA_Z80_DEBUGGER\r\n        if (R->Trace || Debugger.cpu_exec_traps[R->PC.W])\r\n            if (!Debugger_Hook(R))\r\n                return (R->PC.W);\r\n\r\n\t\t// Trace\r\n\t\tif (size_t log_size = Debugger.pc_detail_log_data.size())\r\n\t\t{\r\n\t\t\tconst size_t head = Debugger.pc_detail_log_head;\r\n\t\t\tconst size_t prev = head == 0 ? log_size - 1 : head - 1;\r\n\t\t\tif (Debugger.pc_detail_log_data[prev].pc != R->PC.W)\r\n\t\t\t{\r\n\t\t\t\tt_debugger_exec_log_entry* e = &Debugger.pc_detail_log_data[head];\r\n\t\t\t\te->af = R->AF.W;\r\n\t\t\t\te->bc = R->BC.W;\r\n\t\t\t\te->de = R->DE.W;\r\n\t\t\t\te->hl = R->HL.W;\r\n\t\t\t\te->ix = R->IX.W;\r\n\t\t\t\te->iy = R->IY.W;\r\n\t\t\t\te->pc = R->PC.W;\r\n\t\t\t\te->sp = R->SP.W;\r\n\t\t\t\tif (++Debugger.pc_detail_log_head == log_size)\r\n\t\t\t\t\tDebugger.pc_detail_log_head = 0;\r\n\t\t\t\tif (Debugger.pc_detail_log_count < log_size)\r\n\t\t\t\t\tDebugger.pc_detail_log_count++;\r\n\t\t\t}\r\n\t\t}\r\n#endif // MEKA_Z80_DEBUGGER\r\n\r\n        // Save ICount before instruction\r\n        icount_before_instruction = R->ICount;\r\n\r\n        // Execute instruction\r\n        I = RdZ80 (R->PC.W ++);\r\n        R->R++;\r\n        R->ICount -= Cycles[I];\r\n        #ifdef MEKA_Z80_OPCODES_USAGE\r\n            Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_NONE][I]++;\r\n        #endif\r\n        switch (I)\r\n        {\r\n        #include \"Codes.h\"\r\n      case PFX_CB: CodesCB(R); break;\r\n      case PFX_ED: CodesED(R); break;\r\n      case PFX_FD: CodesFD(R); break;\r\n      case PFX_DD: CodesDD(R); break;\r\n        }\r\n\r\n        // Increment debugger cycle counter\r\n#ifdef MEKA_Z80_DEBUGGER\r\n        Debugger.cycle_counter += (icount_before_instruction - R->ICount);\r\n\r\n        // Reset stepping flag\r\n        Debugger.stepping = FALSE;\r\n#endif // MEKA_Z80_DEBUGGER\r\n\r\n        /* If cycle counter expired... */\r\n        if (R->ICount <= 0)\r\n        {\r\n            /* If we have come after EI, get address from IRequest */\r\n            /* Otherwise, get it from the loop handler             */\r\n            if (R->IFF & IFF_EI)\r\n            {\r\n                R->IFF=(R->IFF&~IFF_EI)|IFF_1; /* Done with AfterEI state */\r\n                R->ICount += R->IBackup - 1;   /* Restore the ICount       */\r\n\r\n                /* Call periodic handler or set pending IRQ */\r\n                if (R->ICount>0) J.W=R->IRequest;\r\n                else\r\n                {\r\n                    J.W = LoopZ80(/*R*/);                 /* Call periodic handler    */\r\n                    R->ICount+=R->IPeriod;                /* Add up to cycle counter  */\r\n                    if (J.W==INT_NONE) J.W=R->IRequest;   /* Pending IRQ */\r\n                }\r\n            }\r\n            else\r\n            {\r\n                J.W = LoopZ80(/*R*/);                   /* Call periodic handler    */\r\n                R->ICount+=R->IPeriod;                  /* Add up to cycle counter  */\r\n                if (J.W==INT_NONE) J.W=R->IRequest;     /* Pending int-rupt */\r\n            }\r\n\r\n            if (J.W == INT_QUIT) return (R->PC.W);    /* Exit if INT_QUIT */\r\n            if (J.W != INT_NONE) IntZ80 (R,J.W);      /* Int-pt if needed */\r\n        }\r\n    }\r\n\r\n    /* Execution stopped */\r\n   // Note: unreachable code\r\n    return (R->PC.W);\r\n}\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Z80.h",
    "content": "/** Z80: portable Z80 emulator *******************************/\r\n/**                                                         **/\r\n/**                           Z80.h                         **/\r\n/**                                                         **/\r\n/** This file contains declarations relevant to emulation   **/\r\n/** of Z80 CPU.                                             **/\r\n/**                                                         **/\r\n/** Copyright (C) Marat Fayzullin 1994-2002                 **/\r\n/**     You are not allowed to distribute this software     **/\r\n/**     commercially. Please, notify me, if you make any    **/\r\n/**     changes to this file.                               **/\r\n/*************************************************************/\r\n#ifndef Z80_H\r\n#define Z80_H\r\n\r\n                               /* Compilation options:       */\r\n/* #define DEBUG */            /* Compile debugging version  */\r\n #define LSB_FIRST */        /* Compile for low-endian CPU */\r\n/* #define MSB_FIRST */        /* Compile for hi-endian CPU  */\r\n\r\n                               /* LoopZ80() may return:      */\r\n#define INT_RST00   0x00C7     /* RST 00h                    */\r\n#define INT_RST08   0x00CF     /* RST 08h                    */\r\n#define INT_RST10   0x00D7     /* RST 10h                    */\r\n#define INT_RST18   0x00DF     /* RST 18h                    */\r\n#define INT_RST20   0x00E7     /* RST 20h                    */\r\n#define INT_RST28   0x00EF     /* RST 28h                    */\r\n#define INT_RST30   0x00F7     /* RST 30h                    */\r\n#define INT_RST38   0x00FF     /* RST 38h                    */\r\n#define INT_IRQ     INT_RST38  /* Default IRQ opcode is FFh  */\r\n#define INT_NMI     0xFFFD     /* Non-maskable interrupt     */\r\n#define INT_NONE    0xFFFF     /* No interrupt required      */\r\n#define INT_QUIT    0xFFFE     /* Exit the emulation         */\r\n\r\n                               /* Bits in Z80 F register:    */\r\n#define S_FLAG      0x80       /* 1: Result negative         */\r\n#define Z_FLAG      0x40       /* 1: Result is zero          */\r\n#define H_FLAG      0x10       /* 1: Halfcarry/Halfborrow    */\r\n#define P_FLAG      0x04       /* 1: Result is even          */\r\n#define V_FLAG      0x04       /* 1: Overflow occured        */\r\n#define N_FLAG      0x02       /* 1: Subtraction occured     */\r\n#define C_FLAG      0x01       /* 1: Carry/Borrow occured    */\r\n\r\n                               /* Bits in IFF flip-flops:    */\r\n#define IFF_1       0x01       /* IFF1 flip-flop             */\r\n#define IFF_IM1     0x02       /* 1: IM1 mode                */\r\n#define IFF_IM2     0x04       /* 1: IM2 mode                */\r\n#define IFF_2       0x08       /* IFF2 flip-flop             */\r\n#define IFF_EI      0x20       /* 1: EI pending              */\r\n#define IFF_HALT    0x80       /* 1: CPU HALTed              */\r\n\r\n/** Simple Datatypes *****************************************/\r\n/** NOTICE: sizeof(byte)=1 and sizeof(word)=2               **/\r\n/*************************************************************/\r\n#ifndef BYTE_TYPE_DEFINED\r\n#define BYTE_TYPE_DEFINED\r\ntypedef unsigned char byte;\r\n#endif\r\n#ifndef WORD_TYPE_DEFINED\r\n#define WORD_TYPE_DEFINED\r\ntypedef unsigned short word;\r\n#endif\r\ntypedef signed char offset;\r\n\r\n/** Structured Datatypes *************************************/\r\n/** NOTICE: #define LSB_FIRST for machines where least      **/\r\n/**         signifcant byte goes first.                     **/\r\n/*************************************************************/\r\ntypedef union\r\n{\r\n#ifdef LSB_FIRST\r\n  struct { byte l,h; } B;\r\n#else\r\n  struct { byte h,l; } B;\r\n#endif\r\n  word W;\r\n} pair;\r\n\r\ntypedef struct\r\n{\r\n  pair AF, BC, DE, HL, IX, IY, PC, SP;  /* Main registers      */\r\n  pair AF1, BC1, DE1, HL1;              /* Shadow registers    */\r\n  byte IFF, I;                          /* Interrupt registers */\r\n  byte R, R7;                           /* Refresh register    */ /* Copy of 7th bit of R assigned by user */\r\n\r\n  int  IPeriod, ICount; /* Set IPeriod to number of CPU cycles */\r\n                        /* between calls to LoopZ80()          */\r\n  int  IBackup;         /* Private, don't touch                */\r\n  word IRequest;        /* Set to address of pending IRQ       */\r\n\r\n  /* Miscellaneous */\r\n  byte IAutoReset;      /* Set to 1 to autom. reset IRequest   */\r\n  byte TrapBadOps;      /* Set to 1 to warn of illegal opcodes */\r\n  word Trap;            /* Set Trap to address to trace from   */\r\n  byte Trace;           /* Set Trace=1 to start tracing        */\r\n  void *User;           /* Arbitrary user data (ID,RAM*,etc.)  */\r\n} Z80;\r\n\r\n/** ResetZ80() ***********************************************/\r\n/** This function can be used to reset the registers before **/\r\n/** starting execution with RunZ80(). It sets registers to  **/\r\n/** their initial values.                                   **/\r\n/*************************************************************/\r\nvoid    ResetZ80(register Z80 *R);\r\n\r\n/** IntZ80() *************************************************/\r\n/** This function will generate interrupt of given vector.  **/\r\n/*************************************************************/\r\nvoid    IntZ80(register Z80 *R,register word Vector);\r\n\r\n/** RunZ80() *************************************************/\r\n/** This function will run Z80 code until an LoopZ80() call **/\r\n/** returns INT_QUIT. It will return the PC at which        **/\r\n/** emulation stopped, and current register values in R.    **/\r\n/*************************************************************/\r\nword    RunZ80(register Z80 *R);\r\nword    RunZ80_Debugging(Z80 *R); /* MEKA */\r\n\r\n/** RdZ80()/WrZ80() ******************************************/\r\n/** These functions are called when access to RAM occurs.   **/\r\n/** They allow to control memory access.                    **/\r\n/************************************ TO BE WRITTEN BY USER **/\r\nextern void    (*WrZ80)(register word Addr, register byte Value);\r\nextern byte    (*RdZ80)(register word Addr);\r\n\r\n// Those are no-hook version to be used by tools.\r\n// The Z80 emulator still use the normal version, which may be hooked by the debugger.\r\nextern void    (*WrZ80_NoHook)(register word Addr, register byte Value);\r\nextern byte    (*RdZ80_NoHook)(register word Addr);\r\n\r\n/** InZ80()/OutZ80() *****************************************/\r\n/** Z80 emulation calls these functions to read/write from  **/\r\n/** I/O ports. There can be 65536 I/O ports, but only first **/\r\n/** 256 are usually used                                    **/\r\n/************************************ TO BE WRITTEN BY USER **/\r\n\r\nextern void    (*OutZ80)(register word Port, register byte Value);\r\nextern byte    (*InZ80)(register word Port);\r\n\r\n// Those are no-hook version to be used by tools.\r\n// The Z80 emulator still use the normal version, which may be hooked by the debugger.\r\nextern void    (*OutZ80_NoHook)(register word Port, register byte Value);\r\nextern byte    (*InZ80_NoHook)(register word Port);\r\n\r\n/** PatchZ80() ***********************************************/\r\n/** Z80 emulation calls this function when it encounters a  **/\r\n/** special patch command (ED FE) provided for user needs.  **/\r\n/** For example, it can be called to emulate BIOS calls,    **/\r\n/** such as disk and tape access. Replace it with an empty  **/\r\n/** macro for no patching.                                  **/\r\n/************************************ TO BE WRITTEN BY USER **/\r\nvoid    PatchZ80(register Z80 *R);\r\n\r\n/** DebugZ80() ***********************************************/\r\n/** This function should exist if DEBUG is #defined. When   **/\r\n/** Trace!=0, it is called after each command executed by   **/\r\n/** the CPU, and given the Z80 registers. Emulation exits   **/\r\n/** if DebugZ80() returns 0.                                **/\r\n/*************************************************************/\r\n// #ifdef DEBUG\r\nbyte    DebugZ80(register Z80 *R);\r\n// #endif DEBUG\r\n\r\n/** LoopZ80() ************************************************/\r\n/** Z80 emulation calls this function periodically to check **/\r\n/** if the system hardware requires any interrupts. This    **/\r\n/** function must return an address of the interrupt vector **/\r\n/** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt.    **/\r\n/** Return INT_QUIT to exit the emulation loop.             **/\r\n/************************************ TO BE WRITTEN BY USER **/\r\nextern word    (*LoopZ80)(/*register Z80 *R*/ void);\r\n\r\n/**** Opcode usage statistics ********************************/\r\nvoid    Z80_Opcodes_Usage_Print();\r\n\r\n#endif /* Z80_H */\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Z80Call.cpp",
    "content": "/** Z80-Call *************************************************/\r\n/** This file contains debugging tools created for MEKA     **/\r\n/** in order to log what opcodes are being used in a game.  **/\r\n/*************************************************************/\r\n\r\n// Define to enable Z80-Call functionnality\r\n// (Slow down emulation)\r\n// #define MEKA_Z80_OPCODES_USAGE\r\n\r\n#ifdef MEKA_Z80_OPCODES_USAGE\r\n\r\n#define MEKA_Z80_OPCODE_PREFIX_NONE     (0)\r\n#define MEKA_Z80_OPCODE_PREFIX_CB       (1)\r\n#define MEKA_Z80_OPCODE_PREFIX_DD       (2)\r\n#define MEKA_Z80_OPCODE_PREFIX_DDCB     (3)\r\n#define MEKA_Z80_OPCODE_PREFIX_ED       (4)\r\n#define MEKA_Z80_OPCODE_PREFIX_FD       (5)\r\n#define MEKA_Z80_OPCODE_PREFIX_FDCB     (6)\r\n#define MEKA_Z80_OPCODE_PREFIX_MAX      (7)\r\n\r\nint     Z80_Opcodes_Usage [MEKA_Z80_OPCODE_PREFIX_MAX] [256];\r\n\r\nvoid    Z80_Opcodes_Usage_Reset()\r\n{\r\n memset (Z80_Opcodes_Usage, 0, sizeof (Z80_Opcodes_Usage));\r\n}\r\n\r\nextern  byte  *ROM;\r\nextern  byte  *Mem_Pages[8];\r\nextern  int    Z80_Disassemble(char *S, word A, bool display_symbols, bool display_symbols_for_current_index_registers, bool resolve_indirect_offsets);\r\n\r\nvoid    Z80_Opcodes_Usage_Print()\r\n{\r\n int    i, j;\r\n byte  *op_code = Mem_Pages[0] = ROM; // Note: this will screws up data in ROM\r\n int    op_code_pos;\r\n byte   op_name[32];\r\n byte  *cycles;\r\n\r\n printf (\"Z80_Opcodes_Usage_Print();\\n\");\r\n for (i = 0; i < MEKA_Z80_OPCODE_PREFIX_MAX; i++)\r\n     {\r\n     op_code_pos = 0;\r\n     memset (op_code, 0, 16);\r\n     switch (i)\r\n        {\r\n        case MEKA_Z80_OPCODE_PREFIX_CB:   cycles = CyclesCB;   printf (\"---- Prefix: CB\\n\");   op_code[op_code_pos++] = 0xCB; break;\r\n        case MEKA_Z80_OPCODE_PREFIX_DD:   cycles = CyclesXX;   printf (\"---- Prefix: DD\\n\");   op_code[op_code_pos++] = 0xDD; break;\r\n        case MEKA_Z80_OPCODE_PREFIX_DDCB: cycles = CyclesXXCB; printf (\"---- Prefix: DDCB\\n\"); op_code[op_code_pos++] = 0xDD; op_code[op_code_pos++] = 0xCB; break;\r\n        case MEKA_Z80_OPCODE_PREFIX_ED:   cycles = CyclesED;   printf (\"---- Prefix: ED\\n\");   op_code[op_code_pos++] = 0xED; break;\r\n        case MEKA_Z80_OPCODE_PREFIX_FD:   cycles = CyclesXX;   printf (\"---- Prefix: FD\\n\");   op_code[op_code_pos++] = 0xFD; break;\r\n        case MEKA_Z80_OPCODE_PREFIX_FDCB: cycles = CyclesXXCB; printf (\"---- Prefix: FDCB\\n\"); op_code[op_code_pos++] = 0xFD; op_code[op_code_pos++] = 0xCB; break;\r\n        case MEKA_Z80_OPCODE_PREFIX_NONE:\r\n        default:                          cycles = Cycles;     printf (\"---- Prefix: None\\n\"); break;\r\n        }\r\n     for (j = 0; j < 256; j++)\r\n        if (Z80_Opcodes_Usage[i][j] > 0)\r\n           {\r\n           op_code[op_code_pos] = j;\r\n           Z80_Disassemble(op_name, 0x0000, false, false, false);\r\n           printf (\"Opcode %02X : %- 12i%-20s%d\\n\", j, Z80_Opcodes_Usage[i][j], op_name, cycles[j]);\r\n           }\r\n     }\r\n}\r\n\r\n#endif /* MEKA_Z80_OPCODES_USAGE */\r\n\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Z80DebugHelpers.cpp",
    "content": "#include \"shared.h\"\r\n#include \"Z80.h\"\r\n#include \"Z80DebugHelpers.h\"\r\n#include \"Z80OpcodeEnums.h\"\r\n\r\nbool\tZ80DebugHelper_IsRetExecuting(const Z80 *R)\r\n{\r\n\tu16 pc = R->PC.W;\r\n\r\n\tu8 I = RdZ80_NoHook(pc++);\r\n\r\n\tif (I == PFX_ED)\r\n\t{\r\n\t\twhile ((I = RdZ80_NoHook(pc++)) == PFX_ED) {}\r\n\t\tswitch (I)\r\n\t\t{\r\n\t\tcase RETI: return true;\r\n\t\tcase RETN: return true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif (I == PFX_DD || I == PFX_FD)\r\n\t{\r\n\t\twhile ((I = RdZ80_NoHook(pc++)) == PFX_DD || I == PFX_FD) {}\r\n\t\t// RET opcodes after DD/FD prefixes are the same as with no prefix\r\n\t}\r\n\r\n\tswitch (I)\r\n\t{\r\n\tcase RET_NZ:  return (!(R->AF.B.l&Z_FLAG));\r\n\tcase RET_NC:  return (!(R->AF.B.l&C_FLAG));\r\n\tcase RET_PO:  return (!(R->AF.B.l&P_FLAG));\r\n\tcase RET_P:   return (!(R->AF.B.l&S_FLAG));\r\n\tcase RET_Z:   return ((R->AF.B.l&Z_FLAG)!=0);\r\n\tcase RET_C:   return ((R->AF.B.l&C_FLAG)!=0);\r\n\tcase RET_PE:  return ((R->AF.B.l&P_FLAG)!=0);\r\n\tcase RET_M:   return ((R->AF.B.l&S_FLAG)!=0);\r\n\tcase RET:\t  return true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Z80DebugHelpers.h",
    "content": "\r\nbool\tZ80DebugHelper_IsRetExecuting(const Z80 *R);\r\n"
  },
  {
    "path": "meka/srcs/z80marat/Z80OpcodeEnums.h",
    "content": "enum Codes\r\n{\r\n  NOP, LD_BC_WORD, LD_xBC_A, INC_BC, INC_B, DEC_B, LD_B_BYTE, RLCA,     // 00-07\r\n  EX_AF_AF, ADD_HL_BC, LD_A_xBC, DEC_BC, INC_C, DEC_C, LD_C_BYTE, RRCA, // 08-0F\r\n  DJNZ, LD_DE_WORD, LD_xDE_A, INC_DE, INC_D, DEC_D, LD_D_BYTE, RLA,     // 10-17\r\n  JR, ADD_HL_DE, LD_A_xDE, DEC_DE, INC_E, DEC_E, LD_E_BYTE, RRA,        // 18-1F\r\n  JR_NZ, LD_HL_WORD, LD_xWORD_HL, INC_HL, INC_H, DEC_H, LD_H_BYTE, DAA, // 20-27\r\n  JR_Z, ADD_HL_HL, LD_HL_xWORD, DEC_HL, INC_L, DEC_L, LD_L_BYTE, CPL,   // 28-2F\r\n  JR_NC, LD_SP_WORD, LD_xWORD_A, INC_SP, INC_xHL, DEC_xHL, LD_xHL_BYTE, SCF, // 30-37\r\n  JR_C, ADD_HL_SP, LD_A_xWORD, DEC_SP, INC_A, DEC_A, LD_A_BYTE, CCF,    // 38-3F\r\n  LD_B_B, LD_B_C, LD_B_D, LD_B_E, LD_B_H, LD_B_L, LD_B_xHL, LD_B_A,     // 40-47\r\n  LD_C_B, LD_C_C, LD_C_D, LD_C_E, LD_C_H, LD_C_L, LD_C_xHL, LD_C_A,     // 48-4F\r\n  LD_D_B, LD_D_C, LD_D_D, LD_D_E, LD_D_H, LD_D_L, LD_D_xHL, LD_D_A,     // 50-57\r\n  LD_E_B, LD_E_C, LD_E_D, LD_E_E, LD_E_H, LD_E_L, LD_E_xHL, LD_E_A,     // 58-5F\r\n  LD_H_B, LD_H_C, LD_H_D, LD_H_E, LD_H_H, LD_H_L, LD_H_xHL, LD_H_A,     // 60-67\r\n  LD_L_B, LD_L_C, LD_L_D, LD_L_E, LD_L_H, LD_L_L, LD_L_xHL, LD_L_A,     // 68-6F\r\n  LD_xHL_B, LD_xHL_C, LD_xHL_D, LD_xHL_E, LD_xHL_H, LD_xHL_L, HALT, LD_xHL_A, // 70-77\r\n  LD_A_B, LD_A_C, LD_A_D, LD_A_E, LD_A_H, LD_A_L, LD_A_xHL, LD_A_A,     // 78-7F\r\n  ADD_B, ADD_C, ADD_D, ADD_E, ADD_H, ADD_L, ADD_xHL, ADD_A,             // 80-87\r\n  ADC_B, ADC_C, ADC_D, ADC_E, ADC_H, ADC_L, ADC_xHL, ADC_A,             // 88-8F\r\n  SUB_B, SUB_C, SUB_D, SUB_E, SUB_H, SUB_L, SUB_xHL, SUB_A,             // 90-97\r\n  SBC_B, SBC_C, SBC_D, SBC_E, SBC_H, SBC_L, SBC_xHL, SBC_A,             // 98-9F\r\n  AND_B, AND_C, AND_D, AND_E, AND_H, AND_L, AND_xHL, AND_A,             // A0-A7\r\n  XOR_B, XOR_C, XOR_D, XOR_E, XOR_H, XOR_L, XOR_xHL, XOR_A,             // A8-AF\r\n  OR_B, OR_C, OR_D, OR_E, OR_H, OR_L, OR_xHL, OR_A,                     // B0-B7\r\n  CP_B, CP_C, CP_D, CP_E, CP_H, CP_L, CP_xHL, CP_A,                     // B8-BF\r\n  RET_NZ, POP_BC, JP_NZ, JP, CALL_NZ, PUSH_BC, ADD_BYTE, RST00,         // C0-C7\r\n  RET_Z, RET, JP_Z, PFX_CB, CALL_Z, CALL, ADC_BYTE, RST08,              // C8-CF\r\n  RET_NC, POP_DE, JP_NC, OUTA, CALL_NC, PUSH_DE, SUB_BYTE, RST10,       // D0-D7\r\n  RET_C, EXX, JP_C, INA, CALL_C, PFX_DD, SBC_BYTE, RST18,               // D8-DF\r\n  RET_PO, POP_HL, JP_PO, EX_HL_xSP, CALL_PO, PUSH_HL, AND_BYTE, RST20,  // E0-E7\r\n  RET_PE, LD_PC_HL, JP_PE, EX_DE_HL, CALL_PE, PFX_ED, XOR_BYTE, RST28,  // E8-EF\r\n  RET_P, POP_AF, JP_P, DI, CALL_P, PUSH_AF, OR_BYTE, RST30,             // F0-F7\r\n  RET_M, LD_SP_HL, JP_M, EI, CALL_M, PFX_FD, CP_BYTE, RST38             // F8-FF\r\n};\r\n\r\nenum CodesCB\r\n{\r\n  RLC_B, RLC_C, RLC_D, RLC_E, RLC_H, RLC_L, RLC_xHL, RLC_A,             // 00-07\r\n  RRC_B, RRC_C, RRC_D, RRC_E, RRC_H, RRC_L, RRC_xHL, RRC_A,             // 08-0F\r\n  RL_B, RL_C, RL_D, RL_E, RL_H, RL_L, RL_xHL, RL_A,                     // 10-17\r\n  RR_B, RR_C, RR_D, RR_E, RR_H, RR_L, RR_xHL, RR_A,                     // 18-1F\r\n  SLA_B, SLA_C, SLA_D, SLA_E, SLA_H, SLA_L, SLA_xHL, SLA_A,             // 20-27\r\n  SRA_B, SRA_C, SRA_D, SRA_E, SRA_H, SRA_L, SRA_xHL, SRA_A,             // 28-2F\r\n  SLL_B, SLL_C, SLL_D, SLL_E, SLL_H, SLL_L, SLL_xHL, SLL_A,             // 30-37\r\n  SRL_B, SRL_C, SRL_D, SRL_E, SRL_H, SRL_L, SRL_xHL, SRL_A,             // 38-3F\r\n  BIT0_B, BIT0_C, BIT0_D, BIT0_E, BIT0_H, BIT0_L, BIT0_xHL, BIT0_A,     // 40-47\r\n  BIT1_B, BIT1_C, BIT1_D, BIT1_E, BIT1_H, BIT1_L, BIT1_xHL, BIT1_A,     // 48-4F\r\n  BIT2_B, BIT2_C, BIT2_D, BIT2_E, BIT2_H, BIT2_L, BIT2_xHL, BIT2_A,     // 50-57\r\n  BIT3_B, BIT3_C, BIT3_D, BIT3_E, BIT3_H, BIT3_L, BIT3_xHL, BIT3_A,     // 58-5F\r\n  BIT4_B, BIT4_C, BIT4_D, BIT4_E, BIT4_H, BIT4_L, BIT4_xHL, BIT4_A,     // 60-67\r\n  BIT5_B, BIT5_C, BIT5_D, BIT5_E, BIT5_H, BIT5_L, BIT5_xHL, BIT5_A,     // 68-6F\r\n  BIT6_B, BIT6_C, BIT6_D, BIT6_E, BIT6_H, BIT6_L, BIT6_xHL, BIT6_A,     // 70-77\r\n  BIT7_B, BIT7_C, BIT7_D, BIT7_E, BIT7_H, BIT7_L, BIT7_xHL, BIT7_A,     // 78-7F\r\n  RES0_B, RES0_C, RES0_D, RES0_E, RES0_H, RES0_L, RES0_xHL, RES0_A,     // 80-87\r\n  RES1_B, RES1_C, RES1_D, RES1_E, RES1_H, RES1_L, RES1_xHL, RES1_A,     // 88-8F\r\n  RES2_B, RES2_C, RES2_D, RES2_E, RES2_H, RES2_L, RES2_xHL, RES2_A,     // 90-97\r\n  RES3_B, RES3_C, RES3_D, RES3_E, RES3_H, RES3_L, RES3_xHL, RES3_A,     // 98-9F\r\n  RES4_B, RES4_C, RES4_D, RES4_E, RES4_H, RES4_L, RES4_xHL, RES4_A,     // A0-A7\r\n  RES5_B, RES5_C, RES5_D, RES5_E, RES5_H, RES5_L, RES5_xHL, RES5_A,     // A8-AF\r\n  RES6_B, RES6_C, RES6_D, RES6_E, RES6_H, RES6_L, RES6_xHL, RES6_A,     // B0-B7\r\n  RES7_B, RES7_C, RES7_D, RES7_E, RES7_H, RES7_L, RES7_xHL, RES7_A,     // B8-BF\r\n  SET0_B, SET0_C, SET0_D, SET0_E, SET0_H, SET0_L, SET0_xHL, SET0_A,     // C0-C7\r\n  SET1_B, SET1_C, SET1_D, SET1_E, SET1_H, SET1_L, SET1_xHL, SET1_A,     // C8-CF\r\n  SET2_B, SET2_C, SET2_D, SET2_E, SET2_H, SET2_L, SET2_xHL, SET2_A,     // D0-D7\r\n  SET3_B, SET3_C, SET3_D, SET3_E, SET3_H, SET3_L, SET3_xHL, SET3_A,     // D8-DF\r\n  SET4_B, SET4_C, SET4_D, SET4_E, SET4_H, SET4_L, SET4_xHL, SET4_A,     // E0-E7\r\n  SET5_B, SET5_C, SET5_D, SET5_E, SET5_H, SET5_L, SET5_xHL, SET5_A,     // E8-EF\r\n  SET6_B, SET6_C, SET6_D, SET6_E, SET6_H, SET6_L, SET6_xHL, SET6_A,     // F0-F7\r\n  SET7_B, SET7_C, SET7_D, SET7_E, SET7_H, SET7_L, SET7_xHL, SET7_A      // F8-FF\r\n};\r\n\r\nenum CodesED\r\n{\r\n  DB_00, DB_01, DB_02, DB_03, DB_04, DB_05, DB_06, DB_07,               // 00-07\r\n  DB_08, DB_09, DB_0A, DB_0B, DB_0C, DB_0D, DB_0E, DB_0F,               // 08-0F\r\n  DB_10, DB_11, DB_12, DB_13, DB_14, DB_15, DB_16, DB_17,               // 10-17\r\n  DB_18, DB_19, DB_1A, DB_1B, DB_1C, DB_1D, DB_1E, DB_1F,               // 18-1F\r\n  DB_20, DB_21, DB_22, DB_23, DB_24, DB_25, DB_26, DB_27,               // 20-27\r\n  DB_28, DB_29, DB_2A, DB_2B, DB_2C, DB_2D, DB_2E, DB_2F,               // 28-2F\r\n  DB_30, DB_31, DB_32, DB_33, DB_34, DB_35, DB_36, DB_37,               // 30-37\r\n  DB_38, DB_39, DB_3A, DB_3B, DB_3C, DB_3D, DB_3E, DB_3F,               // 38-3F\r\n  IN_B_xC, OUT_xC_B, SBC_HL_BC, LD_xWORDe_BC, NEG, RETN, IM_0, LD_I_A,    // 40-47\r\n  IN_C_xC, OUT_xC_C, ADC_HL_BC, LD_BC_xWORDe, DB_4C, RETI, DB_4E, LD_R_A, // 48-4F\r\n  IN_D_xC, OUT_xC_D, SBC_HL_DE, LD_xWORDe_DE, DB_54, DB_55, IM_1, LD_A_I, // 50-57\r\n  IN_E_xC, OUT_xC_E, ADC_HL_DE, LD_DE_xWORDe, DB_5C, DB_5D, IM_2, LD_A_R, // 58-5F\r\n  IN_H_xC, OUT_xC_H, SBC_HL_HL, LD_xWORDe_HL, DB_64, DB_65, DB_66, RRD,   // 60-67\r\n  IN_L_xC, OUT_xC_L, ADC_HL_HL, LD_HL_xWORDe, DB_6C, DB_6D, DB_6E, RLD,   // 68-6F\r\n  IN_F_xC, OUT_xC_0, SBC_HL_SP, LD_xWORDe_SP, DB_74, DB_75, DB_76, DB_77, // 70-77\r\n  IN_A_xC, OUT_xC_A, ADC_HL_SP, LD_SP_xWORDe, DB_7C, DB_7D, DB_7E, DB_7F, // 78-7F\r\n  DB_80, DB_81, DB_82, DB_83, DB_84, DB_85, DB_86, DB_87,               // 80-87\r\n  DB_88, DB_89, DB_8A, DB_8B, DB_8C, DB_8D, DB_8E, DB_8F,               // 88-8F\r\n  DB_90, DB_91, DB_92, DB_93, DB_94, DB_95, DB_96, DB_97,               // 90-97\r\n  DB_98, DB_99, DB_9A, DB_9B, DB_9C, DB_9D, DB_9E, DB_9F,               // 98-9F\r\n  LDI, CPI, INI, OUTI, DB_A4, DB_A5, DB_A6, DB_A7,                      // A0-A7\r\n  LDD, CPD, IND, OUTD, DB_AC, DB_AD, DB_AE, DB_AF,                      // A8-AF\r\n  LDIR, CPIR, INIR, OTIR, DB_B4, DB_B5, DB_B6, DB_B7,                   // B0-B7\r\n  LDDR, CPDR, INDR, OTDR, DB_BC, DB_BD, DB_BE, DB_BF,                   // B8-BF\r\n  DB_C0, DB_C1, DB_C2, DB_C3, DB_C4, DB_C5, DB_C6, DB_C7,               // C0-C7\r\n  DB_C8, DB_C9, DB_CA, DB_CB, DB_CC, DB_CD, DB_CE, DB_CF,               // C8-CF\r\n  DB_D0, DB_D1, DB_D2, DB_D3, DB_D4, DB_D5, DB_D6, DB_D7,               // D0-D7\r\n  DB_D8, DB_D9, DB_DA, DB_DB, DB_DC, DB_DD, DB_DE, DB_DF,               // D8-DF\r\n  DB_E0, DB_E1, DB_E2, DB_E3, DB_E4, DB_E5, DB_E6, DB_E7,               // E0-E7\r\n  DB_E8, DB_E9, DB_EA, DB_EB, DB_EC, DB_ED, DB_EE, DB_EF,               // E8-EF\r\n  DB_F0, DB_F1, DB_F2, DB_F3, DB_F4, DB_F5, DB_F6, DB_F7,               // F0-F7\r\n  DB_F8, DB_F9, DB_FA, DB_FB, DB_FC, DB_FD, DB_FE, DB_FF                // F8-FF\r\n};\r\n"
  },
  {
    "path": "meka/srcs/z80marat/dasm.cpp",
    "content": "/** Z80 Disassembler ******************************************/\r\n/**                                                          **/\r\n/**                         dasmz80.c                        **/\r\n/**                                                          **/\r\n/** This file contains the source of a portable disassembler **/\r\n/** for the Z80 CPU.                                         **/\r\n/**                                                          **/\r\n/** Copyright (C) Marat Fayzullin 1995,1996                  **/\r\n/**     You are not allowed to distribute this software      **/\r\n/**     commercially. Please, notify me, if you make any     **/\r\n/**     changes to this file.                                **/\r\n/**************************************************************/\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\n#ifdef ZLIB\r\n#include <zlib.h>\r\n#define fopen          gzopen\r\n#define fclose         gzclose\r\n#define fread(B,N,L,F) gzread(F,B,(L)*(N))\r\n#endif\r\n\r\ntypedef unsigned char byte;   /* This type is exactly 1 byte  */\r\ntypedef unsigned short word;  /* This type is exactly 2 bytes */\r\n\r\nstatic int PrintHex;          /* Print hexadecimal codes      */\r\nstatic unsigned long Counter; /* Address counter              */\r\n\r\nstatic int DAsm(char *S,byte *A);\r\n    /* This function will disassemble a single command and    */\r\n    /* return the number of bytes disassembled.               */\r\n\r\nstatic char *Mnemonics[256] =\r\n{\r\n  \"NOP\",\"LD BC,#h\",\"LD (BC),A\",\"INC BC\",\"INC B\",\"DEC B\",\"LD B,*h\",\"RLCA\",\r\n  \"EX AF,AF'\",\"ADD HL,BC\",\"LD A,(BC)\",\"DEC BC\",\"INC C\",\"DEC C\",\"LD C,*h\",\"RRCA\",\r\n  \"DJNZ @h\",\"LD DE,#h\",\"LD (DE),A\",\"INC DE\",\"INC D\",\"DEC D\",\"LD D,*h\",\"RLA\",\r\n  \"JR @h\",\"ADD HL,DE\",\"LD A,(DE)\",\"DEC DE\",\"INC E\",\"DEC E\",\"LD E,*h\",\"RRA\",\r\n  \"JR NZ,@h\",\"LD HL,#h\",\"LD (#h),HL\",\"INC HL\",\"INC H\",\"DEC H\",\"LD H,*h\",\"DAA\",\r\n  \"JR Z,@h\",\"ADD HL,HL\",\"LD HL,(#h)\",\"DEC HL\",\"INC L\",\"DEC L\",\"LD L,*h\",\"CPL\",\r\n  \"JR NC,@h\",\"LD SP,#h\",\"LD (#h),A\",\"INC SP\",\"INC (HL)\",\"DEC (HL)\",\"LD (HL),*h\",\"SCF\",\r\n  \"JR C,@h\",\"ADD HL,SP\",\"LD A,(#h)\",\"DEC SP\",\"INC A\",\"DEC A\",\"LD A,*h\",\"CCF\",\r\n  \"LD B,B\",\"LD B,C\",\"LD B,D\",\"LD B,E\",\"LD B,H\",\"LD B,L\",\"LD B,(HL)\",\"LD B,A\",\r\n  \"LD C,B\",\"LD C,C\",\"LD C,D\",\"LD C,E\",\"LD C,H\",\"LD C,L\",\"LD C,(HL)\",\"LD C,A\",\r\n  \"LD D,B\",\"LD D,C\",\"LD D,D\",\"LD D,E\",\"LD D,H\",\"LD D,L\",\"LD D,(HL)\",\"LD D,A\",\r\n  \"LD E,B\",\"LD E,C\",\"LD E,D\",\"LD E,E\",\"LD E,H\",\"LD E,L\",\"LD E,(HL)\",\"LD E,A\",\r\n  \"LD H,B\",\"LD H,C\",\"LD H,D\",\"LD H,E\",\"LD H,H\",\"LD H,L\",\"LD H,(HL)\",\"LD H,A\",\r\n  \"LD L,B\",\"LD L,C\",\"LD L,D\",\"LD L,E\",\"LD L,H\",\"LD L,L\",\"LD L,(HL)\",\"LD L,A\",\r\n  \"LD (HL),B\",\"LD (HL),C\",\"LD (HL),D\",\"LD (HL),E\",\"LD (HL),H\",\"LD (HL),L\",\"HALT\",\"LD (HL),A\",\r\n  \"LD A,B\",\"LD A,C\",\"LD A,D\",\"LD A,E\",\"LD A,H\",\"LD A,L\",\"LD A,(HL)\",\"LD A,A\",\r\n  \"ADD B\",\"ADD C\",\"ADD D\",\"ADD E\",\"ADD H\",\"ADD L\",\"ADD (HL)\",\"ADD A\",\r\n  \"ADC B\",\"ADC C\",\"ADC D\",\"ADC E\",\"ADC H\",\"ADC L\",\"ADC (HL)\",\"ADC A\",\r\n  \"SUB B\",\"SUB C\",\"SUB D\",\"SUB E\",\"SUB H\",\"SUB L\",\"SUB (HL)\",\"SUB A\",\r\n  \"SBC B\",\"SBC C\",\"SBC D\",\"SBC E\",\"SBC H\",\"SBC L\",\"SBC (HL)\",\"SBC A\",\r\n  \"AND B\",\"AND C\",\"AND D\",\"AND E\",\"AND H\",\"AND L\",\"AND (HL)\",\"AND A\",\r\n  \"XOR B\",\"XOR C\",\"XOR D\",\"XOR E\",\"XOR H\",\"XOR L\",\"XOR (HL)\",\"XOR A\",\r\n  \"OR B\",\"OR C\",\"OR D\",\"OR E\",\"OR H\",\"OR L\",\"OR (HL)\",\"OR A\",\r\n  \"CP B\",\"CP C\",\"CP D\",\"CP E\",\"CP H\",\"CP L\",\"CP (HL)\",\"CP A\",\r\n  \"RET NZ\",\"POP BC\",\"JP NZ,#h\",\"JP #h\",\"CALL NZ,#h\",\"PUSH BC\",\"ADD *h\",\"RST 00h\",\r\n  \"RET Z\",\"RET\",\"JP Z,#h\",\"PFX_CB\",\"CALL Z,#h\",\"CALL #h\",\"ADC *h\",\"RST 08h\",\r\n  \"RET NC\",\"POP DE\",\"JP NC,#h\",\"OUTA (*h)\",\"CALL NC,#h\",\"PUSH DE\",\"SUB *h\",\"RST 10h\",\r\n  \"RET C\",\"EXX\",\"JP C,#h\",\"INA (*h)\",\"CALL C,#h\",\"PFX_DD\",\"SBC *h\",\"RST 18h\",\r\n  \"RET PO\",\"POP HL\",\"JP PO,#h\",\"EX HL,(SP)\",\"CALL PO,#h\",\"PUSH HL\",\"AND *h\",\"RST 20h\",\r\n  \"RET PE\",\"LD PC,HL\",\"JP PE,#h\",\"EX DE,HL\",\"CALL PE,#h\",\"PFX_ED\",\"XOR *h\",\"RST 28h\",\r\n  \"RET P\",\"POP AF\",\"JP P,#h\",\"DI\",\"CALL P,#h\",\"PUSH AF\",\"OR *h\",\"RST 30h\",\r\n  \"RET M\",\"LD SP,HL\",\"JP M,#h\",\"EI\",\"CALL M,#h\",\"PFX_FD\",\"CP *h\",\"RST 38h\"\r\n};\r\n\r\nstatic char *MnemonicsCB[256] =\r\n{\r\n  \"RLC B\",\"RLC C\",\"RLC D\",\"RLC E\",\"RLC H\",\"RLC L\",\"RLC (HL)\",\"RLC A\",\r\n  \"RRC B\",\"RRC C\",\"RRC D\",\"RRC E\",\"RRC H\",\"RRC L\",\"RRC (HL)\",\"RRC A\",\r\n  \"RL B\",\"RL C\",\"RL D\",\"RL E\",\"RL H\",\"RL L\",\"RL (HL)\",\"RL A\",\r\n  \"RR B\",\"RR C\",\"RR D\",\"RR E\",\"RR H\",\"RR L\",\"RR (HL)\",\"RR A\",\r\n  \"SLA B\",\"SLA C\",\"SLA D\",\"SLA E\",\"SLA H\",\"SLA L\",\"SLA (HL)\",\"SLA A\",\r\n  \"SRA B\",\"SRA C\",\"SRA D\",\"SRA E\",\"SRA H\",\"SRA L\",\"SRA (HL)\",\"SRA A\",\r\n  \"SLL B\",\"SLL C\",\"SLL D\",\"SLL E\",\"SLL H\",\"SLL L\",\"SLL (HL)\",\"SLL A\",\r\n  \"SRL B\",\"SRL C\",\"SRL D\",\"SRL E\",\"SRL H\",\"SRL L\",\"SRL (HL)\",\"SRL A\",\r\n  \"BIT 0,B\",\"BIT 0,C\",\"BIT 0,D\",\"BIT 0,E\",\"BIT 0,H\",\"BIT 0,L\",\"BIT 0,(HL)\",\"BIT 0,A\",\r\n  \"BIT 1,B\",\"BIT 1,C\",\"BIT 1,D\",\"BIT 1,E\",\"BIT 1,H\",\"BIT 1,L\",\"BIT 1,(HL)\",\"BIT 1,A\",\r\n  \"BIT 2,B\",\"BIT 2,C\",\"BIT 2,D\",\"BIT 2,E\",\"BIT 2,H\",\"BIT 2,L\",\"BIT 2,(HL)\",\"BIT 2,A\",\r\n  \"BIT 3,B\",\"BIT 3,C\",\"BIT 3,D\",\"BIT 3,E\",\"BIT 3,H\",\"BIT 3,L\",\"BIT 3,(HL)\",\"BIT 3,A\",\r\n  \"BIT 4,B\",\"BIT 4,C\",\"BIT 4,D\",\"BIT 4,E\",\"BIT 4,H\",\"BIT 4,L\",\"BIT 4,(HL)\",\"BIT 4,A\",\r\n  \"BIT 5,B\",\"BIT 5,C\",\"BIT 5,D\",\"BIT 5,E\",\"BIT 5,H\",\"BIT 5,L\",\"BIT 5,(HL)\",\"BIT 5,A\",\r\n  \"BIT 6,B\",\"BIT 6,C\",\"BIT 6,D\",\"BIT 6,E\",\"BIT 6,H\",\"BIT 6,L\",\"BIT 6,(HL)\",\"BIT 6,A\",\r\n  \"BIT 7,B\",\"BIT 7,C\",\"BIT 7,D\",\"BIT 7,E\",\"BIT 7,H\",\"BIT 7,L\",\"BIT 7,(HL)\",\"BIT 7,A\",\r\n  \"RES 0,B\",\"RES 0,C\",\"RES 0,D\",\"RES 0,E\",\"RES 0,H\",\"RES 0,L\",\"RES 0,(HL)\",\"RES 0,A\",\r\n  \"RES 1,B\",\"RES 1,C\",\"RES 1,D\",\"RES 1,E\",\"RES 1,H\",\"RES 1,L\",\"RES 1,(HL)\",\"RES 1,A\",\r\n  \"RES 2,B\",\"RES 2,C\",\"RES 2,D\",\"RES 2,E\",\"RES 2,H\",\"RES 2,L\",\"RES 2,(HL)\",\"RES 2,A\",\r\n  \"RES 3,B\",\"RES 3,C\",\"RES 3,D\",\"RES 3,E\",\"RES 3,H\",\"RES 3,L\",\"RES 3,(HL)\",\"RES 3,A\",\r\n  \"RES 4,B\",\"RES 4,C\",\"RES 4,D\",\"RES 4,E\",\"RES 4,H\",\"RES 4,L\",\"RES 4,(HL)\",\"RES 4,A\",\r\n  \"RES 5,B\",\"RES 5,C\",\"RES 5,D\",\"RES 5,E\",\"RES 5,H\",\"RES 5,L\",\"RES 5,(HL)\",\"RES 5,A\",\r\n  \"RES 6,B\",\"RES 6,C\",\"RES 6,D\",\"RES 6,E\",\"RES 6,H\",\"RES 6,L\",\"RES 6,(HL)\",\"RES 6,A\",\r\n  \"RES 7,B\",\"RES 7,C\",\"RES 7,D\",\"RES 7,E\",\"RES 7,H\",\"RES 7,L\",\"RES 7,(HL)\",\"RES 7,A\",\r\n  \"SET 0,B\",\"SET 0,C\",\"SET 0,D\",\"SET 0,E\",\"SET 0,H\",\"SET 0,L\",\"SET 0,(HL)\",\"SET 0,A\",\r\n  \"SET 1,B\",\"SET 1,C\",\"SET 1,D\",\"SET 1,E\",\"SET 1,H\",\"SET 1,L\",\"SET 1,(HL)\",\"SET 1,A\",\r\n  \"SET 2,B\",\"SET 2,C\",\"SET 2,D\",\"SET 2,E\",\"SET 2,H\",\"SET 2,L\",\"SET 2,(HL)\",\"SET 2,A\",\r\n  \"SET 3,B\",\"SET 3,C\",\"SET 3,D\",\"SET 3,E\",\"SET 3,H\",\"SET 3,L\",\"SET 3,(HL)\",\"SET 3,A\",\r\n  \"SET 4,B\",\"SET 4,C\",\"SET 4,D\",\"SET 4,E\",\"SET 4,H\",\"SET 4,L\",\"SET 4,(HL)\",\"SET 4,A\",\r\n  \"SET 5,B\",\"SET 5,C\",\"SET 5,D\",\"SET 5,E\",\"SET 5,H\",\"SET 5,L\",\"SET 5,(HL)\",\"SET 5,A\",\r\n  \"SET 6,B\",\"SET 6,C\",\"SET 6,D\",\"SET 6,E\",\"SET 6,H\",\"SET 6,L\",\"SET 6,(HL)\",\"SET 6,A\",\r\n  \"SET 7,B\",\"SET 7,C\",\"SET 7,D\",\"SET 7,E\",\"SET 7,H\",\"SET 7,L\",\"SET 7,(HL)\",\"SET 7,A\"\r\n};\r\n\r\nstatic char *MnemonicsED[256] =\r\n{\r\n  \"DB EDh,00h\",\"DB EDh,01h\",\"DB EDh,02h\",\"DB EDh,03h\",\r\n  \"DB EDh,04h\",\"DB EDh,05h\",\"DB EDh,06h\",\"DB EDh,07h\",\r\n  \"DB EDh,08h\",\"DB EDh,09h\",\"DB EDh,0Ah\",\"DB EDh,0Bh\",\r\n  \"DB EDh,0Ch\",\"DB EDh,0Dh\",\"DB EDh,0Eh\",\"DB EDh,0Fh\",\r\n  \"DB EDh,10h\",\"DB EDh,11h\",\"DB EDh,12h\",\"DB EDh,13h\",\r\n  \"DB EDh,14h\",\"DB EDh,15h\",\"DB EDh,16h\",\"DB EDh,17h\",\r\n  \"DB EDh,18h\",\"DB EDh,19h\",\"DB EDh,1Ah\",\"DB EDh,1Bh\",\r\n  \"DB EDh,1Ch\",\"DB EDh,1Dh\",\"DB EDh,1Eh\",\"DB EDh,1Fh\",\r\n  \"DB EDh,20h\",\"DB EDh,21h\",\"DB EDh,22h\",\"DB EDh,23h\",\r\n  \"DB EDh,24h\",\"DB EDh,25h\",\"DB EDh,26h\",\"DB EDh,27h\",\r\n  \"DB EDh,28h\",\"DB EDh,29h\",\"DB EDh,2Ah\",\"DB EDh,2Bh\",\r\n  \"DB EDh,2Ch\",\"DB EDh,2Dh\",\"DB EDh,2Eh\",\"DB EDh,2Fh\",\r\n  \"DB EDh,30h\",\"DB EDh,31h\",\"DB EDh,32h\",\"DB EDh,33h\",\r\n  \"DB EDh,34h\",\"DB EDh,35h\",\"DB EDh,36h\",\"DB EDh,37h\",\r\n  \"DB EDh,38h\",\"DB EDh,39h\",\"DB EDh,3Ah\",\"DB EDh,3Bh\",\r\n  \"DB EDh,3Ch\",\"DB EDh,3Dh\",\"DB EDh,3Eh\",\"DB EDh,3Fh\",\r\n  \"IN B,(C)\",\"OUT (C),B\",\"SBC HL,BC\",\"LD (#h),BC\",\r\n  \"NEG\",\"RETN\",\"IM 0\",\"LD I,A\",\r\n  \"IN C,(C)\",\"OUT (C),C\",\"ADC HL,BC\",\"LD BC,(#h)\",\r\n  \"DB EDh,4Ch\",\"RETI\",\"DB EDh,4Eh\",\"LD R,A\",\r\n  \"IN D,(C)\",\"OUT (C),D\",\"SBC HL,DE\",\"LD (#h),DE\",\r\n  \"DB EDh,54h\",\"DB EDh,55h\",\"IM 1\",\"LD A,I\",\r\n  \"IN E,(C)\",\"OUT (C),E\",\"ADC HL,DE\",\"LD DE,(#h)\",\r\n  \"DB EDh,5Ch\",\"DB EDh,5Dh\",\"IM 2\",\"LD A,R\",\r\n  \"IN H,(C)\",\"OUT (C),H\",\"SBC HL,HL\",\"LD (#h),HL\",\r\n  \"DB EDh,64h\",\"DB EDh,65h\",\"DB EDh,66h\",\"RRD\",\r\n  \"IN L,(C)\",\"OUT (C),L\",\"ADC HL,HL\",\"LD HL,(#h)\",\r\n  \"DB EDh,6Ch\",\"DB EDh,6Dh\",\"DB EDh,6Eh\",\"RLD\",\r\n  \"IN F,(C)\",\"DB EDh,71h\",\"SBC HL,SP\",\"LD (#h),SP\",\r\n  \"DB EDh,74h\",\"DB EDh,75h\",\"DB EDh,76h\",\"DB EDh,77h\",\r\n  \"IN A,(C)\",\"OUT (C),A\",\"ADC HL,SP\",\"LD SP,(#h)\",\r\n  \"DB EDh,7Ch\",\"DB EDh,7Dh\",\"DB EDh,7Eh\",\"DB EDh,7Fh\",\r\n  \"DB EDh,80h\",\"DB EDh,81h\",\"DB EDh,82h\",\"DB EDh,83h\",\r\n  \"DB EDh,84h\",\"DB EDh,85h\",\"DB EDh,86h\",\"DB EDh,87h\",\r\n  \"DB EDh,88h\",\"DB EDh,89h\",\"DB EDh,8Ah\",\"DB EDh,8Bh\",\r\n  \"DB EDh,8Ch\",\"DB EDh,8Dh\",\"DB EDh,8Eh\",\"DB EDh,8Fh\",\r\n  \"DB EDh,90h\",\"DB EDh,91h\",\"DB EDh,92h\",\"DB EDh,93h\",\r\n  \"DB EDh,94h\",\"DB EDh,95h\",\"DB EDh,96h\",\"DB EDh,97h\",\r\n  \"DB EDh,98h\",\"DB EDh,99h\",\"DB EDh,9Ah\",\"DB EDh,9Bh\",\r\n  \"DB EDh,9Ch\",\"DB EDh,9Dh\",\"DB EDh,9Eh\",\"DB EDh,9Fh\",\r\n  \"LDI\",\"CPI\",\"INI\",\"OUTI\",\r\n  \"DB EDh,A4h\",\"DB EDh,A5h\",\"DB EDh,A6h\",\"DB EDh,A7h\",\r\n  \"LDD\",\"CPD\",\"IND\",\"OUTD\",\r\n  \"DB EDh,ACh\",\"DB EDh,ADh\",\"DB EDh,AEh\",\"DB EDh,AFh\",\r\n  \"LDIR\",\"CPIR\",\"INIR\",\"OTIR\",\r\n  \"DB EDh,B4h\",\"DB EDh,B5h\",\"DB EDh,B6h\",\"DB EDh,B7h\",\r\n  \"LDDR\",\"CPDR\",\"INDR\",\"OTDR\",\r\n  \"DB EDh,BCh\",\"DB EDh,BDh\",\"DB EDh,BEh\",\"DB EDh,BFh\",\r\n  \"DB EDh,C0h\",\"DB EDh,C1h\",\"DB EDh,C2h\",\"DB EDh,C3h\",\r\n  \"DB EDh,C4h\",\"DB EDh,C5h\",\"DB EDh,C6h\",\"DB EDh,C7h\",\r\n  \"DB EDh,C8h\",\"DB EDh,C9h\",\"DB EDh,CAh\",\"DB EDh,CBh\",\r\n  \"DB EDh,CCh\",\"DB EDh,CDh\",\"DB EDh,CEh\",\"DB EDh,CFh\",\r\n  \"DB EDh,D0h\",\"DB EDh,D1h\",\"DB EDh,D2h\",\"DB EDh,D3h\",\r\n  \"DB EDh,D4h\",\"DB EDh,D5h\",\"DB EDh,D6h\",\"DB EDh,D7h\",\r\n  \"DB EDh,D8h\",\"DB EDh,D9h\",\"DB EDh,DAh\",\"DB EDh,DBh\",\r\n  \"DB EDh,DCh\",\"DB EDh,DDh\",\"DB EDh,DEh\",\"DB EDh,DFh\",\r\n  \"DB EDh,E0h\",\"DB EDh,E1h\",\"DB EDh,E2h\",\"DB EDh,E3h\",\r\n  \"DB EDh,E4h\",\"DB EDh,E5h\",\"DB EDh,E6h\",\"DB EDh,E7h\",\r\n  \"DB EDh,E8h\",\"DB EDh,E9h\",\"DB EDh,EAh\",\"DB EDh,EBh\",\r\n  \"DB EDh,ECh\",\"DB EDh,EDh\",\"DB EDh,EEh\",\"DB EDh,EFh\",\r\n  \"DB EDh,F0h\",\"DB EDh,F1h\",\"DB EDh,F2h\",\"DB EDh,F3h\",\r\n  \"DB EDh,F4h\",\"DB EDh,F5h\",\"DB EDh,F6h\",\"DB EDh,F7h\",\r\n  \"DB EDh,F8h\",\"DB EDh,F9h\",\"DB EDh,FAh\",\"DB EDh,FBh\",\r\n  \"DB EDh,FCh\",\"DB EDh,FDh\",\"DB EDh,FEh\",\"DB EDh,FFh\"\r\n};\r\n\r\nstatic char *MnemonicsXX[256] =\r\n{\r\n  \"NOP\",\"LD BC,#h\",\"LD (BC),A\",\"INC BC\",\"INC B\",\"DEC B\",\"LD B,*h\",\"RLCA\",\r\n  \"EX AF,AF'\",\"ADD I%,BC\",\"LD A,(BC)\",\"DEC BC\",\"INC C\",\"DEC C\",\"LD C,*h\",\"RRCA\",\r\n  \"DJNZ @h\",\"LD DE,#h\",\"LD (DE),A\",\"INC DE\",\"INC D\",\"DEC D\",\"LD D,*h\",\"RLA\",\r\n  \"JR @h\",\"ADD I%,DE\",\"LD A,(DE)\",\"DEC DE\",\"INC E\",\"DEC E\",\"LD E,*h\",\"RRA\",\r\n  \"JR NZ,@h\",\"LD I%,#h\",\"LD (#h),I%\",\"INC I%\",\"INC I%h\",\"DEC I%h\",\"LD I%h,*h\",\"DAA\",\r\n  \"JR Z,@h\",\"ADD I%,I%\",\"LD I%,(#h)\",\"DEC I%\",\"INC I%l\",\"DEC I%l\",\"LD I%l,*h\",\"CPL\",\r\n  \"JR NC,@h\",\"LD SP,#h\",\"LD (#h),A\",\"INC SP\",\"INC (I%+^h)\",\"DEC (I%+^h)\",\"LD (I%+^h),*h\",\"SCF\",\r\n  \"JR C,@h\",\"ADD I%,SP\",\"LD A,(#h)\",\"DEC SP\",\"INC A\",\"DEC A\",\"LD A,*h\",\"CCF\",\r\n  \"LD B,B\",\"LD B,C\",\"LD B,D\",\"LD B,E\",\"LD B,I%h\",\"LD B,I%l\",\"LD B,(I%+^h)\",\"LD B,A\",\r\n  \"LD C,B\",\"LD C,C\",\"LD C,D\",\"LD C,E\",\"LD C,I%h\",\"LD C,I%l\",\"LD C,(I%+^h)\",\"LD C,A\",\r\n  \"LD D,B\",\"LD D,C\",\"LD D,D\",\"LD D,E\",\"LD D,I%h\",\"LD D,I%l\",\"LD D,(I%+^h)\",\"LD D,A\",\r\n  \"LD E,B\",\"LD E,C\",\"LD E,D\",\"LD E,E\",\"LD E,I%h\",\"LD E,I%l\",\"LD E,(I%+^h)\",\"LD E,A\",\r\n  \"LD I%h,B\",\"LD I%h,C\",\"LD I%h,D\",\"LD I%h,E\",\"LD I%h,I%h\",\"LD I%h,I%l\",\"LD H,(I%+^h)\",\"LD I%h,A\",\r\n  \"LD I%l,B\",\"LD I%l,C\",\"LD I%l,D\",\"LD I%l,E\",\"LD I%l,I%h\",\"LD I%l,I%l\",\"LD L,(I%+^h)\",\"LD I%l,A\",\r\n  \"LD (I%+^h),B\",\"LD (I%+^h),C\",\"LD (I%+^h),D\",\"LD (I%+^h),E\",\"LD (I%+^h),H\",\"LD (I%+^h),L\",\"HALT\",\"LD (I%+^h),A\",\r\n  \"LD A,B\",\"LD A,C\",\"LD A,D\",\"LD A,E\",\"LD A,I%h\",\"LD A,I%l\",\"LD A,(I%+^h)\",\"LD A,A\",\r\n  \"ADD B\",\"ADD C\",\"ADD D\",\"ADD E\",\"ADD I%h\",\"ADD I%l\",\"ADD (I%+^h)\",\"ADD A\",\r\n  \"ADC B\",\"ADC C\",\"ADC D\",\"ADC E\",\"ADC I%h\",\"ADC I%l\",\"ADC (I%+^h)\",\"ADC,A\",\r\n  \"SUB B\",\"SUB C\",\"SUB D\",\"SUB E\",\"SUB I%h\",\"SUB I%l\",\"SUB (I%+^h)\",\"SUB A\",\r\n  \"SBC B\",\"SBC C\",\"SBC D\",\"SBC E\",\"SBC I%h\",\"SBC I%l\",\"SBC (I%+^h)\",\"SBC A\",\r\n  \"AND B\",\"AND C\",\"AND D\",\"AND E\",\"AND I%h\",\"AND I%l\",\"AND (I%+^h)\",\"AND A\",\r\n  \"XOR B\",\"XOR C\",\"XOR D\",\"XOR E\",\"XOR I%h\",\"XOR I%l\",\"XOR (I%+^h)\",\"XOR A\",\r\n  \"OR B\",\"OR C\",\"OR D\",\"OR E\",\"OR I%h\",\"OR I%l\",\"OR (I%+^h)\",\"OR A\",\r\n  \"CP B\",\"CP C\",\"CP D\",\"CP E\",\"CP I%h\",\"CP I%l\",\"CP (I%+^h)\",\"CP A\",\r\n  \"RET NZ\",\"POP BC\",\"JP NZ,#h\",\"JP #h\",\"CALL NZ,#h\",\"PUSH BC\",\"ADD *h\",\"RST 00h\",\r\n  \"RET Z\",\"RET\",\"JP Z,#h\",\"PFX_CB\",\"CALL Z,#h\",\"CALL #h\",\"ADC *h\",\"RST 08h\",\r\n  \"RET NC\",\"POP DE\",\"JP NC,#h\",\"OUTA (*h)\",\"CALL NC,#h\",\"PUSH DE\",\"SUB *h\",\"RST 10h\",\r\n  \"RET C\",\"EXX\",\"JP C,#h\",\"INA (*h)\",\"CALL C,#h\",\"PFX_DD\",\"SBC *h\",\"RST 18h\",\r\n  \"RET PO\",\"POP I%\",\"JP PO,#h\",\"EX I%,(SP)\",\"CALL PO,#h\",\"PUSH I%\",\"AND *h\",\"RST 20h\",\r\n  \"RET PE\",\"LD PC,I%\",\"JP PE,#h\",\"EX DE,I%\",\"CALL PE,#h\",\"PFX_ED\",\"XOR *h\",\"RST 28h\",\r\n  \"RET P\",\"POP AF\",\"JP P,#h\",\"DI\",\"CALL P,#h\",\"PUSH AF\",\"OR *h\",\"RST 30h\",\r\n  \"RET M\",\"LD SP,I%\",\"JP M,#h\",\"EI\",\"CALL M,#h\",\"PFX_FD\",\"CP *h\",\"RST 38h\"\r\n};\r\n\r\nstatic char *MnemonicsXCB[256] =\r\n{\r\n  \"RLC B\",\"RLC C\",\"RLC D\",\"RLC E\",\"RLC H\",\"RLC L\",\"RLC (I%@h)\",\"RLC A\",\r\n  \"RRC B\",\"RRC C\",\"RRC D\",\"RRC E\",\"RRC H\",\"RRC L\",\"RRC (I%@h)\",\"RRC A\",\r\n  \"RL B\",\"RL C\",\"RL D\",\"RL E\",\"RL H\",\"RL L\",\"RL (I%@h)\",\"RL A\",\r\n  \"RR B\",\"RR C\",\"RR D\",\"RR E\",\"RR H\",\"RR L\",\"RR (I%@h)\",\"RR A\",\r\n  \"SLA B\",\"SLA C\",\"SLA D\",\"SLA E\",\"SLA H\",\"SLA L\",\"SLA (I%@h)\",\"SLA A\",\r\n  \"SRA B\",\"SRA C\",\"SRA D\",\"SRA E\",\"SRA H\",\"SRA L\",\"SRA (I%@h)\",\"SRA A\",\r\n  \"SLL B\",\"SLL C\",\"SLL D\",\"SLL E\",\"SLL H\",\"SLL L\",\"SLL (I%@h)\",\"SLL A\",\r\n  \"SRL B\",\"SRL C\",\"SRL D\",\"SRL E\",\"SRL H\",\"SRL L\",\"SRL (I%@h)\",\"SRL A\",\r\n  \"BIT 0,B\",\"BIT 0,C\",\"BIT 0,D\",\"BIT 0,E\",\"BIT 0,H\",\"BIT 0,L\",\"BIT 0,(I%@h)\",\"BIT 0,A\",\r\n  \"BIT 1,B\",\"BIT 1,C\",\"BIT 1,D\",\"BIT 1,E\",\"BIT 1,H\",\"BIT 1,L\",\"BIT 1,(I%@h)\",\"BIT 1,A\",\r\n  \"BIT 2,B\",\"BIT 2,C\",\"BIT 2,D\",\"BIT 2,E\",\"BIT 2,H\",\"BIT 2,L\",\"BIT 2,(I%@h)\",\"BIT 2,A\",\r\n  \"BIT 3,B\",\"BIT 3,C\",\"BIT 3,D\",\"BIT 3,E\",\"BIT 3,H\",\"BIT 3,L\",\"BIT 3,(I%@h)\",\"BIT 3,A\",\r\n  \"BIT 4,B\",\"BIT 4,C\",\"BIT 4,D\",\"BIT 4,E\",\"BIT 4,H\",\"BIT 4,L\",\"BIT 4,(I%@h)\",\"BIT 4,A\",\r\n  \"BIT 5,B\",\"BIT 5,C\",\"BIT 5,D\",\"BIT 5,E\",\"BIT 5,H\",\"BIT 5,L\",\"BIT 5,(I%@h)\",\"BIT 5,A\",\r\n  \"BIT 6,B\",\"BIT 6,C\",\"BIT 6,D\",\"BIT 6,E\",\"BIT 6,H\",\"BIT 6,L\",\"BIT 6,(I%@h)\",\"BIT 6,A\",\r\n  \"BIT 7,B\",\"BIT 7,C\",\"BIT 7,D\",\"BIT 7,E\",\"BIT 7,H\",\"BIT 7,L\",\"BIT 7,(I%@h)\",\"BIT 7,A\",\r\n  \"RES 0,B\",\"RES 0,C\",\"RES 0,D\",\"RES 0,E\",\"RES 0,H\",\"RES 0,L\",\"RES 0,(I%@h)\",\"RES 0,A\",\r\n  \"RES 1,B\",\"RES 1,C\",\"RES 1,D\",\"RES 1,E\",\"RES 1,H\",\"RES 1,L\",\"RES 1,(I%@h)\",\"RES 1,A\",\r\n  \"RES 2,B\",\"RES 2,C\",\"RES 2,D\",\"RES 2,E\",\"RES 2,H\",\"RES 2,L\",\"RES 2,(I%@h)\",\"RES 2,A\",\r\n  \"RES 3,B\",\"RES 3,C\",\"RES 3,D\",\"RES 3,E\",\"RES 3,H\",\"RES 3,L\",\"RES 3,(I%@h)\",\"RES 3,A\",\r\n  \"RES 4,B\",\"RES 4,C\",\"RES 4,D\",\"RES 4,E\",\"RES 4,H\",\"RES 4,L\",\"RES 4,(I%@h)\",\"RES 4,A\",\r\n  \"RES 5,B\",\"RES 5,C\",\"RES 5,D\",\"RES 5,E\",\"RES 5,H\",\"RES 5,L\",\"RES 5,(I%@h)\",\"RES 5,A\",\r\n  \"RES 6,B\",\"RES 6,C\",\"RES 6,D\",\"RES 6,E\",\"RES 6,H\",\"RES 6,L\",\"RES 6,(I%@h)\",\"RES 6,A\",\r\n  \"RES 7,B\",\"RES 7,C\",\"RES 7,D\",\"RES 7,E\",\"RES 7,H\",\"RES 7,L\",\"RES 7,(I%@h)\",\"RES 7,A\",\r\n  \"SET 0,B\",\"SET 0,C\",\"SET 0,D\",\"SET 0,E\",\"SET 0,H\",\"SET 0,L\",\"SET 0,(I%@h)\",\"SET 0,A\",\r\n  \"SET 1,B\",\"SET 1,C\",\"SET 1,D\",\"SET 1,E\",\"SET 1,H\",\"SET 1,L\",\"SET 1,(I%@h)\",\"SET 1,A\",\r\n  \"SET 2,B\",\"SET 2,C\",\"SET 2,D\",\"SET 2,E\",\"SET 2,H\",\"SET 2,L\",\"SET 2,(I%@h)\",\"SET 2,A\",\r\n  \"SET 3,B\",\"SET 3,C\",\"SET 3,D\",\"SET 3,E\",\"SET 3,H\",\"SET 3,L\",\"SET 3,(I%@h)\",\"SET 3,A\",\r\n  \"SET 4,B\",\"SET 4,C\",\"SET 4,D\",\"SET 4,E\",\"SET 4,H\",\"SET 4,L\",\"SET 4,(I%@h)\",\"SET 4,A\",\r\n  \"SET 5,B\",\"SET 5,C\",\"SET 5,D\",\"SET 5,E\",\"SET 5,H\",\"SET 5,L\",\"SET 5,(I%@h)\",\"SET 5,A\",\r\n  \"SET 6,B\",\"SET 6,C\",\"SET 6,D\",\"SET 6,E\",\"SET 6,H\",\"SET 6,L\",\"SET 6,(I%@h)\",\"SET 6,A\",\r\n  \"SET 7,B\",\"SET 7,C\",\"SET 7,D\",\"SET 7,E\",\"SET 7,H\",\"SET 7,L\",\"SET 7,(I%@h)\",\"SET 7,A\"\r\n};\r\n\r\n/** DAsm() ****************************************************/\r\n/** This function will disassemble a single command and      **/\r\n/** return the number of bytes disassembled.                 **/\r\n/**************************************************************/\r\nint     DAsm(char *S,byte *A)\r\n{\r\n  char R[128],H[10],C,*T,*P;\r\n  byte *B,J,Offset;\r\n\r\n  B=A;C='\\0';J=0;\r\n\r\n  switch(*B)\r\n  {\r\n    case 0xCB: B++;T=MnemonicsCB[*B++];break;\r\n    case 0xED: B++;T=MnemonicsED[*B++];break;\r\n    case 0xDD: B++;C='X';\r\n               if(*B!=0xCB) T=MnemonicsXX[*B++];\r\n               else { B++;Offset=*B++;J=1;T=MnemonicsXCB[*B++]; }\r\n               break;\r\n    case 0xFD: B++;C='Y';\r\n               if(*B!=0xCB) T=MnemonicsXX[*B++];\r\n               else { B++;Offset=*B++;J=1;T=MnemonicsXCB[*B++]; }\r\n               break;\r\n    default:   T=Mnemonics[*B++];\r\n  }\r\n\r\n  if (P=strchr(T,'^'))\r\n  {\r\n    strncpy(R,T,P-T);R[P-T]='\\0';\r\n    sprintf(H,\"%02X\",*B++);\r\n    strcat(R,H);strcat(R,P+1);\r\n  }\r\n  else strcpy(R,T);\r\n  if (P=strchr(R,'%')) *P=C;\r\n\r\n  if (P=strchr(R,'*'))\r\n  {\r\n    strncpy(S,R,P-R);S[P-R]='\\0';\r\n    sprintf(H,\"%02X\",*B++);\r\n    strcat(S,H);strcat(S,P+1);\r\n  }\r\n  else\r\n    if (P=strchr(R,'@'))\r\n    {\r\n      strncpy(S,R,P-R);S[P-R]='\\0';\r\n      if(!J) Offset=*B++;\r\n      strcat(S,Offset&0x80? \"-\":\"+\");\r\n      J=Offset&0x80? 256-Offset:Offset;\r\n      sprintf(H,\"%02X\",J);\r\n      strcat(S,H);strcat(S,P+1);\r\n    }\r\n    else\r\n      if (P=strchr(R,'#'))\r\n      {\r\n        strncpy(S,R,P-R);S[P-R]='\\0';\r\n        sprintf(H,\"%04X\",B[0]+256*B[1]);\r\n        strcat(S,H);strcat(S,P+1);\r\n        B+=2;\r\n      }\r\n      else strcpy(S,R);\r\n\r\n  return (B - A);\r\n}\r\n\r\n/** main() ****************************************************/\r\n/** This is the main function from which execution starts.   **/\r\n/**************************************************************/\r\nint     main(int argc, char **argv)\r\n{\r\n  FILE  *F;\r\n  int   N, I, J;\r\n  byte  Buf [32];\r\n  char  S [128];\r\n\r\n  Counter = 0L;\r\n  PrintHex = 0;\r\n\r\n  for (N=1; (N < argc) && (*argv[N] == '-'); N++)\r\n    switch (argv[N][1])\r\n      {\r\n      case 'o': sscanf (argv[N], \"-o%lx\", &Counter);\r\n                Counter &= 0xFFFFFFFFL;\r\n                break;\r\n      default:\r\n        for (J=1; argv[N][J]; J++)\r\n          switch (argv[N][J])\r\n            {\r\n            case 'h': PrintHex = 1; break;\r\n            default:\r\n              fprintf(stderr,\"%s: Unknown option -%c\\n\", argv[0], argv[N][J]);\r\n            }\r\n      }\r\n\r\n  if (N==argc)\r\n     {\r\n     fprintf(stderr,\"DASMZ80 Z80 Disassembler v.2.0 by Marat Fayzullin\\n\");\r\n     #ifdef ZLIB\r\n       fprintf(stderr,\"  This program will transparently uncompress singular\\n\");\r\n       fprintf(stderr,\"  GZIPped and PKZIPped files.\\n\");\r\n     #endif\r\n     fprintf(stderr,\"Usage: %s [-h] [-oOrigin] file\\n\", argv[0]);\r\n     fprintf(stderr,\"  -h - Print hexadecimal values\\n\");\r\n     fprintf(stderr,\"  -o - Count addresses from a given origin (hex)\\n\");\r\n     return (1);\r\n     }\r\n\r\n  if (!(F=fopen(argv[N],\"rb\")))\r\n     {\r\n     printf(\"\\n%s: Can't open file %s\\n\", argv[0], argv[N]);\r\n     return (1);\r\n     }\r\n\r\n  for (N = 0; N += fread(Buf + N, 1, 16 - N, F); )\r\n     {\r\n     memset(Buf + N, 0, 32 - N);\r\n     I = DAsm(S, Buf);\r\n     printf(\"%08lX:\", Counter);\r\n     if (PrintHex)\r\n        {\r\n        for (J = 0; J < I; J++)\r\n           printf(\" %02X\", Buf[J]);\r\n        if (I < 3)\r\n           printf(\"\\t\");\r\n        }\r\n    printf(\"\\t%s\\n\", S);\r\n    Counter += I;\r\n    N -= I;\r\n    if (N > 0)\r\n       {\r\n       for (J = 0; J < N; J++)\r\n           Buf[J] = Buf[16 - N + J];\r\n       }\r\n    else\r\n       {\r\n       if (N < 0)\r\n          N = 0;\r\n       }\r\n  }\r\n\r\n  fclose(F);\r\n  return (0);\r\n}\r\n"
  },
  {
    "path": "meka/srcs/z80marat/todo",
    "content": "\r\n Codes.h                                Ok      !! Int stuffs, grep UPGRADE\r\n CodesCB.h                              Ok\r\n CodesED.h                              Ok      Outd stuff\r\n CodesXCB.h                             Ok\r\n CodesXX.h                              Ok      !! Int stuffs, grep UPGRADE\r\n Debug.c                                Ok\r\n Tables.h                               Ok\r\n Z80.c                                  ..\r\n Z80.h                                  Ok\r\n\r\n verify I flags -> has IFF2 changed ??\r\n then need to update savestate format\r\n\r\n"
  },
  {
    "path": "meka/tech.txt",
    "content": "-----------------------------------------------------------------------------\r\n MEKA - Technical Stuff\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n SUMMARY\r\n-----------------------------------------------------------------------------\r\n 1. SMS Joypads Pinouts\r\n 2. SMS Joypads (DB-9) to Parallel port adapter (type 1)\r\n 3. SMS Joypads (DB-9) to Parallel port adapter (type 2)\r\n 4. SMS Joypads (DB-9) to Parallel port adapter (GNU/Linux)\r\n 5. SMS 3-D Glasses to Serial/COM port adapter\r\n 6. More ?\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 1. SMS Joypads Pinouts\r\n    Copied from Linux Joystick Driver documentation\r\n    http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/\r\n-----------------------------------------------------------------------------\r\n\r\n Pinouts are shown looking into a controller plug.\r\n\r\n        +-----------> Power (unused on most controllers)\r\n        | +---------> Right\r\n        | | +-------> Left\r\n        | | | +-----> Down\r\n        | | | | +---> Up\r\n        | | | | |\r\n      _____________\r\n    5 \\ o o o o o / 1       DB-9 connector\r\n       \\ o o x o /\r\n      9 `~~~~~~~' 6\r\n         | |   |\r\n         | |   +----> Button 1\r\n         | +--------> Ground\r\n         +----------> Button 2\r\n\r\n DB-9 joypads (and more generally, inputs peripherals) were of common usage\r\n on Sega Master System, Megadrive (Genesis), several older consoles, Amiga\r\n and Atari computers, etc.\r\n Although the DB-9 connector is shared by many controllers, not all uses\r\n the same pinouts as the Sega Master System controller. Old joystick might\r\n also have only one button connected.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 2. SMS Joypads (DB-9) to Parallel port adapter (type 1)\r\n    Comments by Mike Gordon.\r\n-----------------------------------------------------------------------------\r\n This adapter schematic is natively supported by the MS-DOS version of MEKA\r\n through the Allegro library. The adapter is also usable under Windows using\r\n the DirectPad Pro driver.\r\n If you do not plan to use the MS-DOS version, building the second type of\r\n adapter is recommended.\r\n-----------------------------------------------------------------------------\r\n\r\n Note\r\n ----\r\n This is a copy based on the schematic available on the now defunct\r\n DirectPad Pro site. A mirror is available at:\r\n    http://www.arcadecontrols.com/Mirrors/www.ziplabel.com/dpadpro/\r\n I'm not sure who is the original author of this schematic, but it is very\r\n simple and the common nature of the adapter make it somewhat public domain\r\n knowledge.\r\n\r\n D-Connector Pinouts\r\n -------------------\r\n\r\n DB-9 SMS Joypad plug:\r\n     -------------\r\n     \\ 5 4 3 2 1 /\r\n      \\ 9 8 7 6 /\r\n       ---------\r\n\r\n DB-25 Parallel connector on PC (female):\r\n     ------------------------------------------\r\n     \\ 13 12 11 10  9  8  7  6  5  4  3  2  1 /\r\n      \\  25 24 23 22 21 20 19 18 17 16 15 14 /\r\n       --------------------------------------\r\n\r\n\r\n Legend\r\n ------\r\n Resistor:  --vvvvv--\r\n\r\n Circuit\r\n -------\r\n\r\n PARALLEL PORT (DB-25)                          SMS PAD (DB-9)\r\n\r\n     DB25:1  <----------------------------------->  DB-9:1      (Up)\r\n\r\n     DB25:2  <------vvvvvvvvv---+---------------->  DB-9:6      (Button 1)\r\n                       10K      |\r\n     DB25:11 <------------------+\r\n\r\n     DB25:3  <------vvvvvvvvv---+---------------->  DB-9:9      (Button 2)\r\n                       10K      |\r\n     DB25:12 <------------------+\r\n\r\n     DB25:14 <----------------------------------->  DB-9:2      (Down)\r\n     DB25:16 <----------------------------------->  DB-9:3      (Left)\r\n     DB25:17 <----------------------------------->  DB-9:4      (Right)\r\n\r\n     DB25:18 <------------------+---------------->  DB-9:8      (Ground)\r\n                                |\r\n     DB25:19 <------------------+\r\n\r\n* You need a 25-pin male D-plug (DB-25) for the parallel port connection (to\r\n  fit the female parallel port socket), and a 9-pin male D-plug (DB-9) for\r\n  the SMS joypad connection (to fit the female joypad plug). The pin numbers\r\n  should be marked on the plug itself.\r\n\r\n* The type of resistor used (metal film, carbon etc.) is not important. The\r\n  resistors can be soldered directly to the DB-25 connector, i.e. connect one\r\n  resistor between pin 3 and pin 12, another between pin 2 and pin 11. (And\r\n  a wire link, between pins 18 and 19.)\r\n\r\n  The resistor value (10K) is indicated by coloured bands on the body of the\r\n  resistor, as follows, from left to right:\r\n\r\n   Either: Brown Black Orange       (gap)  Brown or Gold\r\n       or: Brown Black Black Red    (gap)  Brown or Gold\r\n\r\n* Use shielded cable, and use the outer shield of the cable for the Ground\r\n  connection. Try and keep the cable as short as possible.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 3. SMS Joypads (DB-9) to Parallel port adapter (type 2)\r\n    Comments by Gary Pierce (Youltar).\r\n-----------------------------------------------------------------------------\r\n Please refer to SmsCartPad homepage for more detailed instruction:\r\n    http://www.smspower.org/smscartpad/\r\n-----------------------------------------------------------------------------\r\n\r\n Circuit\r\n -------\r\n\r\n PARALLEL PORT (DB-25)                          SMS PAD (DB-9)\r\n\r\n     DB25:2  <----------------------------------->  DB-9:1      (Up)\r\n     DB25:3  <----------------------------------->  DB-9:2      (Down)\r\n     DB25:4  <----------------------------------->  DB-9:3      (Left)\r\n     DB25:5  <----------------------------------->  DB-9:4      (Right)\r\n     DB25:6  <----------------------------------->  DB-9:6      (Button 1)\r\n     DB25:1  <----------------------------------->  DB-9:5      (Power)\r\n     DB25:18 <----------------------------------->  DB-9:8      (Ground)\r\n     DB25:7  <----------------------------------->  DB-9:9      (Button 2)\r\n     DB25:14 <----------------------------------->  DB-9:7      (?)\r\n\r\n After some research and digging around this is the diagram I have found to\r\n work best for me. As you can see above, there is no need for any diodes or\r\n resistors. This is a straight-through connection. All one needs to do is\r\n connect the proper pins from the DB 9 to the DB 25 connector.\r\n\r\n I used an old IDE ribbon cable and some crimp on connectors. That's it.\r\n (I used crimp connectors because my soldering skills are somewhat lacking)\r\n\r\n Select the \"Linux-DB9\" in the driver configuration window.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 4. SMS Joypads (DB-9) to Parallel port adapter (GNU/Linux)\r\n-----------------------------------------------------------------------------\r\n GNU/Linux kernels starting version 2.2 supports a wide range of joysticks,\r\n based on the \"Linux Joystick Driver\" project:\r\n    http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/\r\n Please refer to appropriate documentation (joystick-parport.txt) for\r\n detailed instruction about how to build different kind of adapters.\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 5. SMS 3-D Glasses to Serial/COM port adapter\r\n    Unknown original author. Comments by Frank and Mike Gordon.\r\n-----------------------------------------------------------------------------\r\n This adapter schematic is natively supported by the MS-DOS and Windows\r\n versions of MEKA. As of yet, UN*X versions does not support this feature.\r\n-----------------------------------------------------------------------------\r\n Please refer to SmsCartPad homepage for more detailed instruction:\r\n    http://www.smspower.org/smscartpad/3d_glasses.shtml\r\n-----------------------------------------------------------------------------\r\n\r\n Note\r\n ----\r\n About the MS-DOS version of MEKA: the SMS 3-D Glasses adapter should work\r\n even under in a Windows 95/98 command prompt, but I have not done extensive\r\n testing to confirm. Please e-mail me any problem you may have.\r\n\r\n The Nintendo Famicom 3-D Glasses are said to be compatible with the\r\n SMS 3-D Glasses, meaning that they should work with this adapter as well.\r\n I could not confirm it myself.\r\n\r\n Legend\r\n ------\r\n Diode:      --|>|--\r\n\r\n Resistor:  --vvvvv--\r\n\r\n                |\r\n Capacitor:    ---\r\n               ---\r\n                |\r\n\r\n Circuit\r\n -------\r\n\r\n       RS-232\r\n     DB25 / DB9\r\n                                                   10K\r\nRTS   4      7  Switching signal +/- 10V  --------vvvvv--+\r\n                                                         |\r\n                                                         |\r\nGND   7      5  Ground ----+-------------+--+---------+--|----+\r\n                           |             |  |         |  |    |\r\n                           |             |  +-|>|--+  |  |    |\r\n                           +--|>|--+    ---        |  |  |    |  Transistor\r\n                                   |    ---  22 uF |  |  |    |   2N2222\r\n                                   |     |         |  |  |  +-+---------+\r\n                                   |     |         |  |  |  | Emitter   |\r\n                                   |     |         |  |  |  |           |\r\nDTR  20      4  Vdd +10V --|>|-----+-----+         +--|--+--+ Base      |\r\n                                         |            |     |           |\r\n                              +--+--+--+-+-vvvvv---+--|-----+ Collector |\r\n                              |  |  |  |    10K    |  |     |           |\r\n                              |  |  |  |           |  |     +-----------+\r\n                      +-------+--+--+--+-----------+--+--+\r\n                      |       1  9  13 14          5  7  |\r\n                      |                                  |\r\n                      |   RCA CD 4030 Quad XOR gate      |\r\n                      |                                  |\r\n                      | 2 11  12       3  6  8   10   4  |\r\n                      +-+--+---+-------+--+--+----+---+--+\r\n                        |  |   |       |  |  |    |   |\r\n                        +--+   |       +--+--+    |   +--- Outside of jack\r\n                           |   |             |    |\r\n                           |   +-vvvvv-+     |    +------- Middle of jack\r\n                           |      22K  |     |\r\n                           |           |     +------------ Centre of jack\r\n                           +-vvvvv-----+     |\r\n                              22K      |     |\r\n                                      ---    |\r\n                              .01 uF  ---    |\r\n                                       |     |\r\n                                       +-----+\r\n\r\n[FRANK]\r\n\r\nThis is my best attempt at a rendition of the circuit which connects my\r\nSEGA glasses to my AT. I didn't design the circuit -- I'm a software\r\nrather than hardware person. In fact I barely understand it -- as far as\r\nI can tell, the .01uF capacitor & the 22K resistors act as a delay. The\r\noutputs of the XOR gates feed back into their own inputs, thus producing\r\nan oscillator. The \"jack\" mentioned in the diagram is the mini-jack\r\nwhich is connected as standard to the glasses. \"Centre\", \"middle\", and\r\n\"outside\" relate to the external connections, looking at the thing\r\nend-on.\r\n\r\nCaveat emptor... to paraphrase the standard software licence agreement:\r\nIt's as good as I can get it. If it doesn't work or blows up your\r\ncomputer or your glasses and blinds you for life, I'll give you back all\r\nthe money you paid me.\r\n\r\n[MIKE GORDON]\r\n\r\nAs far as I can see, the oscillator circuit is used to provide an AC supply\r\nto power the glasses. The switching signal (+ or - 10 volts) applied to the\r\nbase of the transistor produces a high or low output on the collector, which\r\npresumably is used to switch between left and right frames.\r\n\r\nWhen building the adapter:\r\n\r\n* Use a CMOS series 4030B (or 4070B, which is functionally equivalent). Do\r\n  not use a 74HC series chip.\r\n\r\n  Chip pin numbering:\r\n\r\n      7  6  5  4  3  2  1\r\n     +-------------------+\r\n     |                   |\r\n     |   4070B           < - notch\r\n     |                   |\r\n     +-------------------+\r\n      8  9 10 11 12 13 14\r\n\r\n\r\n* Use 1N4148 (or equivalent) signal diodes. The positive end is marked by a\r\n  black band around the component.\r\n\r\n      Negative  -  --|>|--  +  Positive\r\n\r\n\r\n* The resistors should ideally be metal film types (blue-coloured body).\r\n  The value is indicated by coloured bands, as follows, from left to right:\r\n\r\n     22K - Red Red Orange           (gap)  Brown or Gold\r\n      OR - Red Red Black Red        (gap)  Brown or Gold\r\n\r\n     10K - Brown Black Orange       (gap)  Brown or Gold\r\n      OR - Brown Black Black Red    (gap)  Brown or Gold\r\n\r\n\r\n* The .01 uF (10 nF) capacitor should be a ceramic disc type, while the 22uF\r\n  capacitor should be an electrolytic type.\r\n\r\n\r\n* For the 2N2222A transistor (looking at it from below, with the pins towards\r\n  you) :\r\n\r\n\r\n                     o - Base\r\n\r\n\r\n     Emitter -   o       o   - Collector\r\n\r\n\r\n  Metal tab - /_/\r\n\r\n\r\n* The serial port is a 9-pin D-type male connector, so you need a 9-pin\r\n  female D plug for the adapter. Looking into the serial port itself, this\r\n  is the pin configuration:\r\n\r\n                 1 2 3 4 5\r\n               -------------\r\n               \\ o o o o o /\r\n                \\ o o o o /\r\n                 ---------\r\n                  6 7 8 9\r\n\r\n\r\n* Finally, the 3-D glasses jack is a 3.5mm stereo phone socket, i.e. the\r\n  Walkman type.\r\n\r\nGood luck building the adapter, and enjoy!\r\n-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------\r\n 6. More ?\r\n-----------------------------------------------------------------------------\r\n http://www.smspower.org/Development !\r\n-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "meka/tools/dist_bin_osx.sh",
    "content": "#!/bin/bash\n\nMEKA_APPBIN=Dist/Meka.app/Contents/MacOS/meka\nRESOURCE_DIR=./Dist/Meka.app/Contents/Resources\nBIN_DIR=./Dist/Meka.app/Contents/MacOS\nPLUGINS_DIR=./Dist/Meka.app/Contents/PlugIns\nDIR=`dirname $0`\n\n# Ignoring meka.dat while the 0.8x branch is using the Data/ folder (which we should aim to fix)\nDATA_FILES=\"meka.nam meka.thm meka.pat meka.blt meka.inp meka.msg\"\nDOC_FILES=\"meka.txt compat.txt multi.txt changes.txt debugger.txt\"\n#CONF_FILES=\"meka.cfg\"\nCONF_FILES=\"\"\n\nfunction copy_to_resources {\n\tfor file in $1; do\n\t\tcp $file $2\n\tdone\n}\n\n# Directories\n# Since these most likely are supposed to be written to, they should be \n# created in ~/Library/Application Support/MEKA or some place like that. \nDIRS=\"Screenshots Saves Music Debug\"\n\ncd $DIR/..\n\n# Create Meka.app from template.\nrm -fR Dist/Meka.app\nmkdir -p Dist\ncp -r tools/dist_osx/Meka.app_template Dist/Meka.app\nmkdir -p $BIN_DIR\nmkdir -p $RESOURCE_DIR\nmkdir -p $PLUGINS_DIR\ncp meka $BIN_DIR\n\n#copy resources files\n\ncopy_to_resources \"$DATA_FILES\" $RESOURCE_DIR\ncopy_to_resources \"$DOC_FILES\" $RESOURCE_DIR\ncopy_to_resources \"$CONF_FILES\" $RESOURCE_DIR\ncp -r Data $RESOURCE_DIR\ncp -r Themes $RESOURCE_DIR\n\n\n# copy libraries from /usr/local/lib to $BIN_DIR\n\nLOCAL_LIBS=$(otool -L $MEKA_APPBIN | awk '/\\/usr\\/local\\// { print $1}')\n\n\nfor local_lib in $LOCAL_LIBS\ndo\n\tcp -r $local_lib $BIN_DIR\n\tfile_name=$(basename $local_lib)\n\n\tchmod +w $BIN_DIR/$file_name\n\n\tinstall_name_tool -id @executable_path/$file_name $BIN_DIR/$file_name\n\tinstall_name_tool -change $local_lib @executable_path/$file_name $MEKA_APPBIN\n\n\totool -L $BIN_DIR/$file_name\ndone\n\n# special case, fix path to libpng inside libfreetype.\n# TODO: Make a generic function that can do this for any lib.\ninstall_name_tool -change /usr/local/lib/libpng16.16.dylib @loader_path/libpng16.16.dylib $BIN_DIR/libfreetype.6.dylib\n\notool -L $MEKA_APPBIN\n"
  },
  {
    "path": "meka/tools/dist_bin_win32.bat",
    "content": "@echo Creating Dist/mekaw.zip\r\ncd ..\r\nmkdir Dist\r\n\r\n@REM @echo Compressing\r\n@REM tools\\dist_win\\upx.exe -9 mekaw.exe\r\n\r\n@echo Packaging\r\ntools\\dist_win\\zip.exe -X9 Dist\\mekaw.zip meka.blt meka.dat mekaw.exe meka.inp meka.msg meka.nam meka.pat meka.thm\r\n@REM tools\\dist_win\\zip.exe -X9 Dist\\mekaw.zip mekaw.cfg\r\ntools\\dist_win\\zip.exe -X9 Dist\\mekaw.zip icons.zip setup.bat\r\ntools\\dist_win\\zip.exe -X9 Dist\\mekaw.zip meka.txt changes.txt compat.txt debugger.txt multi.txt tech.txt\r\ntools\\dist_win\\zip.exe -X9 Dist\\mekaw.zip -r Data\\*.*\r\ntools\\dist_win\\zip.exe -X9 Dist\\mekaw.zip -r Themes\\*.png Themes\\README.txt\r\n@echo Done!\r\n@echo -- Check MEKA.BLT ! --\r\n@echo -- Check MEKA.INP ! Joypad auto, on --\r\npause\r\n"
  },
  {
    "path": "meka/tools/dist_osx/Meka.app_template/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleExecutable</key>\n\t<string>meka</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>org.smspower.meka</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 1998-2015 Omar Cornut and contributors</string>\n\t<key>CFBundleName</key>\n\t<string>Meka</string>\n\n\t<key>CFBundleVersion</key>\n\t<string>0.80.0</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>0.80-alpha</string>\n</dict>\n</plist>\n"
  }
]