/*

  This is a part of the Project Frontier's Source code.

  Copyright (C) 1997-98 Francis Gastellu
                    aka Lone Runner/Aegis

  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.

*/
/*

Swaps a PPE to disk/XMS

*/
#include <mem.h>
#include <string.h>
#include <malloc.h>

#include "..\lang\ppl.h"
#include "..\lang\fortify.h"
#include "..\com\xms\xms.h"
#include "..\com\ppeswap.h"
#include "..\com\pcbdat.h"
#include "..\lang\vfs.h"

#define XMS_INC 32
#define SWAPFILE_INC 32

#define ALLOCATED_INC 64

#define SWAP_XMS 1
#define SWAP_DISK 0

typedef struct {
	char scriptName[256];
    long scriptSize;
    long scriptPtr;
    int scriptMode;
	} saveStruct;

XMS **xmspointer=NULL;
int far XMSsize=0;
int far XMSpos=0;

char **swapFile=NULL;
int far swapFileSize=0;
int far swapFilePos=0;

extern int swapType;
extern int nVars;                                     // n of vars
extern int globalNVars;                               // n of vars (never modified)
extern int nalloc;                                    // n of allocated
extern pplvar **baseallocated;                        // ptr on base of allocated vars table
extern pplvar **allocated;                            // ptr on allocated vars
extern pplvar **baseallocated;                        // ptr on base of allocated vars table
extern int maxAlloc;                                  // current size of allocated
extern int baseMaxAlloc;                              // current size of baseallocated

// -------------------------------------------------------------------------

void fppe_swapPPE(void)
{
saveStruct save;
FILE *stream;
int dec;
int c;
char **ptr;
int a;
int b;
int strType;
pplvar *s;
int elems;

switch (swapType)
	{
    case SWAP_XMS:

		while (XMSpos+1 > XMSsize)
	        {
            st_Disabled=1;
            XMSsize += XMS_INC;
            if (xmspointer == NULL)
    	        xmspointer = (XMS **)malloc(XMSsize+1 * sizeof(XMS*));
            else
	            xmspointer = (XMS **)realloc(xmspointer, XMSsize+1 * sizeof(XMS*));
            st_Disabled=0;
            }
        xmspointer[++XMSpos] = new XMS(((script->size+sizeof(saveStruct)+256)& ~1) + 4);

        strcpy(save.scriptName, script->filename);
        save.scriptSize = script->size;
        save.scriptPtr = script->ptr;
        save.scriptMode = script->mode;

        XMS::copy (xmspointer[XMSpos]->at(0), &save, sizeof(saveStruct));
        XMS::copy (xmspointer[XMSpos]->at(sizeof(saveStruct)), script->data, (script->size & ~1) + 2);

    	break;

    case SWAP_DISK:

		while (swapFilePos+1 > swapFileSize)
	        {
            st_Disabled=1;
            swapFileSize += SWAPFILE_INC;
            if (swapFile == NULL)
    	        swapFile = (char **)malloc(swapFileSize+1 * sizeof(char *));
            else
	            swapFile = (char **)realloc(swapFile, swapFileSize+1 * sizeof(char *));
            st_Disabled=0;
            }
        strcpy(tmpStr2, tempFilesPath);
        if (tmpStr2[strlen(tmpStr2)-1] != '\\') strcat(tmpStr2, "\\");
        tmpnam(&tmpStr2[strlen(tmpStr2)]);
        swapFile[++swapFilePos] = (char *)malloc(strlen(tmpStr2)+1);
        strcpy(swapFile[swapFilePos], tmpStr2);

        strcpy(save.scriptName, script->filename);
        save.scriptSize = script->size;
        save.scriptPtr = script->ptr;
        save.scriptMode = script->mode;

		if ((stream = fopen(swapFile[swapFilePos],"wb")) == NULL)
        	{
			fppe_runtimeError("SWAP ERROR!");
            exit(-1);
            }
        fwrite(&save, sizeof(saveStruct), 1, stream);
        fwrite(script->data, script->size + 2, 1, stream);


/*
        // VARS
	    dec = allocated - baseallocated;
        fwrite(&dec, 2, 1, stream);

		fwrite(&nVars, 2, 1, stream);
        fwrite(&nalloc, 2, 1, stream);
        fwrite(&globalNVars, 2, 1, stream);
        fwrite(&maxAlloc, 2, 1, stream);
        fwrite(&baseMaxAlloc, 2, 1, stream);

        for (c=0;c<globalNVars+nalloc;c++)
        	{
            s = baseallocated[c];
			fwrite(s, sizeof(pplvar), 1, stream);

			if (fppe_isStr(s))
			   	{
                if (s->nDim != 0)
                	{
			        elems = (s->dim[0]+1)*(s->dim[1]+1)*(s->dim[2]+1) -1;
				    ptr = (char**)s->value;
                	}
                else
                	{
                    elems = 0;
                    ptr = (char **)&s->value;
                    }
                strType = s->type;
				for (a = 0; a <= elems; a++)
                	{
                    switch (strType)
                    	{
                        case 7:
		                    b = *ptr[a];
                            fwrite(&b, 2, 1, stream);
                            fwrite(ptr[a], b+1, 1, stream);
                            break;
                        case 0xD:
                        	b = 2048;
                            fwrite(&b, 2, 1, stream);
                            fwrite(ptr[a], b, 1, stream);
                            break;
                        }
				    if (s->nDim != 0) free(ptr[a]);
                    }
			    }
			if (s->name != NULL) free(s->name);
			free(s->value);
			free(s);
            }

/*if (nVars+nalloc > maxAlloc-1)
	{
    dec = allocated - baseallocated;
    baseMaxAlloc += ALLOCATED_INC;
    maxAlloc += ALLOCATED_INC;
	baseallocated = realloc(baseallocated, sizeof(pplvar *)*baseMaxAlloc);
    allocated = baseallocated + dec;
    }

allocated[nVars+nalloc] = s;
s->tableElement = NULL;
nalloc++;
if (type != 7 && type != 0xD)
	// fppe_setValue(s,0);
    memset(s->value, 0, fppe_sizeofType(s->type));
s->name = NULL;
s->identHdr=0;
return s;




s = (pplvar *)calloc(sizeof(pplvar),1);*/

*/

        fclose(stream);

    	break;
    }


vfs_fclose(script);
}

// -------------------------------------------------------------------------

void fppe_restorePPE(void)
{
saveStruct save;
FILE *stream;

int dec;
int c;
char **ptr;
int a;
int b;
int strType;
pplvar *s;
int elems;

script = (vfs_file *)farmalloc(sizeof(vfs_file));

switch (swapType)
	{
    case SWAP_XMS:

		XMS::copy (&save, xmspointer[XMSpos]->at(0), sizeof(saveStruct));

		strcpy(script->filename, save.scriptName);
		script->data = (char *)malloc((save.scriptSize & ~1) + 4);
		script->size = save.scriptSize;
		script->ptr = save.scriptPtr;
		script->mode = save.scriptMode;
		script->limit = 0;

		XMS::copy (script->data, xmspointer[XMSpos]->at(sizeof(saveStruct)), (script->size & ~1) + 2);

		delete xmspointer[XMSpos--];

        break;

    case SWAP_DISK:

		if ((stream = fopen(swapFile[swapFilePos],"rb")) == NULL)
        	{
			fppe_runtimeError("SWAP ERROR!");
            exit(-1);
            }

        fread(&save, sizeof(saveStruct), 1, stream);

		strcpy(script->filename, save.scriptName);
		script->data = (char *)malloc((save.scriptSize & ~1) + 4);
		script->size = save.scriptSize;
		script->ptr = save.scriptPtr;
		script->mode = save.scriptMode;
		script->limit = 0;

        fread(script->data, script->size + 2, 1, stream);



/*
        // VARS
        fread(&dec, 2, 1, stream);

		fread(&nVars, 2, 1, stream);
        fread(&nalloc, 2, 1, stream);
        fread(&globalNVars, 2, 1, stream);
        fread(&maxAlloc, 2, 1, stream);
        fread(&baseMaxAlloc, 2, 1, stream);

		baseallocated = (pplvar **)calloc(sizeof(pplvar *)*baseMaxAlloc, 0);
	    allocated = baseallocated + dec;

        for (c=0;c<globalNVars+nalloc;c++)
        	{
			s = (pplvar *)calloc(sizeof(pplvar),1);
            fread(&s, sizeof(pplvar), 1, stream);

			fppe_allocValue(s);
			allocated[c] = s;

			if (s->type != 7 && s->type != 0xD)
			    memset(s->value, 0, fppe_sizeofType(s->type));

			if (fppe_isStr(s))
			   	{
                if (s->nDim != 0)
                	{
			        elems = (s->dim[0]+1)*(s->dim[1]+1)*(s->dim[2]+1) -1;
				    ptr = (char**)s->value;
                	}
                else
                	{
                    elems = 0;
                    ptr = (char **)&s->value;
                    }
                strType = s->type;
				for (a = 0; a < elems; a++)
                	{
                    switch (strType)
                    	{
                        case 7:
		                    b = *ptr[a];
                            fwrite(&b, 2, 1, stream);
                            fwrite(&ptr[a], b+1, 1, stream);
                            break;
                        case 0xD:
                        	b = 2048;
                            fwrite(&b, 2, 1, stream);
                            fwrite(&ptr[a], b, 1, stream);
                            break;
                        }
				    free(ptr[a]);
                    }
			    }
			if (s->name != NULL) free(s->name);
			free(s->value);
			free(s);
            }

*/

        fclose(stream);
        unlink(swapFile[swapFilePos]);

		free(swapFile[swapFilePos--]);

        break;

    }
}

void xmsCloseUp(void)
{
if (swapType == SWAP_XMS)
	{
    st_Disabled=1;
    if (xmspointer != NULL) free(xmspointer);
    st_Disabled=0;
    }
}
