/*****************************************************************************/
/*                                                                           */
/*   VECTREX HP3000 Software Emulator              Copyright K.Wilkins 1996  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Title      : Vectrex System RAM Emulation function module               */
/*                                                                           */
/*   File Name  : SYS_RAM.C                                                  */
/*                                                                           */
/*   Author     : Keith Wilkins                                              */
/*                                                                           */
/*   Version    : 1.00                                                       */
/*                                                                           */
/*   Desciption : This file contains the functions that emulate the Vectrex  */
/*                System RAM.                                                */
/*                                                                           */
/*   Functions  : fSystemRAMInit()      - Init & Load the System RAM         */
/*                fSystemRAMSave()      - Save the System RAM area to disk   */
/*                fSystemRAMRead()      - Read a RAM location                */
/*                fSystemRAMWrite()     - Write to a RAM 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_ram.h"

static T_INT tFirstTime=T_TRUE;

#endif //#ifdef _NO_DEBUG_INFORMATION_

#ifndef _NO_DEBUG_INFORMATION_

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemRAMLoad()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : This function will open and load a binary file into the   */
/*                 1Kb System RAM space. Before loading all addresses        */
/*                 will be written to SYSTEM_RAM_FILL_VALUE. The file is     */
/*                 opened before the RAM space is cleared as if the load     */
/*                 fails we havent destroyed the current RAM Image.          */
/*                 If a NULL file is passed we fill ram only.                */
/*                                                                           */
/*   Accepts     : char * Pointer to a file name, any length.                */
/*                                                                           */
/*   Returns     : T_INTEAN T_TRUE/T_FALSE depending on load success.             */
/*                                                                           */
/*****************************************************************************/

T_INT fSystemRAMLoad(T_PUCHAR pcRAMFileName)
{
    T_INT         bRetVal=T_TRUE;
    FILE         *pfSystemRAM=NULL;
    T_ULONG        tLoop;
    T_UBYTE        tData;

    /* First Time through we must decare the RAM to the CPU */

    if (tFirstTime==T_TRUE)
    {
        tFirstTime=T_FALSE;
        if(f6809DeclareAddress(SYSTEM_RAM_BASE,SYSTEM_RAM_SIZE,fSystemRAMRead,fSystemRAMWrite)==T_FALSE)
        {
            fDebug(VERROR,("fSystemRAMLoad() RAM Space delaration failed"));
            return(T_FALSE);
        }
    }

    /* Now clear out the RAM area */

    for(tLoop=SYSTEM_RAM_BASE;tLoop<=SYSTEM_RAM_TOP;tLoop++)
    {
        f6809AddressWrite((T_UWORD)tLoop,SYSTEM_RAM_FILL_VALUE);
    }
    fDebug(MED,("fSystemRAMLoad() RAM Space Cleared"));

    /* Try and open the RAM image file, if NULL dont open */

    if(pcRAMFileName!=NULL && strcmp(pcRAMFileName,"")!=0)
    {
        T_PCHAR current_path=NULL;
        current_path=get_current_path();
        if (GblBinDir!=NULL)
         change_directory(GblBinDir);
        if (f_file_exist(pcRAMFileName)==T_FALSE)
        {
         if (current_path!=NULL)
         {
          change_directory(current_path);
          free(current_path);
          current_path=NULL;
         }
        }
        if((pfSystemRAM=fopen(pcRAMFileName,"rb"))==NULL)
        {
            fDebug(VERROR,("fSystemRAMLoad() Couldnt open file \"%s\"",pcRAMFileName));
            bRetVal=T_FALSE;
        }
        else
        {
            fDebug(MED,("fSystemRAMLoad() \"%s\" opened O.K",pcRAMFileName));

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

            tLoop=SYSTEM_RAM_BASE;

            while(tLoop<=SYSTEM_RAM_TOP && fread(&tData,sizeof(T_UBYTE),1,pfSystemRAM)==1)
            {
                f6809AddressWrite((T_UWORD)tLoop++,tData);
            }
            fDebug(MED,("fSystemRAMLoad() Loaded %d Bytes",tLoop-SYSTEM_RAM_BASE));

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

    /* All finished */
    return(bRetVal);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemRAMSave()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Open a file on disk, write the contents of the system RAM */
/*                 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 fSystemRAMSave(T_PUCHAR pcRAMFileName)
{
    FILE  *pfSystemRAM=NULL;
    T_UWORD tLoop;
    T_UBYTE tData;

    /* Try and open the RAM image file */

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

    /* Now Save SYSTEM_RAM_SIZE bytes */

    tLoop=SYSTEM_RAM_BASE;

    while(tLoop<SYSTEM_RAM_BASE+SYSTEM_RAM_SIZE)
    {
        tData=fSystemRAMRead(tLoop++);
        if(fwrite(&tData,sizeof(T_UBYTE),1,pfSystemRAM)==0)
        {
            fclose(pfSystemRAM);
            if (current_path!=NULL)
            {
             change_directory(current_path);
             free(current_path);
             current_path=NULL;
            }
            fDebug(VERROR,("fSystemRAMSave() File write error, aborting save"));
            return(T_FALSE);
        }
    }
    fDebug(MED,("fSystemRAMSave() Saved %d Bytes",tLoop-SYSTEM_RAM_BASE));

    fclose(pfSystemRAM);
    if (current_path!=NULL)
    {
     change_directory(current_path);
     free(current_path);
     current_path=NULL;
    }
    /* All finished */
    return(T_TRUE);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemRAMRead()                                          */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Read a value fRAM the RAM 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_UBYTE fSystemRAMRead(T_UWORD tAddress)
{
 fDebug(LOW,("fSystemRAMRead"));
 return(atSystemImage[tAddress]);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fSystemRAMWrite()                                         */
/*                                                                           */
/*   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 RAM write       */
/*                 enable flag is T_TRUE.                                      */
/*                                                                           */
/*   Accepts     : WORD Address and a BYTE of Data                           */
/*                                                                           */
/*   Returns     : BYTE of Data                                              */
/*                                                                           */
/*****************************************************************************/

T_UBYTE fSystemRAMWrite(T_UWORD tAddress,T_UBYTE tData)
{
    atSystemImage[tAddress]=tData;
    return(tData);
}

#endif //#ifndef _NO_DEBUG_INFORMATION_
