text: /** fMSX: portable MSX emulator ******************************/
  /**                                                         **/
  /**                         Menu.c                          **/
  /**                                                         **/
  /** This file contains runtime menu code for configuring    **/
  /** the emulator. It uses console functions from Console.h. **/
  /**                                                         **/
  /** Copyright (C) Marat Fayzullin 2005-2018                 **/
  /**     You are not allowed to distribute this software     **/
  /**     commercially. Please, notify me, if you make any    **/
  /**     changes to this file.                               **/
  /*************************************************************/
  #include "MSX.h"
  #include "Console.h"
  #include "Sound.h"
  #include "Hunt.h"
  #include "MCF.h"
  
  #include <string.h>
  #include <stdlib.h>
  #include <stdio.h>
  
  #define CLR_BACK   PIXEL(255,255,255)
  #define CLR_BACK2  PIXEL(255,200,150)
  #define CLR_BACK3  PIXEL(150,255,255)
  #define CLR_BACK4  PIXEL(255,255,150)
  #define CLR_BACK5  PIXEL(255,150,255)
  #define CLR_TEXT   PIXEL(0,0,0)
  #define CLR_WHITE  PIXEL(255,255,255)
  #define CLR_ERROR  PIXEL(200,0,0)
  #define CLR_INFO   PIXEL(0,128,0)
  
  static char SndNameBuf[256];
  
  extern byte *MemMap[4][4][8];         /* [PPage][SPage][Adr] */
  extern byte *EmptyRAM;                /* Dummy memory area   */
  
  /** Cheat Structures *****************************************/
  extern int CheatCount;       /* # of cheats in CheatCodes[]  */
  extern int MCFCount;         /* # of entries in MCFEntries[] */
  extern CheatCode CheatCodes[MAXCHEATS];
  extern MCFEntry MCFEntries[MAXCHEATS];
  
  /** MenuMSX() ************************************************/
  /** Invoke a menu system allowing to configure the emulator **/
  /** and perform several common tasks.                       **/
  /*************************************************************/
  void MenuMSX(void)
  {
    const char *P;
    char S[512],*T,*PP;
    int I,J,K,N,V,M;
  
    /* Display and activate top menu */
    for(J=1;J;)
    {
      /* Compose menu */
      sprintf(S,
        "fMSX\n"
        "Load file\n"
        "Save file\n"
        "  \n"
        "Hardware model\n"
        "Input devices\n"
        "Cartridge slots\n"
        "Disk drives\n"
        "Cheats\n"
        "Search cheats\n"
        "  \n"
        "Log soundtrack    %c\n"
        "Hit MIDI drums    %c\n"
        "  \n"
        "Use fixed font    %c\n"
        "Show all sprites  %c\n"
        "Patch DiskROM     %c\n"
        "  \n"
        "POKE &hFFFF,&hAA\n"
        "Rewind tape\n"
        "Reset emulator\n"
        "Quit emulator\n"
        "About\n"
        "Done\n",
        MIDILogging(MIDI_QUERY)? CON_CHECK:' ',
        OPTION(MSX_DRUMS)?       CON_CHECK:' ',
        OPTION(MSX_FIXEDFONT)?   CON_CHECK:' ',
        OPTION(MSX_ALLSPRITE)?   CON_CHECK:' ',
        OPTION(MSX_PATCHBDOS)?   CON_CHECK:' '
      );
  
      /* Replace all EOLNs with zeroes */
      for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
      /* Run menu */
      J=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK,S,J);
      /* Handle menu selection */
      switch(J)
      {
        case 1: /* Load cartridge, disk image, state, or font */
          /* Request file name */
          P=CONFile(CLR_TEXT,CLR_BACK3,".rom\0.rom.gz\0.mx1\0.mx1.gz\0.mx2\0.mx2.gz\0.dsk\0.dsk.gz\0.sta\0.sta.gz\0.cas\0.fnt\0.fnt.gz\0.cht\0.pal\0");
          /* Try loading file, show error on failure */
          if(P&&!LoadSTA(P)&&!LoadFile(P))
            CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Cannot load file.\0\0");
          /* Exit top menu */
          J=0;
          break;
  
        case 2: /* Save state, printer output, or soundtrack */
          /* Run menu */
          switch(CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,
            "Save File\0Emulation state\0Printer output\0MIDI soundtrack\0",1
          ))
          {
            case 1: /* Save state */
              /* Request file name */
              P=CONFile(CLR_TEXT,CLR_BACK2,".sta\0");
              /* Try saving state, show error on failure */
              if(P&&!SaveSTA(P))
                CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Cannot save state.\0\0");
              /* Exit top menu */
              J=0;
              break;
            case 2: /* Printer output file */
              /* Request file name */
              P=CONFile(CLR_TEXT,CLR_BACK2,".prn\0.out\0.txt\0");
              /* Try changing printer output */
              if(P) ChangePrinter(P);
              /* Exit top menu */
              J=0;
              break;
            case 3: /* Soundtrack output file */
              /* Request file name */
              P=CONFile(CLR_TEXT,CLR_BACK2,".mid\0.rmi\0");
              if(P)
              {
                /* Try changing MIDI log output, show error on failure */
                if(strlen(P)+1>sizeof(SndNameBuf))
                  CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Name too long.\0\0");
                else
                {
                  strcpy(SndNameBuf,P);
                  SndName=SndNameBuf;
                  InitMIDI(SndName);
                  MIDILogging(MIDI_ON);
                }
              }
              /* Exit top menu */
              J=0;
              break;
          }
          break;
  
        case 4: /* Hardware model */
          for(K=1;K;)
          {
            /* Compose menu */
            sprintf(S,
              "Hardware Model\n"
              "MSX1 (TMS9918)    %c\n"
              "MSX2 (V9938)      %c\n"
              "MSX2+ (V9958)     %c\n"
              "  \n"
              "NTSC (US/Japan)   %c\n"
              "PAL (Europe)      %c\n"
              "  \n"
              "Main memory   %3dkB\n"
              "Video memory  %3dkB\n"
              "  \n"
              "Done\n",
              MODEL(MSX_MSX1)?       CON_CHECK:' ',
              MODEL(MSX_MSX2)?       CON_CHECK:' ',
              MODEL(MSX_MSX2P)?      CON_CHECK:' ',
              VIDEO(MSX_NTSC)?       CON_CHECK:' ',
              VIDEO(MSX_PAL)?        CON_CHECK:' ',
              RAMPages*16,
              VRAMPages*16
            );
            /* Replace all EOLNs with zeroes */
            for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
            /* Run menu */
            K=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,S,K);
            /* Handle menu selection */
            switch(K)
            {
              case 1:  if(!MODEL(MSX_MSX1))  ResetMSX((Mode&~MSX_MODEL)|MSX_MSX1,RAMPages,VRAMPages);break;
              case 2:  if(!MODEL(MSX_MSX2))  ResetMSX((Mode&~MSX_MODEL)|MSX_MSX2,RAMPages,VRAMPages);break;
              case 3:  if(!MODEL(MSX_MSX2P)) ResetMSX((Mode&~MSX_MODEL)|MSX_MSX2P,RAMPages,VRAMPages);break;
              case 5:  if(!VIDEO(MSX_NTSC))  ResetMSX((Mode&~MSX_VIDEO)|MSX_NTSC,RAMPages,VRAMPages);break;
              case 6:  if(!VIDEO(MSX_PAL))   ResetMSX((Mode&~MSX_VIDEO)|MSX_PAL,RAMPages,VRAMPages);break;
              case 8:  ResetMSX(Mode,RAMPages<32? RAMPages*2:4,VRAMPages);break;
              case 9:  ResetMSX(Mode,RAMPages,VRAMPages<32? VRAMPages*2:2);break;
              case 11: K=0;break;
            }
          }
          /* Exit top menu */
          J=0;
          break;
  
        case 5: /* Input devices */
          for(K=1;K;)
          {
            /* Compose menu */
            sprintf(S,
              "Input Devices\n"
              "SOCKET1:Empty       %c\n"
              "SOCKET1:Joystick    %c\n"
              "SOCKET1:JoyMouse    %c\n"
              "SOCKET1:Mouse       %c\n"
              "  \n"
              "SOCKET2:Empty       %c\n"
              "SOCKET2:Joystick    %c\n"
              "SOCKET2:JoyMouse    %c\n"
              "SOCKET2:Mouse       %c\n"
              "  \n"
              "Autofire on SPACE   %c\n"
              "Autofire on FIRE-A  %c\n"
              "Autofire on FIRE-B  %c\n"
              "  \n"
              "Done\n",
              JOYTYPE(0)==JOY_NONE?     CON_CHECK:' ',
              JOYTYPE(0)==JOY_STICK?    CON_CHECK:' ',
              JOYTYPE(0)==JOY_MOUSTICK? CON_CHECK:' ',
              JOYTYPE(0)==JOY_MOUSE?    CON_CHECK:' ',
              JOYTYPE(1)==JOY_NONE?     CON_CHECK:' ',
              JOYTYPE(1)==JOY_STICK?    CON_CHECK:' ',
              JOYTYPE(1)==JOY_MOUSTICK? CON_CHECK:' ',
              JOYTYPE(1)==JOY_MOUSE?    CON_CHECK:' ',
              OPTION(MSX_AUTOSPACE)?    CON_CHECK:' ',
              OPTION(MSX_AUTOFIREA)?    CON_CHECK:' ',
              OPTION(MSX_AUTOFIREB)?    CON_CHECK:' '
            );
            /* Replace all EOLNs with zeroes */
            for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
            /* Run menu */
            K=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,S,K);
            /* Handle menu selection */
            switch(K)
            {
              case 1:  SETJOYTYPE(0,JOY_NONE);break;
              case 2:  SETJOYTYPE(0,JOY_STICK);break;
              case 3:  SETJOYTYPE(0,JOY_MOUSTICK);break;
              case 4:  SETJOYTYPE(0,JOY_MOUSE);break;
              case 6:  SETJOYTYPE(1,JOY_NONE);break;
              case 7:  SETJOYTYPE(1,JOY_STICK);break;
              case 8:  SETJOYTYPE(1,JOY_MOUSTICK);break;
              case 9:  SETJOYTYPE(1,JOY_MOUSE);break;
              case 11: Mode^=MSX_AUTOSPACE;break;
              case 12: Mode^=MSX_AUTOFIREA;break;
              case 13: Mode^=MSX_AUTOFIREB;break;
              case 15: K=0;break;
            }
          }
          /* Exit top menu */
          J=0;
          break;
  
        case 6: /* Cartridge slots */
          /* Create slot selection menu */
          sprintf(S,
            "Cartridges\n"
            "Slot A:%c\n"
            "Slot B:%c\n",
            MemMap[1][0][2]!=EmptyRAM? CON_FILE:' ',
            MemMap[2][0][2]!=EmptyRAM? CON_FILE:' '
          );
          /* Replace all EOLNs with zeroes */
          for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
          /* Get cartridge slot number */
          N=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,S,1);
          /* Exit to top menu if cancelled */
          if(!N) break; else --N;
          /* Run slot-specific menu */
          for(K=1;K;)
          {
            /* Compose menu */
            sprintf(S,
              "Cartridge Slot %c\n"
              "Load cartridge\n"
              "Eject cartridge\n"
              "Guess MegaROM mapper  %c\n"
              "  \n"
              "Generic 8kB switch    %c\n"
              "Generic 16kB switch   %c\n"
              "Konami 5000h mapper   %c\n"
              "Konami 4000h mapper   %c\n"
              "ASCII 8kB mapper      %c\n"
              "ASCII 16kB mapper     %c\n"
              "Konami GameMaster2    %c\n"
              "Panasonic FMPAC       %c\n"
              "  \n"
              "Done\n",
              'A'+N,
              ROMGUESS(N)?              CON_CHECK:' ',
              ROMTYPE(N)==MAP_GEN8?     CON_CHECK:' ',
              ROMTYPE(N)==MAP_GEN16?    CON_CHECK:' ',
              ROMTYPE(N)==MAP_KONAMI5?  CON_CHECK:' ',
              ROMTYPE(N)==MAP_KONAMI4?  CON_CHECK:' ',
              ROMTYPE(N)==MAP_ASCII8?   CON_CHECK:' ',
              ROMTYPE(N)==MAP_ASCII16?  CON_CHECK:' ',
              ROMTYPE(N)==MAP_GMASTER2? CON_CHECK:' ',
              ROMTYPE(N)==MAP_FMPAC?    CON_CHECK:' '
            );
            /* Replace all EOLNs with zeroes */
            for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
            /* Run menu */
            K=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,S,K);
            /* Handle menu selection */
            switch(K)
            {
              case 1:
                /* Request file name */
                P=CONFile(CLR_TEXT,CLR_BACK3,".rom\0.rom.gz\0.mx1\0.mx1.gz\0.mx2\0.mx2.gz\0");
                /* Try loading file, show error on failure */
                if(P&&!LoadCart(P,N,ROMGUESS(N)|ROMTYPE(N)))
                  CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Cannot load file.\0\0");
                /* Exit to top menu */
                K=0;
                break;
              case 2:  LoadCart(0,N,ROMGUESS(N)|ROMTYPE(N));K=0;break;
              case 3:  Mode^=MSX_GUESSA<<N;break;
              case 5:
              case 6:
              case 7:
              case 8:
              case 9:
              case 10:
              case 11:
              case 12: SETROMTYPE(N,K-5);ResetMSX(Mode,RAMPages,VRAMPages);break;
              case 14: K=0;break;
            }
          }
          /* Exit top menu */
          J=0;
          break;
  
        case 7: /* Disk drives */
          /* Create drive selection menu */
          sprintf(S,
            "Disk Drives\n"
            "Drive A:%c\n"
            "Drive B:%c\n",
            FDD[0].Data? CON_FILE:' ',
            FDD[1].Data? CON_FILE:' '
          );
          /* Replace all EOLNs with zeroes */
          for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
          /* Get disk drive number */
          N=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,S,1);
          /* Exit to top menu if cancelled */
          if(!N) break; else --N;
          /* Create disk operations menu */
          sprintf(S,
            "Disk Drive %c:\n"
            "Load disk\n"
            "New disk\n"
            "Eject disk\n"
            " \n"
            "Save DSK image\n"
            "Save FDI image\n",
            'A'+N
          );
          /* Replace all EOLNs with zeroes */
          for(I=0;S[I];I++) if(S[I]=='\n') S[I]='\0';
          /* Run menu and handle menu selection */
          switch(CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK4,S,1))
          {
            case 1: /* Load disk */
              P=CONFile(CLR_TEXT,CLR_BACK3,".dsk\0.dsk.gz\0.fdi\0.fdi.gz\0");
              if(P&&!ChangeDisk(N,P))
                CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Cannot load disk image.\0\0");
              break;
            case 2: /* New disk */
              ChangeDisk(N,"");
              break;
            case 3: /* Eject disk */
              ChangeDisk(N,0);
              break;
            case 5: /* Save .DSK image */
              P=CONFile(CLR_TEXT,CLR_BACK2,".dsk\0");
              if(P&&!SaveFDI(&FDD[N],P,FMT_DSK))
                CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Cannot save disk image.\0\0");
              break;
            case 6: /* Save .FDI image */
              P=CONFile(CLR_TEXT,CLR_BACK2,".fdi\0");
              if(P&&!SaveFDI(&FDD[N],P,FMT_FDI))
                CONMsg(-1,-1,-1,-1,CLR_BACK,CLR_ERROR,"Error","Cannot save disk image.\0\0");
              break;
          }
          /* Exit top menu */
          J=0;
          break;
  
        case 8: /* Cheats */
          /* Allocate buffer for cheats */
          PP=malloc(MAXCHEATS*2*16+64);
          if(!PP) break;
          /* Save cheat setting and turn cheats off */
          K=Cheats(CHTS_QUERY);
          Cheats(CHTS_OFF);
          /* Menu loop */
          for(I=1;I;)
          {
            /* Compose menu */
            sprintf(PP,
              "Cheat Codes\n"
              "Enabled     %c\n"
              "New cheat\n"
              "Done\n"
              " \n",
              K? CON_CHECK:' '
            );
            T=PP+strlen(PP);
            for(J=0;J<CheatCount;++J)
            { strcpy(T,(const char *)CheatCodes[J].Text);T+=strlen(T);*T++='\n'; }
            *T='\0';
  
            /* Replace all EOLNs with zeroes */
            for(J=0;PP[J];J++) if(PP[J]=='\n') PP[J]='\0';
            /* Run menu */
            I=CONMenu(-1,-1,16,24,CLR_TEXT,CLR_BACK4,PP,I);
            /* Handle menu selection */
            switch(I)
            {
              case 1:
                K=!K;
                break;
              case 2:
                T=CONInput(-1,-1,CLR_TEXT,CLR_BACK2,"New cheat:",S,14);
                if(T) AddCheat(T);
                break;
              case 3:
                I=0;
                break;
              default:
                /* No cheats above this line */
                if(I<5) break;
                /* Find cheat */
                for(T=PP,J=0;*T&&(J<I);++J) T+=strlen(T)+1;
                /* Delete cheat */
                if(T) DelCheat(T);
                break;
            }
          }
          /* Put cheat settings into effect */
          if(K) Cheats(CHTS_ON);
          /* Done */
          free(PP);
          J=0;
          break;
  
        case 9: /* Hunt for cheat codes */
          /* Until user quits the menu... */
          for(I=1;I;)
          {
            /* Compose menu */
            sprintf(S,
              "Cheat Hunter\n"
              "Clear all watches\n"
              "Add a new watch\n"
              "Scan watches\n"
              "See cheat codes\n"
              "  \n"
              "Done\n"
            );
  
            /* Replace all EOLNs with zeroes */
            for(J=0;S[J];J++) if(S[J]=='\n') S[J]='\0';
  
            /* Run menu */
            I=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK5,S,I);
  
            /* Handle menu selection */
            switch(I)
            {
              case 1: InitHUNT();break;
              case 6: I=0;break;
  
              case 2:
                /* Ask for search value in 0..65535 range */
                for(K=-1;(K<0)&&(P=CONInput(-1,-1,CLR_TEXT,CLR_BACK4,"Watch Value",S,6|CON_DEC));)
                {
                  K = strtoul(P,0,10);
                  K = K<0x10000? K:-1;
                }
  
                /* If cancelled, drop out */
                if(!P) { I=0;break; }
  
                /* Ask for search options */
                for(I=1,V=K,M=0;I;)
                {
                  /* Force 16bit mode for large values */
                  if((K>=0x100)||(V>=0x100)) M|=HUNT_16BIT;
  
                  sprintf(S,
                    "Search for %d\n"
                    "New value %5d\n"
                    "  \n"
                    "8bit value    %c\n"
                    "16bit value   %c\n"
                    "  \n"
                    "Constant      %c\n"
                    "Changes by +1 %c\n"
                    "Changes by -1 %c\n"
                    "Changes by +N %c\n"
                    "Changes by -N %c\n"
                    "  \n"
                    "Search now\n",
                    K,V,
                    !(M&HUNT_16BIT)? CON_CHECK:' ',
                    M&HUNT_16BIT?    CON_CHECK:' ',
                    (M&HUNT_MASK_CHANGE)==HUNT_CONSTANT?  CON_CHECK:' ',
                    (M&HUNT_MASK_CHANGE)==HUNT_PLUSONE?   CON_CHECK:' ',
                    (M&HUNT_MASK_CHANGE)==HUNT_MINUSONE?  CON_CHECK:' ',
                    (M&HUNT_MASK_CHANGE)==HUNT_PLUSMANY?  CON_CHECK:' ',
                    (M&HUNT_MASK_CHANGE)==HUNT_MINUSMANY? CON_CHECK:' '
                  );
  
                  /* Replace all EOLNs with zeroes */
                  for(J=0;S[J];J++) if(S[J]=='\n') S[J]='\0';
  
                  /* Run menu */
                  I=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK2,S,I);
  
                  /* Change options */
                  switch(I)
                  {
                    case 1:
                      /* Ask for replacement value in 0..65535 range */
                      P  = CONInput(-1,-1,CLR_TEXT,CLR_BACK4,"New Value",S,6|CON_DEC);
                      I  = P? strtoul(P,0,10):-1;
                      V = (I>=0)&&(I<0x10000)? I:V;
                      I  = 1;
                      break;
                    case 3:  M&=~HUNT_16BIT;break;
                    case 4:  M|=HUNT_16BIT;break;
                    case 6:  M=(M&~HUNT_MASK_CHANGE)|HUNT_CONSTANT;break;
                    case 7:  M=(M&~HUNT_MASK_CHANGE)|HUNT_PLUSONE;break;
                    case 8:  M=(M&~HUNT_MASK_CHANGE)|HUNT_MINUSONE;break;
                    case 9:  M=(M&~HUNT_MASK_CHANGE)|HUNT_PLUSMANY;break;
                    case 10: M=(M&~HUNT_MASK_CHANGE)|HUNT_MINUSMANY;break;
                    case 12:
                      /* Search for value RAM */
                      J = AddHUNT(0xC000,0x4000,K,V,M);
                      I = 0;
                      /* Show number of found locations */
                      sprintf(S,"Found %d locations.\n",J);
                      for(J=0;S[J];J++) if(S[J]=='\n') S[J]='\0';
                      CONMsg(-1,-1,-1,-1,CLR_WHITE,CLR_INFO,"Initial Search",S);
                      break;
                  }
                }
                I=0;
                break;
  
              case 3: ScanHUNT();
              /* Fall through */
              case 4: /* Show current cheats */
                /* Find current number of locations, limit it to 32 */
                K = TotalHUNT();
                K = K<32? K:32;
  
                /* If no locations, show a warning */
                if(!K)
                {
                  CONMsg(-1,-1,-1,-1,CLR_WHITE,CLR_INFO,"Empty","No cheats found.\0\0");
                  I=0;
                  break;
                }
  
                /* Show cheat selection dialog */
                for(I=1,M=0;I;)
                {
                  /* Compose dialog */
                  sprintf(S,"Found %d Cheats\n",K);
                  for(J=0;(J<K)&&(strlen(S)<sizeof(S)-64);++J)
                  {
                    if(!(PP=(char *)HUNT2Cheat(J,HUNT_MSX))) break;
                    if(strlen(PP)>9) { PP[8]=CON_DOTS;PP[9]='\0'; }
                    sprintf(S+strlen(S),"%-9s %c\n",PP,M&(1<<J)? CON_CHECK:' ');
                  }
                  strcat(S,"  \nAdd cheats\n");
       
                  /* Number of shown locations */
                  K=J;
       
                  /* Replace all EOLNs with zeroes */
                  for(J=0;S[J];J++) if(S[J]=='\n') S[J]='\0';
       
                  /* Run menu */
                  I=CONMenu(-1,-1,-1,16,CLR_TEXT,CLR_BACK2,S,I);
       
                  /* Toggle checkmarks */
                  if((I>=1)&&(I<=K)) M^=1<<(I-1);
                  else if(I)
                  {
                    /* If there are cheats to add, drop out */
                    if(!M)
                    {
                      CONMsg(-1,-1,-1,-1,CLR_WHITE,CLR_INFO,"Empty","No cheats chosen.\0\0");
                      I=0;
                      break;
                    }
  
                    /* Disable and clear current cheats */
                    ResetCheats();
  
                    /* Add found cheats */
                    for(J=0;J<K;++J)
                      if((M&(1<<J))&&(P=(char *)HUNT2Cheat(J,HUNT_MSX)))
                        for(T=0;P;P=T)
                        {
                          T=strchr(P,';');
                          if(T) *T++='\0';
                          AddCheat(P);
                        }
  
                    /* Activate new cheats */
                    Cheats(CHTS_ON);
                    I=0;
                  }
                }
  
                /* Done with the menu */
                I=0;
                break;
            }
          }
          J=0;
          break;
  
        case 11: /* Log MIDI soundtrack */
          MIDILogging(MIDI_TOGGLE);
          break;
        case 12: /* Hit MIDI drums for noise */
          Mode^=MSX_DRUMS;
          break;
        case 14: /* Use fixed font */
          Mode^=MSX_FIXEDFONT;
          break;
        case 15: /* Show all sprites */
          Mode^=MSX_ALLSPRITE;
          break;
        case 16: /* Patch DiskROM routines */
          ResetMSX(Mode^MSX_PATCHBDOS,RAMPages,VRAMPages);
          break;
        case 18: /* POKE &hFFFF,&hAA */
          WrZ80(0xFFFF,0xAA);
          J=0;
          break;
        case 19: /* Rewind */
          RewindTape();
          J=0;
          break;
        case 20: /* Reset */
          ResetMSX(Mode,RAMPages,VRAMPages);
          J=0;
          break;
        case 21: /* Quit */
          ExitNow=1;
          J=0;
          break;
        case 22:
          //CONMsg(-1,-1,-1,-1,CLR_WHITE,CLR_INFO,"About","fMSX by Marat Fayzullin, ported by Baram \0\0");
          /* Compose menu */
          sprintf(S,
            "About - fMSX\n"
            "https://fms.komkon.org/fMSX/\n"
            "Made by Marat Fayzullin\n"
            " \n"
            "Ported by Baram for OROCABOY\n"
          );
  
          /* Replace all EOLNs with zeroes */
          for(J=0;S[J];J++) if(S[J]=='\n') S[J]='\0';
  
          /* Run menu */
          I=CONMenu(-1,-1,-1,-1,CLR_TEXT,CLR_BACK5,S,I);
          J=0;
          break;
        case 23: /* Done */
          J=0;
          break;
      }
    }
  }
  