/*

File: target_program.c
Author: Neil Cafferkey
Copyright (C) 1999-2001 Neil Cafferkey

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 2
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.

*/


#include "address_protos.h"
#include "address_set_protos.h"
#include "bank_protos.h"
#include "reverse_graph_protos.h"
#include "set_protos.h"
#include "source_program_protos.h"
#include "string_protos.h"
#include "target_program_protos.h"

#include <stdio.h>
#include <assert.h>


/* Function: WriteTargetProgram
 * ============================
 */

VOID WriteTargetProgram(SourceProgram src_prog,TEXT *directory_name)
{
   Address address;
   Set bank_set=GetSourceProgramBanks(src_prog);
   Bank bank;
   AddressSet entry_points,interrupt_points;
   ULONG base,end,bank_count;
   ULONG i;
   FILE *file;
   LONGBITS flags;
   TEXT *translation;
/*   Instruction instruction;*/

   TEXT *prog_name=GetSourceProgramName(src_prog);
   TEXT *path=CreateString(strlen(directory_name)+strlen(prog_name)+strlen(".asm")+3);

   /* Write translated assembly file for each bank */

   for(bank_count=0;(bank=TakeFromSet(bank_set))!=NULL;bank_count++)
   {

      /* Get file path */

      sprintf(path,"%s%s%s",directory_name,prog_name,".asm");

      /* Create translated assembly file */

      file=fopen(path,"w");
      if(file==NULL)
         fprintf(stderr,"Can't open \"%s\" for writing. Exiting...\n",path);

      /* Get start and end of this bank */

      base=GetBankBase(bank);
      end=base+GetBankLength(bank);

      /* Print assembler directives etc. */

      fprintf(file,"\n\tinclude\t\"atari2600.i\"\n\n\n");

      interrupt_points=GetInterruptPoints(src_prog);
      if(!IsEmptySet(interrupt_points))
         fprintf(file,"\tmacro\tINTERRUPT\n\tbsr\t.%04x\n\tendm\n\n\n",
            GetAddressOffset(TakeFromSet(interrupt_points)));
      KillSet(interrupt_points);

      fprintf(file,"\tcode\n\n\tSTART_UP\n");
      fprintf(file,"\tlea\tdata,DATA\n");

      entry_points=GetEntryPoints(src_prog);
      if(IsEmptySet(entry_points))
         exit(20);

      fprintf(file,"\tbra\t.%04x\n\n",
         GetAddressOffset(TakeFromSet(entry_points)));
      KillSet(entry_points);

      /* Print instructions from this bank */

      for(i=base;i<end;i++)
      {
         address=GetBankAddress(bank,i);

         /* Print a single instruction and associated condition code handling */

         if(address!=NULL)
         {

            /* Print address label */

            fprintf(file,".%04x:",i);

            /* Print macro to restore condition codes */
/*
            if((instruction=GetAddressInstruction(address))!=NULL)
            {
               flags=GetCriticalFlags(instruction);
               if(flags!=0)
                  fprintf(file,"\tLOAD_P\n");
            }
*/
            /* Print actual instruction */

            if((translation=GetAddressTranslation(address))!=NULL)
               fprintf(file,"\t%s",translation);

            fprintf(file,"\n");

            /* Print macro to save condition codes */

            flags=GetSavedFlags(address);
            if(flags!=0)
               fprintf(file,"\tSAVE_P\t$%x\n",flags);

         }
      }

      fprintf(file,"\nexit:\n\n\tEXIT\n\n\n");

      fprintf(file,"\tdata\n\n\tcnop\t0,4\n\n");
      fprintf(file,"rom:\n\n\tincbin\t\"%s\"\n\n\n",GetBankDataFileName(bank));

      fprintf(file,"\tdata\n\nprog_name:\n\tdc.b\t\"%s\",0\n\n",
         GetSourceProgramName(src_prog));
      fprintf(file,"\tcnop\t0,4\n\n"
         "env_tags:\n\n\tdc.l\tA2600TAG_ProgramName,prog_name\n"
         "\tdc.l\tA2600TAG_ExitFunction,exit\n"
         "\tdc.l\tTAG_MORE,extra_tags\n\n\n");
      fprintf(file,"\tend\n\n\n");

      fclose(file);
   }


   KillSet(bank_set);
   KillString(path);

   return;
}


/* Function: KillTargetProgram
 * ===========================
 */
/*
VOID KillTargetProgram(TargetProgram target_prog)
{
   return;
}
*/

