/*****************************************************************************/
/*                                                                           */
/*   VECTREX HP3000 Software Emulator              Copyright K.Wilkins 1996  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Title      : Vectrex System ROM Emulation function module               */
/*                                                                           */
/*   File Name  : SYS_ROM.C                                                  */
/*                                                                           */
/*   Author     : Keith Wilkins                                              */
/*                                                                           */
/*   Version    : 1.00                                                       */
/*                                                                           */
/*   Desciption : This file contains the functions that emulate the Vectrex  */
/*                System ROM. The ROM Write routine is only allowed when     */
/*                the System is in debug mode and is for doing patches.      */
/*                                                                           */
/*   Functions  : fSystemROMLoad()      - Init & Load the System Exec ROM    */
/*                fSystemROMSave()      - Save the System ROM area to disk   */
/*                fSystemROMRead()      - Read a ROM location                */
/*                fSystemROMWrite()     - Write to a ROM location            */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Revision History:                                                       */
/*                                                                           */
/*   Version    Date    Who  Description of changes                          */
/*   -------    ----    ---  ----------------------                          */
/*                                                                           */
/*    0.01    14/03/93  K.W  Creation of empty file and descriptions         */
/*    1.00    05/08/96  K.W  Public release of DVE V1.0                      */
/*                                                                           */
/*****************************************************************************/

#ifdef _NO_DEBUG_INFORMATION_

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <standard.h>

#include "emu6809.h"
#include "vdebug.h"
#include "verror.h"
#include "vectrex.h"
#include "sys_rom.h"
#include "dis6809.h" //dis_init_state

static T_INT tFirstTime=T_TRUE;

#endif //#ifdef _NO_DEBUG_INFORMATION_

#ifndef _NO_DEBUG_INFORMATION_

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemROMLoad()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : This function will open and load a binary file into the   */
/*                 8Kb System ROM space. Before loading all addresses        */
/*                 will be written to SYSTEM_ROM_FILL_VALUE. The file is     */
/*                 opened before the ROM space is cleared as if the load     */
/*                 fails we havent destroyed the current ROM Image.          */
/*                                                                           */
/*   Accepts     : char * Pointer to a file name, any length.                */
/*                                                                           */
/*   Returns     : BOOLEAN T_TRUE/T_FALSE depending on load success.             */
/*                                                                           */
/*****************************************************************************/

T_INT fSystemROMLoad(T_UCHAR *pcROMFileName)
{
    T_INT        bRetVal=T_TRUE;
    T_INT        bTmp;
    FILE        *pfSystemROM=NULL;
    T_ULONG       tLoop;
    T_UCHAR       tData;
    T_PCHAR current_path=NULL;

    /* Only on the 1st execution do we declare the ROM Space */

    if (tFirstTime==T_TRUE)
    {
     tFirstTime=T_FALSE;
     if (f6809DeclareAddress(SYSTEM_ROM_BASE,SYSTEM_ROM_SIZE,fSystemROMRead,fSystemROMWrite)==T_FALSE)
     {
      fDebug(VERROR,("fSystemROMLoad() ROM Space delaration failed"));
      return(T_FALSE);
     }
    }

    // If no filename present we return error

    if (pcROMFileName==NULL || strcmp(pcROMFileName,"")==0)
    {
       fDebug(VERROR,("fSystemROMLoad() - No filename given"));
       return(T_FALSE);
    }

    /* Enable Cartridge ROM writes, and save current stats */

    bTmp=bGblSystemROMWriteEnable;
    bGblSystemROMWriteEnable=T_TRUE;

    /* Now clear out the ROM area */

    for(tLoop=SYSTEM_ROM_BASE;tLoop<=SYSTEM_ROM_TOP;tLoop++)
    {
     f6809AddressWrite((T_UWORD)tLoop,SYSTEM_ROM_FILL_VALUE);
    }
    fDebug(MED,("fSystemROMLoad() ROM Space Cleared"));

    /* Try and open the ROM image file */
    current_path=get_current_path();
    if (GblBinDir!=NULL)
     change_directory(GblBinDir);
    if (f_file_exist(pcROMFileName)==T_FALSE)
    {
     if (current_path!=NULL)
     {
      change_directory(current_path);
      free(current_path);
      current_path=NULL;
     }
    }
    if((pfSystemROM=fopen(pcROMFileName,"rb"))==NULL)
    {
        fDebug(VERROR,("fSystemROMLoad() Couldnt open file \"%s\"",pcROMFileName));
        bRetVal=T_FALSE;
    }
    else
    {
        fDebug(MED,("fSystemROMLoad() \"%s\" opened O.K",pcROMFileName));

        /* Now load until we reach ROM_TOP or the file ends */

        tLoop=SYSTEM_ROM_BASE;

        while(tLoop<=SYSTEM_ROM_TOP && fread(&tData,sizeof(T_UCHAR),1,pfSystemROM)==1)
        {
            f6809AddressWrite((T_UWORD)tLoop++,tData);
        }
        fDebug(MED,("fSystemROMLoad() Loaded %ld Bytes",tLoop-SYSTEM_ROM_BASE));

        fclose(pfSystemROM);
        if (current_path!=NULL)
        {
         change_directory(current_path);
         free(current_path);
         current_path=NULL;
        }
    }

    /* Restore the ROM writes flag */

    bGblSystemROMWriteEnable=bTmp;
    dis_init_state=T_FALSE;

    /* All finished */

    return(bRetVal);

}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemROMSave()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Open a file on disk, write the contents of the system ROM */
/*                 to disk and close the file                                */
/*                                                                           */
/*   Accepts     : char * Pointer to a file name, any length.                */
/*                                                                           */
/*   Returns     : T_INTEAN T_TRUE/T_FALSE depending on load success.             */
/*                                                                           */
/*****************************************************************************/

T_INT fSystemROMSave(T_PUCHAR pcROMFileName)
{
    T_PCHAR current_path=NULL;
    FILE    *pfSystemROM=NULL;
    T_UWORD   tLoop;
    T_UCHAR   tData;

    /* Try and open the ROM image file */

    current_path=get_current_path();
    if (GblBinDir!=NULL)
     change_directory(GblBinDir);
    if (f_file_exist(pcROMFileName)==T_FALSE)
    {
     if (current_path!=NULL)
     {
      change_directory(current_path);
      free(current_path);
      current_path=NULL;
     }
    }
    if((pfSystemROM=fopen(pcROMFileName,"wb"))==NULL)
    {
        fDebug(VERROR,("fSystemROMSave() Couldnt open file %s",pcROMFileName));
        return(T_FALSE);
    }
    else
    {
        fDebug(MED,("fSystemROMSave() %s opened O.K",pcROMFileName));
    }

    /* Now Save SYSTEM_ROM_SIZE bytes */

    tLoop=SYSTEM_ROM_BASE;

    while(tLoop<SYSTEM_ROM_SIZE)
    {
        tData=fSystemROMRead(SYSTEM_ROM_BASE+tLoop++);
        if(fwrite(&tData,sizeof(T_UCHAR),1,pfSystemROM)==0)
        {
            fclose(pfSystemROM);
            if (current_path!=NULL)
            {
             change_directory(current_path);
             free(current_path);
             current_path=NULL;
            }
            fDebug(VERROR,("fSystemROMSave() File write error, aborting save"));
            return(T_FALSE);
        }
    }
    fDebug(MED,("fSystemROMSave() Saved %d Bytes",tLoop-SYSTEM_ROM_BASE));

    if (current_path!=NULL)
    {
     change_directory(current_path);
     free(current_path);
     current_path=NULL;
    }
    fclose(pfSystemROM);

    /* All finished */

    return(T_TRUE);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemROMRead()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Read a value from the ROM image, apply the address mask   */
/*                 to the address before reading to ensure were not out of   */
/*                 bounds.                                                   */
/*                                                                           */
/*   Accepts     : WORD Address pointer (16bit)                              */
/*                                                                           */
/*   Returns     : BYTE Data value                                           */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fSystemROMRead(T_UWORD tAddress)
{
 // We can gauarantee because of the memory handler that tAddress
 // will always be in the correct range
 fDebug(LOW,("fSystemROMRead:%i",tAddress));
 return (atSystemImage[tAddress]);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemROMWrite()                                         */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Write a byte to the image array, the address is masked    */
/*                 before the write to ensure we're within the bounds of the */
/*                 array. The write is only performed if the ROM write       */
/*                 enable flag is T_TRUE.                                      */
/*                                                                           */
/*   Accepts     : WORD Address and a BYTE of Data                           */
/*                                                                           */
/*   Returns     : BYTE of Data                                              */
/*                                                                           */
/*****************************************************************************/

T_UCHAR fSystemROMWrite(T_UWORD tAddress,T_UCHAR tData)
{
 // We can gauarantee because of the memory handler that tAddress
 // will always be in the correct range
 if (bGblSystemROMWriteEnable==T_FALSE)
 {
  fDebug(VERROR,("fSystemROMWrite() Attempt to Write #$%02x to ROM $%04x",tData,tAddress));
 }
 else
 {
  atSystemImage[tAddress]=tData;
 }
 return(tData);
}

#endif //#ifndef _NO_DEBUG_INFORMATION_
