mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-13 18:02:01 -04:00
165 lines
2.9 KiB
C
165 lines
2.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <memman.h>
|
|
#include <string.h>
|
|
#include "setupcpy.h"
|
|
|
|
#define DATASIZE 32768
|
|
#define INFOBLOCK 1
|
|
#define DATABLOCK 2
|
|
#define ERRORBLOCK 3
|
|
|
|
typedef struct tdatablock
|
|
{
|
|
void *next;
|
|
char block_type;
|
|
unsigned short load_size;
|
|
char data[DATASIZE];
|
|
}TDATABLOCK;
|
|
|
|
typedef struct tinfoblock
|
|
{
|
|
void *next;
|
|
char block_type;
|
|
char pathname[2];
|
|
}TINFOBLOCK;
|
|
|
|
static void *start=NULL;
|
|
static void *end=NULL;
|
|
static FILE *cpyout=NULL;
|
|
static long progress=0;
|
|
|
|
void (*cpy_error)(int,char *);
|
|
void (*mem_error_next)(long);
|
|
|
|
void (*cpy_progress)(long);
|
|
|
|
|
|
static void *alloc_file(char *target_name)
|
|
{
|
|
TINFOBLOCK *p;
|
|
|
|
p=(TINFOBLOCK *)getmem(sizeof(TINFOBLOCK)+strlen(target_name));
|
|
strcpy(p->pathname,target_name);
|
|
p->next=NULL;
|
|
p->block_type=INFOBLOCK;
|
|
return p;
|
|
}
|
|
|
|
static void *alloc_data()
|
|
{
|
|
TDATABLOCK *p;
|
|
|
|
p=New(TDATABLOCK);
|
|
p->next=NULL;
|
|
p->load_size=0;
|
|
p->block_type=DATABLOCK;
|
|
return p;
|
|
}
|
|
|
|
|
|
static void *load_data(FILE *f)
|
|
{
|
|
TDATABLOCK *p;
|
|
int rc;
|
|
int retry=0;
|
|
void *end_line;
|
|
|
|
p=end_line=alloc_data();
|
|
again:
|
|
errno=0;
|
|
rc=fread(p->data,1,sizeof(p->data),f);
|
|
p->load_size=rc;
|
|
if (ferror(f) || rc!=sizeof(p->data) && errno!=0)
|
|
{
|
|
if (retry) retry--;
|
|
else cpy_error(CPERR_READ,NULL);
|
|
fseek(f,-rc,SEEK_CUR);
|
|
errno=0;
|
|
goto again;
|
|
}
|
|
progress+=p->load_size;
|
|
cpy_progress(progress);
|
|
return end_line;
|
|
}
|
|
|
|
static error_mem(long size)
|
|
{
|
|
TDATABLOCK *p;
|
|
TINFOBLOCK *q;
|
|
int rc;
|
|
|
|
size;
|
|
if (start==NULL) mem_error_next(size);
|
|
while (start!=NULL)
|
|
{
|
|
p=start;
|
|
q=start;
|
|
if (q->block_type==INFOBLOCK)
|
|
{
|
|
if (cpyout!=NULL) fclose(cpyout);
|
|
again:
|
|
cpyout=fopen(q->pathname,"wb");
|
|
if (cpyout==NULL)
|
|
{
|
|
cpy_error(CPERR_OPEN,q->pathname);
|
|
goto again;
|
|
}
|
|
start=q->next;
|
|
free(q);
|
|
}
|
|
else if (p->block_type==DATABLOCK)
|
|
{
|
|
again2:
|
|
rc=fwrite(p->data,1,p->load_size,cpyout);
|
|
if (rc!=p->load_size)
|
|
{
|
|
cpy_error(CPERR_WRITE,q->pathname);
|
|
fseek(cpyout,-rc,SEEK_CUR);
|
|
goto again2;
|
|
}
|
|
progress+=p->load_size;
|
|
cpy_progress(progress);
|
|
start=p->next;
|
|
free(p);
|
|
}
|
|
}
|
|
end=NULL;
|
|
}
|
|
|
|
void cpy_file(char *source,char *target)
|
|
{
|
|
FILE *f;
|
|
TDATABLOCK *p;
|
|
TINFOBLOCK *q;
|
|
|
|
again:
|
|
errno=0;
|
|
f=fopen(source,"rb");
|
|
if (f==NULL)
|
|
{
|
|
cpy_error(CPERR_OPEN,source);
|
|
goto again;
|
|
}
|
|
q=alloc_file(target);
|
|
if (start==NULL) start=end=q;else end=(((TDATABLOCK *)end)->next=q);
|
|
while (!feof(f))
|
|
{
|
|
p=load_data(f);
|
|
if (start==NULL) start=end=p;else end=(((TDATABLOCK *)end)->next=p);
|
|
}
|
|
fclose(f);
|
|
}
|
|
|
|
void cpy_flush()
|
|
{
|
|
if (start!=NULL)error_mem(0);
|
|
if (cpyout!=NULL)fclose(cpyout);
|
|
cpyout=NULL;
|
|
}
|
|
|
|
void install_cpy()
|
|
{
|
|
mem_error_next=mem_error;
|
|
mem_error=error_mem;
|
|
}
|