/*
  HI65 - a high-level Commodore 65 emulator
  Copyright (C) 2013-2023  Simone Gremmo
  Contact: devilmaster@email.com

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see
  http://www.gnu.org/licenses/gpl.txt
*/

#define MAIN

#include <allegro.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include "f8x8.h"
#include "gdef.h"
#include "pro.h"
#include "var.h"
 
int main(int argc, char* argv[])
{
 uchar i;
#ifdef DEBUG_SCREEN
 size_t actual_size;
 FILE *pFile;
#endif
 
 // We expect 2 arguments: the name of the executable and the name of
 // the program to load
 
#ifdef DEBUG_SCREEN
 pFile = fopen ("errorlog.txt","a");
 fputs ("*******************\n",pFile);
 fputs ("* DEBUG LOG START *\n",pFile);
 fputs ("*******************\n",pFile);
 if (argc==3 && !strcmp(argv[2],"recognition_code_927_i_am_a_potato"))
  fputs ("Emulator loaded from Hi65 Edit and Launch Tool.exe\n",pFile);
 else if (argc==1)
  fputs ("Emulator loaded from hi65.exe\n",pFile);
 fclose (pFile);
#endif
 
 // you should always do this at the start of Allegro programs
 if (allegro_init())
  return 1;
#ifdef DEBUG_SCREEN
 pFile = fopen ("errorlog.txt","a");
 fputs ("Allegro library initialized\n",pFile);
 fclose (pFile);
#endif
  
 initvars(); // the variables are initialized
#ifdef DEBUG_SCREEN
 pFile = fopen ("errorlog.txt","a");
 fputs ("C65 variables initialized\n",pFile);
 fclose (pFile);
#endif

 //set up timer handler
 install_timer();
 LOCK_VARIABLE(numvars[TI][0]);
 LOCK_FUNCTION(ticker);
 install_int_ex(ticker, BPS_TO_TIMER(60)); // now we have a timer that ticks 60 times per second
#ifdef DEBUG_SCREEN
 pFile = fopen ("errorlog.txt","a");
 fputs ("Timer initialized\n",pFile);
 fclose (pFile);
#endif
 
 // set up the keyboard handler
 install_keyboard();
#ifdef DEBUG_SCREEN
 pFile = fopen ("errorlog.txt","a");
 fputs ("Keyboard installed\n",pFile);
 fclose (pFile);
#endif
 
 shifted=0;
 
 // configure the resolution
 setresolution();
#ifdef DEBUG_SCREEN
 pFile = fopen ("errorlog.txt","a");
 fputs ("Resolution ",pFile);
 fputc (cfgarray[0]+'0',pFile);
 fputs (" configured as ",pFile);
 if (cfgarray[1])
  fputs ("full screen\n",pFile);
 else
  fputs ("windowed\n",pFile);
 fclose (pFile);
#endif
 
 if (startscreen(0))
  return 1;
 else
  Ready();

 
 if (argc>=2)
 {
  loaderror=0;
  loaderror=load((uchar *)argv[1]); // the program is loaded
#ifdef DEBUG_SCREEN
  pFile = fopen ("errorlog.txt","a");
  fputs ("The program has been loaded\n",pFile);
  fclose (pFile);
#endif
  
  // This simulates what (probably) happens when you load a BASIC
  // program on a physical C65
  simulateloadinstructions((uchar *)argv[1],1);
  
  if (!loaderror)
  {
   prints((uchar *)"run");
   Enter();
   
   // The program is only recognized as loaded from the frontend (as
   // opposed to being loaded from the command line) if the line
   // comprises three parameters:
   // 0) the executable we are launching (hi65)
   // 1) the name of the program we want to run
   // 2) a particular string that is very unlikely to be typed by accident
   if (argc==3 && !strcmp(argv[2],"recognition_code_927_i_am_a_potato"))
    program_loaded_from_frontend=1;
   else
    program_loaded_from_frontend=0;
#ifdef DEBUG_SCREEN
  pFile = fopen ("errorlog.txt","a");
  fputs ("About to run the program...\n",pFile);
  fclose (pFile);
#endif
   Run(1); // WE RUN THE PROGRAM!!!
  }
 
  // If two consecutive cycles have the same instruction end address,
  // the program counter is stuck (like in a 10 GOTO 10 instruction)
#ifdef DEBUG_INSTRUCTIONS
  if (instruction_end_address==old_instruction_end_address)
  {
   Enter();
   forecolor=makecol(240,0,0);
   prints((uchar *)"program counter stuck in loop"); Enter();
   prints((uchar *)"address "); printn(pc); prints((uchar *)" value "); printn(program[pc]);
   forecolor=makecol(240,240,240);
  }
#endif
  Ready();
 }
 else
  program_loaded_from_frontend=0;
 
 // This may look like the main loop, where most of the emulation is
 // done, but it's not. The main loop is actually inside the Run
 // function in interpreter.cpp, where the Interpret function is called
 // once per iteration. That is what runs the programs.
 // This loop handles the keyboard when the emulator is NOT running a
 // program, and the interpretation of direct commands is triggered
 // by pressing the Return key.
 while(1)
 {
  if (keyboard(0)) // quit if ESC is pressed
   return 0;
 }

 return 0;
}

END_OF_MAIN()

