Files
HxCFloppyEmulator/libhxcfe/sources/floppy_loader.c
T

2616 lines
68 KiB
C

/*
//
// Copyright (C) 2006-2025 Jean-François DEL NERO
//
// This file is part of the HxCFloppyEmulator library
//
// HxCFloppyEmulator may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// HxCFloppyEmulator 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.
//
// HxCFloppyEmulator 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 HxCFloppyEmulator; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
*/
///////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------//
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
//----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------//
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
//-------------------------------------------------------------------------------//
//----------------------------------------------------- http://hxc2001.free.fr --//
///////////////////////////////////////////////////////////////////////////////////
// File : floppy_loader.c
// Contains: Library interface functions
//
// Written by: Jean-François DEL NERO
//
// Change History (most recent first):
///////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "types.h"
#include "internal_libhxcfe.h"
#include "tracks/track_generator.h"
#include "floppy_builder.h"
#include "libhxcfe.h"
#include "floppy_loader.h"
#include "floppy_utils.h"
#include "loaders_list.h"
#include "tracks/std_crc32.h"
#include "version.h"
#include "licensetxt.h"
#include "plugins_id.h"
#include "libhxcadaptor.h"
#include "misc/env.h"
#include "misc/script_exec.h"
#include "init_script.h"
#include "xml_disk/packer/pack.h"
#include "tracks/track_types_defs.h"
int dummy_output(int MSGTYPE,const char * chaine, ...)
{
return 0;
}
int dummy_trackpos(unsigned int current,unsigned int total)
{
return 0;
}
int dummy_progress(unsigned int current,unsigned int total, void * user)
{
return 0;
}
////////////////////////////////////////////////////////////////////////
HXCFE* hxcfe_init(void)
{
HXCFE* hxcfe;
HXCFE_IMGLDR *imgldr_ctx;
image_plugin* plugin_ptr;
char * savefilepath;
int nb_loader;
int nb_xml_loader;
int i,j;
int ret;
unsigned char * init_script_buf;
init_script_buf = NULL;
hxcfe = calloc( 1 ,sizeof(HXCFE) );
if( hxcfe )
{
hxcfe->hxc_printf = &dummy_output;
hxcfe->hxc_settrackpos = &dummy_trackpos;
hxcfe->envvar = initEnv( NULL, NULL );
hxcfe_setEnvVar(hxcfe, "LIBVERSION", "v"STR_FILE_VERSION2);
if ( hxcfe_initScript(hxcfe) != HXCFE_NOERROR )
goto init_error;
hxcfe->hxc_printf(MSG_INFO_0,"Starting HxCFloppyEmulator...");
init_script_buf = data_unpack(data_init_script->data,data_init_script->csize,0,data_init_script->size);
if(init_script_buf)
{
if( hxcfe_execScriptRam(hxcfe, init_script_buf, data_init_script->size) != HXCFE_NOERROR )
goto init_error;
free( init_script_buf );
}
#if defined(WIN32)
hxcfe_execScriptLine( hxcfe, "set SPSCAPS_LIB_NAME CAPSImg.dll" );
#elif __APPLE__
hxcfe_execScriptLine( hxcfe, "set SPSCAPS_LIB_NAME @rpath/CAPSImage.framework/CAPSImage,@rpath/CAPSImg.framework/CAPSImg" );
#else
hxcfe_execScriptLine( hxcfe, "set SPSCAPS_LIB_NAME libcapsimage.so.5,libcapsimage.so.5.1,libcapsimage.so" );
#endif
hxcfe_execScriptFile(hxcfe, "config.script");
savefilepath = hxcfe_getEnvVar( hxcfe, "UISTATE_SAVE_FILE", 0 );
if(savefilepath)
{
if(strlen(savefilepath))
{
hxcfe_execScriptFile(hxcfe, savefilepath);
}
else
{
hxcfe_execScriptLine( hxcfe, "set UISTATE_SAVE_FILE laststate.script" );
savefilepath = hxcfe_getEnvVar( hxcfe, "UISTATE_SAVE_FILE", 0 );
hxcfe_execScriptFile(hxcfe, savefilepath);
}
}
nb_loader = 0;
// Count how many static loaders we have.
while( staticplugins[nb_loader] )
{
nb_loader++;
}
nb_xml_loader = 0;
imgldr_ctx = hxcfe_imgInitLoader(hxcfe);
if( imgldr_ctx )
{
ret = staticplugins[nb_loader - 1](imgldr_ctx,GETNBSUBLOADER,&nb_xml_loader);
if( ret != HXCFE_NOERROR )
{
nb_xml_loader = 0;
hxcfe->hxc_printf(MSG_ERROR,"XML Loader unavailable...");
}
}
if( nb_loader )
{
hxcfe->image_handlers = (void*)calloc( 1, (nb_loader+nb_xml_loader+1) * sizeof(image_plugin) );
if( hxcfe->image_handlers )
{
plugin_ptr = (image_plugin*)hxcfe->image_handlers;
for( i = 0 ; i < nb_loader - 1; i++ )
{
plugin_ptr[i].infos_handler = staticplugins[i];
plugin_ptr[i].sub_id = 0;
plugin_ptr[i].flags = 0x00000000;
}
for( j = 0 ; j < nb_xml_loader; j++ )
{
plugin_ptr[i + j].infos_handler = staticplugins[nb_loader - 1];
plugin_ptr[i + j].sub_id = j + 1;
plugin_ptr[i + j].flags = IMAGE_LDR_DISABLED;
}
}
else
{
if( imgldr_ctx )
hxcfe_imgDeInitLoader(imgldr_ctx);
free( hxcfe );
return NULL;
}
}
if( imgldr_ctx )
hxcfe_imgDeInitLoader(imgldr_ctx);
}
return hxcfe;
init_error:
free( hxcfe );
free( init_script_buf );
return NULL;
}
int32_t hxcfe_setOutputFunc( HXCFE* floppycontext, HXCFE_PRINTF_FUNC hxc_printf )
{
floppycontext->hxc_printf=hxc_printf;
return HXCFE_NOERROR;
}
const char * hxcfe_getVersion(HXCFE* floppycontext)
{
return STR_FILE_VERSION2;
}
const char * hxcfe_getLicense(HXCFE* floppycontext)
{
if(floppycontext)
{
if(!floppycontext->license)
{
floppycontext->license = (char*)data_unpack(data_COPYING_FULL->data,data_COPYING_FULL->csize,0,data_COPYING_FULL->size + 1);
floppycontext->license[data_COPYING_FULL->size] = 0;
}
return (char*)floppycontext->license;
}
return NULL;
}
void hxcfe_deinit(HXCFE* hxcfe)
{
if( hxcfe )
{
hxcfe->hxc_printf(MSG_INFO_0,"Stopping HxCFloppyEmulator...");
hxcfe_deinitScript(hxcfe);
free( hxcfe->image_handlers );
free( hxcfe->license );
free( hxcfe );
}
}
////////////////////////////////////////////////////////////////////////
static int32_t hxcfe_checkLoaderID( HXCFE_IMGLDR * imgldr_ctx, int32_t moduleID )
{
int i;
image_plugin* plugin_ptr;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
if( moduleID >= 0 )
{
i=0;
do
{
i++;
}while( plugin_ptr[i].infos_handler && i<moduleID);
if( !plugin_ptr[i].infos_handler )
{
return HXCFE_BADPARAMETER;
}
else
{
return HXCFE_NOERROR;
}
}
else
{
return HXCFE_BADPARAMETER;
}
}
int32_t hxcfe_imgGetNumberOfLoader( HXCFE_IMGLDR * imgldr_ctx )
{
int i;
image_plugin* plugin_ptr;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
i=0;
do
{
i++;
}while( plugin_ptr[i].infos_handler );
return i;
}
int32_t hxcfe_imgGetLoaderID( HXCFE_IMGLDR * imgldr_ctx, char * container )
{
int i;
int ret;
char * plugin_id;
image_plugin* plugin_ptr;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
ret=0;
i=0;
do
{
if( plugin_ptr[i].infos_handler )
{
ret = plugin_ptr[i].infos_handler(imgldr_ctx,GETPLUGINID,&plugin_id);
if((ret==HXCFE_NOERROR) && !strcmp(container,plugin_id))
{
return i;
}
}
i++;
}while( plugin_ptr[i].infos_handler );
imgldr_ctx->hxcfe->hxc_printf(MSG_DEBUG,"hxcfe_searchContainer : Plugin %s not found !",container);
return -1;
}
int32_t hxcfe_imgGetLoaderAccess( HXCFE_IMGLDR * imgldr_ctx, int32_t moduleID )
{
int ret;
plugins_ptr func_ptr;
image_plugin* plugin_ptr;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
ret = 0;
if(hxcfe_checkLoaderID(imgldr_ctx,moduleID)==HXCFE_NOERROR)
{
ret=plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if(ret==HXCFE_NOERROR)
{
imgldr_ctx->selected_id = moduleID;
imgldr_ctx->selected_subid = 0;
if(func_ptr.libLoad_DiskFile)
ret=ret | 0x01;
if(func_ptr.libWrite_DiskFile)
ret=ret | 0x02;
return ret;
}
}
else
{
imgldr_ctx->hxcfe->hxc_printf(MSG_ERROR,"Bad module ID : %x !",moduleID);
}
return ret;
}
const char* hxcfe_imgGetLoaderDesc( HXCFE_IMGLDR * imgldr_ctx, int32_t moduleID )
{
int ret;
plugins_ptr func_ptr;
char * desc;
image_plugin* plugin_ptr;
int sub_id;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
if(hxcfe_checkLoaderID(imgldr_ctx,moduleID)==HXCFE_NOERROR)
{
ret = plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if(ret==HXCFE_NOERROR)
{
imgldr_ctx->selected_id = moduleID;
imgldr_ctx->selected_subid = 0;
if( !plugin_ptr[moduleID].sub_id)
{
plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETDESCRIPTION,&desc);
}
else
{
sub_id = plugin_ptr[moduleID].sub_id;
if( plugin_ptr[moduleID].infos_handler(imgldr_ctx,SELECTSUBLOADER,&sub_id) == HXCFE_NOERROR )
{
plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETDESCRIPTION,&desc);
}
else
{
return 0;
}
}
return desc;
}
}
else
{
imgldr_ctx->hxcfe->hxc_printf(MSG_ERROR,"Bad module ID : %x !",moduleID);
}
return 0;
}
const char* hxcfe_imgGetLoaderName( HXCFE_IMGLDR * imgldr_ctx, int32_t moduleID )
{
int ret;
plugins_ptr func_ptr;
char * desc;
image_plugin* plugin_ptr;
int sub_id;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
if(hxcfe_checkLoaderID(imgldr_ctx,moduleID)==HXCFE_NOERROR)
{
ret = plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if(ret==HXCFE_NOERROR)
{
imgldr_ctx->selected_id = moduleID;
imgldr_ctx->selected_subid = 0;
if( !plugin_ptr[moduleID].sub_id)
{
plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETPLUGINID,&desc);
}
else
{
sub_id = plugin_ptr[moduleID].sub_id;
if( plugin_ptr[moduleID].infos_handler(imgldr_ctx,SELECTSUBLOADER,&sub_id) == HXCFE_NOERROR )
{
plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETPLUGINID,&desc);
}
else
{
return 0;
}
}
return desc;
}
}
else
{
imgldr_ctx->hxcfe->hxc_printf(MSG_ERROR,"Bad module ID : %x !",moduleID);
}
return 0;
}
const char* hxcfe_imgGetLoaderExt( HXCFE_IMGLDR * imgldr_ctx, int32_t moduleID )
{
int ret;
plugins_ptr func_ptr;
char * desc;
image_plugin* plugin_ptr;
int sub_id;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
if(hxcfe_checkLoaderID(imgldr_ctx,moduleID)==HXCFE_NOERROR)
{
ret = plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if(ret==HXCFE_NOERROR)
{
imgldr_ctx->selected_id = moduleID;
imgldr_ctx->selected_subid = 0;
if( !plugin_ptr[moduleID].sub_id)
{
plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETEXTENSION,&desc);
}
else
{
sub_id = plugin_ptr[moduleID].sub_id;
if( plugin_ptr[moduleID].infos_handler(imgldr_ctx,SELECTSUBLOADER,&sub_id) == HXCFE_NOERROR )
{
plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETEXTENSION,&desc);
}
else
{
return 0;
}
}
return desc;
}
}
else
{
imgldr_ctx->hxcfe->hxc_printf(MSG_ERROR,"Bad module ID : %x !",moduleID);
}
return 0;
}
int32_t hxcfe_imgCheckFileCompatibility( HXCFE_IMGLDR * imgldr_ctx, HXCFE_IMGLDR_FILEINFOS * file_infos, char * loadername, char * fileext, int filesizemod)
{
char temp_ext[16];
int ret;
int i,j;
if(loadername)
imgldr_ctx->hxcfe->hxc_printf(MSG_DEBUG,"%s", loadername);
if( fileext )
{
j = 0;
do
{
memset(temp_ext,0,sizeof(temp_ext));
i = 0;
while ( i < sizeof(temp_ext) - 1 && fileext[j] != ',' && fileext[j] )
{
temp_ext[i] = fileext[j];
j++;
i++;
}
if(fileext[j] == ',')
j++;
ret = hxc_checkfileext( file_infos->path, temp_ext, SYS_PATH_TYPE );
}while(fileext[j] && !ret);
if( !ret )
return HXCFE_BADFILE;
}
if( filesizemod )
{
if( ( file_infos->file_size % filesizemod ) || (file_infos->file_size <= 0) )
{
return HXCFE_BADFILE;
}
}
imgldr_ctx->hxcfe->hxc_printf(MSG_DEBUG,"%s : %s is an %s file !", loadername, file_infos->path,fileext);
return HXCFE_VALIDFILE;
}
int32_t hxcfe_preloadImgInfos(HXCFE_IMGLDR * imgldr_ctx, char * imgname, HXCFE_IMGLDR_FILEINFOS * file_infos)
{
FILE *f;
struct stat img_stat;
memset(file_infos,0,sizeof(HXCFE_IMGLDR_FILEINFOS));
memset(&img_stat,0,sizeof(struct stat));
hxc_stat( imgname, &img_stat );
if(img_stat.st_mode&S_IFDIR)
file_infos->is_dir = 1;
else
file_infos->is_dir = 0;
file_infos->file_size = 0;
if(!file_infos->is_dir)
{
f = hxc_fopen(imgname,"rb");
if( f == NULL )
return HXCFE_ACCESSERROR;
file_infos->file_size = hxc_fgetsize(f);
hxc_fread(&file_infos->file_header,sizeof(file_infos->file_header),f);
hxc_fclose(f);
}
strncpy(file_infos->file_extension, hxc_getfilenameext( imgname, 0, SYS_PATH_TYPE ), sizeof(file_infos->file_extension)-1);
file_infos->file_extension[sizeof(file_infos->file_extension)-1] = 0;
strncpy(file_infos->path, imgname, sizeof(file_infos->path));
file_infos->path[sizeof(file_infos->path)-1] = 0;
return HXCFE_NOERROR;
}
int32_t hxcfe_imgAutoSetectLoader( HXCFE_IMGLDR * imgldr_ctx, char* imgname, int32_t moduleID )
{
int i;
int ret;
plugins_ptr func_ptr;
HXCFE* hxcfe;
image_plugin* plugin_ptr;
HXCFE_IMGLDR_FILEINFOS file_infos;
ret = HXCFE_BADPARAMETER;
if( imgldr_ctx )
{
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
hxcfe = imgldr_ctx->hxcfe;
hxcfe->hxc_printf(MSG_INFO_0,"Checking %s",imgname);
ret = hxcfe_preloadImgInfos(imgldr_ctx, imgname, &file_infos);
if(ret != HXCFE_NOERROR)
return ret;
ret = HXCFE_BADPARAMETER;
i = moduleID;
do
{
if(plugin_ptr[i].infos_handler && !(plugin_ptr[i].flags & IMAGE_LDR_DISABLED) )
{
ret = plugin_ptr[i].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if( ret == HXCFE_NOERROR )
{
if(func_ptr.libIsValidDiskFile)
{
ret = func_ptr.libIsValidDiskFile(imgldr_ctx,&file_infos);
if(ret == HXCFE_VALIDFILE)
{
hxcfe->hxc_printf(MSG_INFO_0,"File loader found : %s (%s)",hxcfe_imgGetLoaderName(imgldr_ctx,i),hxcfe_imgGetLoaderDesc(imgldr_ctx,i));
return i;
}
else
{
hxcfe->hxc_printf(MSG_DEBUG,"libIsValidDiskFile n%d return %d",i,ret);
}
}
}
}
i++;
}while( plugin_ptr[i].infos_handler );
hxcfe->hxc_printf(MSG_ERROR,"No loader support the file %s !",imgname);
ret = HXCFE_UNSUPPORTEDFILE;
}
return ret;
}
int32_t hxcfe_imgSetProgressCallback( HXCFE_IMGLDR * imgldr_ctx, HXCFE_IMGLDRPROGRESSOUT_FUNC progress_func, void * userdata )
{
if(imgldr_ctx)
{
if(progress_func)
{
imgldr_ctx->progress_userdata = userdata;
imgldr_ctx->hxc_setprogress = progress_func;
}
}
return 0;
}
int32_t hxcfe_imgCallProgressCallback( HXCFE_IMGLDR * imgldr_ctx, int32_t cur, int32_t max )
{
if(imgldr_ctx)
{
if(imgldr_ctx->hxc_setprogress)
{
imgldr_ctx->hxc_setprogress(cur,max,imgldr_ctx->progress_userdata);
}
}
return 0;
}
HXCFE_IMGLDR * hxcfe_imgInitLoader(HXCFE * hxcfe)
{
HXCFE_IMGLDR * imgldr_ctx;
imgldr_ctx = calloc( 1, sizeof(HXCFE_IMGLDR));
if(imgldr_ctx)
{
imgldr_ctx->hxcfe = hxcfe;
imgldr_ctx->hxc_setprogress=&dummy_progress;
}
return imgldr_ctx;
}
void hxcfe_imgDeInitLoader(HXCFE_IMGLDR * imgldr_ctx)
{
free( imgldr_ctx );
return;
}
HXCFE_FLOPPY * hxcfe_imgLoadEx( HXCFE_IMGLDR * imgldr_ctx, char* imgname, int32_t moduleID, int32_t * err_ret, void * parameters )
{
int ret;
HXCFE* hxcfe;
HXCFE_FLOPPY * newfloppy;
plugins_ptr func_ptr;
image_plugin* plugin_ptr;
HXCFE_IMGLDR_FILEINFOS file_infos;
newfloppy = 0;
if(imgldr_ctx)
{
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
hxcfe = imgldr_ctx->hxcfe;
hxcfe->hxc_printf(MSG_INFO_0,"Loading %s",imgname);
ret = hxcfe_preloadImgInfos(imgldr_ctx, imgname, &file_infos);
if(ret != HXCFE_NOERROR)
{
if(err_ret)
*err_ret = ret;
return 0;
}
if( hxcfe_checkLoaderID(imgldr_ctx,moduleID) == HXCFE_NOERROR )
{
ret = plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if( ret == HXCFE_NOERROR )
{
ret = func_ptr.libIsValidDiskFile(imgldr_ctx,&file_infos);
if( ret == HXCFE_VALIDFILE )
{
newfloppy = calloc( 1, sizeof(HXCFE_FLOPPY) );
if(newfloppy)
{
hxcfe->hxc_printf(MSG_INFO_0,"file loader found!");
ret = func_ptr.libLoad_DiskFile(imgldr_ctx,newfloppy,imgname,parameters);
if(ret != HXCFE_NOERROR)
{
free( newfloppy );
newfloppy = NULL;
}
if(err_ret)
*err_ret = ret;
}
return newfloppy;
}
else
{
hxcfe->hxc_printf(MSG_ERROR,"%s refuse the file %s (%d)!",hxcfe_imgGetLoaderName(imgldr_ctx,moduleID),imgname,ret);
if(err_ret)
*err_ret=ret;
return newfloppy;
}
}
}
hxcfe->hxc_printf(MSG_ERROR,"Bad plugin ID : 0x%x",moduleID);
ret = HXCFE_BADPARAMETER;
if(err_ret)
*err_ret = ret;
}
return newfloppy;
}
HXCFE_FLOPPY * hxcfe_imgLoad(HXCFE_IMGLDR * imgldr_ctx, char* imgname, int32_t moduleID, int32_t * err_ret )
{
return hxcfe_imgLoadEx(imgldr_ctx,imgname,moduleID,err_ret,0);
}
int32_t hxcfe_imgUnload( HXCFE_IMGLDR * imgldr_ctx, HXCFE_FLOPPY * floppydisk )
{
return hxcfe_floppyUnload( imgldr_ctx->hxcfe, floppydisk );
}
int32_t hxcfe_imgExport( HXCFE_IMGLDR * imgldr_ctx, HXCFE_FLOPPY * newfloppy, char* imgname, int32_t moduleID )
{
int ret;
plugins_ptr func_ptr;
image_plugin* plugin_ptr;
plugin_ptr = (image_plugin*)imgldr_ctx->hxcfe->image_handlers;
if(hxcfe_checkLoaderID(imgldr_ctx,moduleID)==HXCFE_NOERROR)
{
ret=plugin_ptr[moduleID].infos_handler(imgldr_ctx->hxcfe,GETFUNCPTR,&func_ptr);
if(ret==HXCFE_NOERROR)
{
if(func_ptr.libWrite_DiskFile)
{
ret=func_ptr.libWrite_DiskFile(imgldr_ctx,newfloppy,imgname,0);
return ret;
}
else
{
imgldr_ctx->hxcfe->hxc_printf(MSG_ERROR,"No export support in %s!",hxcfe_imgGetLoaderName(imgldr_ctx,moduleID) );
return HXCFE_UNSUPPORTEDFILE;
}
}
}
imgldr_ctx->hxcfe->hxc_printf(MSG_ERROR,"Bad plugin ID : 0x%x",moduleID);
return HXCFE_BADPARAMETER;
}
int32_t hxcfe_freeFloppy( HXCFE* floppycontext, HXCFE_FLOPPY * floppydisk )
{
int i,j;
if(floppydisk)
{
if( floppydisk->tracks )
{
for(j=0;j<floppydisk->floppyNumberOfTrack;j++)
{
if( floppydisk->tracks[j] )
{
if( floppydisk->tracks[j]->sides )
{
for(i=0;i<floppydisk->floppyNumberOfSide;i++)
{
hxcfe_freeSide(floppycontext,floppydisk->tracks[j]->sides[i]);
floppydisk->tracks[j]->sides[i] = NULL;
}
free( floppydisk->tracks[j]->sides );
floppydisk->tracks[j]->sides = NULL;
}
free(floppydisk->tracks[j]);
floppydisk->tracks[j] = NULL;
}
}
free(floppydisk->tracks);
floppydisk->tracks = NULL;
}
}
return 0;
}
int32_t hxcfe_floppyUnload( HXCFE* floppycontext, HXCFE_FLOPPY * floppydisk )
{
hxcfe_freeFloppy( floppycontext, floppydisk );
free( floppydisk );
return 0;
}
HXCFE_FLOPPY * hxcfe_floppyDuplicate( HXCFE* floppycontext, HXCFE_FLOPPY * floppydisk )
{
int i,j;
HXCFE_FLOPPY * fp;
fp = NULL;
if(floppydisk)
{
fp = malloc(sizeof(HXCFE_FLOPPY));
if(fp)
{
memcpy(fp,floppydisk,sizeof(HXCFE_FLOPPY));
fp->tracks = (HXCFE_CYLINDER**)malloc(sizeof(HXCFE_CYLINDER*)*fp->floppyNumberOfTrack);
if(fp->tracks)
{
for(j=0;j<fp->floppyNumberOfTrack;j++)
{
fp->tracks[j] = (HXCFE_CYLINDER*)malloc(sizeof(HXCFE_CYLINDER));
if( fp->tracks[j] )
{
memcpy( fp->tracks[j], floppydisk->tracks[j], sizeof(HXCFE_CYLINDER) );
fp->tracks[j]->sides = (HXCFE_SIDE**)calloc( 1, sizeof(HXCFE_SIDE*)*fp->tracks[j]->number_of_side );
if(fp->tracks[j]->sides)
{
for(i=0;i<fp->tracks[j]->number_of_side;i++)
{
fp->tracks[j]->sides[i] = hxcfe_duplicateSide( floppycontext, floppydisk->tracks[j]->sides[i] );
}
}
}
}
}
}
}
return fp;
}
int32_t hxcfe_floppySectorBySectorCopy( HXCFE* floppycontext, HXCFE_FLOPPY * dest_floppy, HXCFE_FLOPPY * src_floppy, int dest_format_ref )
{
int i,j,l,len;
int32_t fdcstatus;
HXCFE_SECTORACCESS* ref_sect_access;
HXCFE_SECTORACCESS* src_sect_access;
HXCFE_SECTORACCESS* new_sect_access;
HXCFE_SECTCFG* sect_ref;
HXCFE_FLOPPY * ref_floppy;
unsigned char * sect_buf;
int types[]={ISOIBM_MFM_ENCODING,ISOIBM_FM_ENCODING,AMIGA_MFM_ENCODING,-1};
int type_index;
char tag_string[64+1];
int error_tag_value;
if(dest_format_ref)
{
ref_floppy = hxcfe_floppyDuplicate( floppycontext, dest_floppy );
}
else
{
ref_floppy = hxcfe_floppyDuplicate( floppycontext, src_floppy );
}
if(!ref_floppy)
return HXCFE_BADPARAMETER;
ref_sect_access = hxcfe_initSectorAccess( floppycontext, ref_floppy );
if(!ref_sect_access)
return HXCFE_BADPARAMETER;
new_sect_access = hxcfe_initSectorAccess( floppycontext, dest_floppy );
if(!new_sect_access)
return HXCFE_BADPARAMETER;
src_sect_access = hxcfe_initSectorAccess( floppycontext, src_floppy );
if(!src_sect_access)
return HXCFE_BADPARAMETER;
type_index = 0;
error_tag_value = hxcfe_getEnvVarValue( floppycontext, "SECTORBYSECTORCOPY_SECTOR_ERROR_TAG" );
while(types[type_index] != -1)
{
for(i=0;i<ref_floppy->floppyNumberOfTrack;i++)
{
for(j=0;j<ref_floppy->floppyNumberOfSide;j++)
{
hxcfe_resetSearchTrackPosition(ref_sect_access);
do
{
sect_ref = hxcfe_getNextSector( ref_sect_access, i, j, types[type_index]);
if(sect_ref)
{
hxcfe_readSectorData( src_sect_access, i, j, sect_ref->sector, 1, sect_ref->sectorsize, types[type_index], sect_ref->input_data, &fdcstatus );
sect_buf = NULL;
if(fdcstatus != FDC_NOERROR)
{
switch(fdcstatus)
{
case FDC_BAD_DATA_CRC:
snprintf(tag_string,sizeof(tag_string)-1,"<ERROR DATA_CRC T:%.3d H:%c S:%.3d>",i,'0'+(j&1),sect_ref->sector);
break;
case FDC_NO_DATA:
snprintf(tag_string,sizeof(tag_string)-1,"<ERROR NO_DATA T:%.3d H:%c S:%.3d>",i,'0'+(j&1),sect_ref->sector);
break;
case FDC_SECTOR_NOT_FOUND:
snprintf(tag_string,sizeof(tag_string)-1,"<ERROR NOTFOUND T:%.3d H:%c S:%.3d>",i,'0'+(j&1),sect_ref->sector);
break;
case FDC_ACCESS_ERROR:
snprintf(tag_string,sizeof(tag_string)-1,"<ERROR ACCESS T:%.3d H:%c S:%.3d>",i,'0'+(j&1),sect_ref->sector);
break;
}
floppycontext->hxc_printf(MSG_WARNING,"Source file sector error : %s", tag_string );
if(sect_ref->sectorsize > 0)
{
sect_buf = malloc(sect_ref->sectorsize + 1);
if(sect_buf)
{
if(error_tag_value >= 0)
memset(sect_buf,error_tag_value,sect_ref->sectorsize + 1);
else
memset(sect_buf,0,sect_ref->sectorsize + 1);
if(error_tag_value == -1)
{
len = strlen(tag_string);
if(len)
{
for(l=0;l<sect_ref->sectorsize / len;l++)
{
strcat((char*)sect_buf,tag_string);
}
}
}
}
}
}
if(sect_buf)
{
if(error_tag_value != -2)
hxcfe_writeSectorData( new_sect_access, i, j, sect_ref->sector, 1, sect_ref->sectorsize, types[type_index], sect_buf, &fdcstatus );
free(sect_buf);
}
else
{
hxcfe_writeSectorData( new_sect_access, i, j, sect_ref->sector, 1, sect_ref->sectorsize, types[type_index], sect_ref->input_data, &fdcstatus );
}
hxcfe_freeSectorConfigData( 0, sect_ref );
}
}while(sect_ref);
}
}
type_index++;
}
hxcfe_floppyUnload( floppycontext, ref_floppy );
hxcfe_deinitSectorAccess( ref_sect_access );
hxcfe_deinitSectorAccess( new_sect_access );
hxcfe_deinitSectorAccess( src_sect_access );
return HXCFE_NOERROR;
}
////////////////////////////////////////////////////////////////////////
int32_t hxcfe_floppyGetSetParams( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy, uint8_t dir, uint16_t param, void * value )
{
int ret;
ret=HXCFE_BADPARAMETER;
switch(dir)
{
case GET:
switch(param)
{
case DOUBLESTEP:
*((unsigned char*)value)=newfloppy->double_step;
ret=HXCFE_NOERROR;
break;
case INTERFACEMODE:
*((unsigned short*)value)=newfloppy->floppyiftype;
ret=HXCFE_NOERROR;
break;
}
break;
case SET:
switch(param)
{
case DOUBLESTEP:
if(*(unsigned char*)value)
{
newfloppy->double_step=0xFF;
}
else
{
newfloppy->double_step=0x00;
}
ret=HXCFE_NOERROR;
break;
case INTERFACEMODE:
newfloppy->floppyiftype=*(unsigned short*)value;
ret=HXCFE_NOERROR;
break;
}
break;
}
return ret;
}
int32_t hxcfe_floppyGetInterfaceMode( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy )
{
return newfloppy->floppyiftype;
}
int32_t hxcfe_floppySetInterfaceMode( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy, int32_t ifmode )
{
if(hxcfe_getFloppyInterfaceModeName(floppycontext,ifmode))
{
newfloppy->floppyiftype=ifmode;
return HXCFE_NOERROR;
}
return HXCFE_BADPARAMETER;
}
int32_t hxcfe_floppyGetDoubleStep( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy )
{
return newfloppy->double_step;
}
int32_t hxcfe_floppySetDoubleStep( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy, int32_t doublestep )
{
newfloppy->double_step=doublestep;
return HXCFE_NOERROR;
}
uint32_t hxcfe_floppyGetFlags( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy )
{
return newfloppy->flags;
}
int32_t hxcfe_floppySetFlags( HXCFE* floppycontext, HXCFE_FLOPPY * newfloppy, uint32_t flags )
{
newfloppy->flags = flags;
return HXCFE_NOERROR;
}
int libGetPluginInfo( HXCFE_IMGLDR * imgldr_ctx, uint32_t infotype, void * returnvalue, const char * pluginid, const char * plugindesc, plugins_ptr * pluginfunc, const char * fileext )
{
if(imgldr_ctx)
{
if(returnvalue)
{
switch(infotype)
{
case GETPLUGINID:
*(char**)(returnvalue)=(char*)pluginid;
break;
case GETDESCRIPTION:
*(char**)(returnvalue)=(char*)plugindesc;
break;
case GETFUNCPTR:
memcpy(returnvalue,pluginfunc,sizeof(plugins_ptr));
break;
case GETEXTENSION:
*(char**)(returnvalue)=(char*)fileext;
break;
default:
return HXCFE_BADPARAMETER;
break;
}
return HXCFE_NOERROR;
}
}
return HXCFE_BADPARAMETER;
}
HXCFE_FLPGEN* hxcfe_initFloppy( HXCFE* floppycontext, int32_t nb_of_track, int32_t nb_of_side )
{
HXCFE_FLPGEN* fb_ctx;
int i;
fb_ctx = 0;
floppycontext->hxc_printf(MSG_DEBUG,"hxcfe_init_floppy : floppy builder init");
if(( nb_of_track && (nb_of_track<=256)) && ((nb_of_side>=1) && (nb_of_side<=2) ) )
{
fb_ctx = (HXCFE_FLPGEN*)calloc( 1, sizeof(HXCFE_FLPGEN) );
if( !fb_ctx )
goto alloc_error;
fb_ctx->floppycontext = floppycontext;
fb_ctx->floppydisk = (HXCFE_FLOPPY*)calloc( 1, sizeof(HXCFE_FLOPPY) );
if(!fb_ctx->floppydisk)
goto alloc_error;
fb_ctx->floppydisk->floppyBitRate=DEFAULT_DD_BITRATE;
fb_ctx->floppydisk->double_step=0;
fb_ctx->floppydisk->floppyiftype=GENERIC_SHUGART_DD_FLOPPYMODE;
fb_ctx->floppydisk->floppyNumberOfTrack=nb_of_track;
fb_ctx->floppydisk->floppyNumberOfSide=nb_of_side;
fb_ctx->floppydisk->floppySectorPerTrack=-1;
fb_ctx->floppydisk->tracks = (HXCFE_CYLINDER**)calloc( 1, sizeof(HXCFE_CYLINDER*)*fb_ctx->floppydisk->floppyNumberOfTrack );
if(!fb_ctx->floppydisk->tracks)
goto alloc_error;
fb_ctx->fb_stack_pointer=0;
fb_ctx->fb_stack = (fb_track_state*)calloc( 1, sizeof(fb_track_state)*STACK_SIZE );
if(!fb_ctx->fb_stack)
goto alloc_error;
fb_ctx->fb_stack[0].interleave=1;
fb_ctx->fb_stack[0].rpm=300;
fb_ctx->fb_stack[0].forced_side_id = -1;
fb_ctx->fb_stack[0].sectors_size = 512;
for(i=0;i<MAX_NUMBER_OF_INDEX;i++)
{
fb_ctx->fb_stack[0].indexlen[i] = 0;
fb_ctx->fb_stack[0].indexpos[i] = 0;
}
fb_ctx->fb_stack[0].indexlen[0] = 2500;
fb_ctx->fb_stack[0].indexpos[0] = -2500;
fb_ctx->fb_stack[0].sectorunderindex=0;
fb_ctx->fb_stack[0].numberofsector = 0;
fb_ctx->fb_stack[0].numberofsector_min = 0;
fb_ctx->fb_stack[0].start_sector_id = 1;
fb_ctx->fb_stack[0].bitrate=250000;
fb_ctx->fb_stack[0].sectorconfig.bitrate=fb_ctx->fb_stack[0].bitrate;
fb_ctx->fb_stack[0].sectorconfig.fill_byte=0xF6;
fb_ctx->fb_stack[0].sectorconfig.gap3=255;
fb_ctx->fb_stack[0].sectorconfig.sectorsize=512;
fb_ctx->fb_stack[0].sectorconfig.trackencoding=IBMFORMAT_DD;
fb_ctx->fb_stack[0].type = IBMFORMAT_DD;
fb_ctx->fb_stack[0].sc_stack[0].bitrate = 250000;
fb_ctx->fb_stack[0].sc_stack[0].fill_byte = 0xF6;
fb_ctx->fb_stack[0].sc_stack[0].gap3 = 255;
fb_ctx->fb_stack[0].sc_stack[0].sectorsize = 512;
fb_ctx->fb_stack[0].sc_stack[0].trackencoding=IBMFORMAT_DD;
}
return fb_ctx;
alloc_error:
floppycontext->hxc_printf(MSG_ERROR,"hxcfe_init_floppy : malloc error");
if(fb_ctx)
{
if(fb_ctx->floppydisk)
{
free( fb_ctx->floppydisk->tracks );
free( fb_ctx->floppydisk );
}
free( fb_ctx->fb_stack );
free( fb_ctx );
}
return 0;
}
int32_t hxcfe_getNumberOfTrack( HXCFE* floppycontext, HXCFE_FLOPPY *fp )
{
if(fp)
{
return fp->floppyNumberOfTrack;
}
return 0;
}
int32_t hxcfe_getNumberOfSide( HXCFE* floppycontext, HXCFE_FLOPPY *fp )
{
if(fp)
{
return fp->floppyNumberOfSide;
}
return 0;
}
int32_t hxcfe_setNumberOfTrack ( HXCFE_FLPGEN* fb_ctx, int32_t numberoftrack )
{
HXCFE_CYLINDER ** tmptracks;
int tmpfloppyNumberOfTrack;
tmptracks = 0;
tmpfloppyNumberOfTrack = 0;
if( fb_ctx->floppydisk->tracks )
{
tmptracks = fb_ctx->floppydisk->tracks;
tmpfloppyNumberOfTrack = fb_ctx->floppydisk->floppyNumberOfTrack;
}
fb_ctx->floppydisk->floppyNumberOfTrack = numberoftrack;
fb_ctx->floppydisk->tracks = (HXCFE_CYLINDER**)calloc( 1, sizeof(HXCFE_CYLINDER*)*fb_ctx->floppydisk->floppyNumberOfTrack);
if( !fb_ctx->floppydisk->tracks)
{
return HXCFE_INTERNALERROR;
}
if(tmptracks)
{
if ( tmpfloppyNumberOfTrack < numberoftrack )
{
memcpy(fb_ctx->floppydisk->tracks,tmptracks,sizeof(HXCFE_CYLINDER*)*tmpfloppyNumberOfTrack);
}
else
{
memcpy(fb_ctx->floppydisk->tracks,tmptracks,sizeof(HXCFE_CYLINDER*)*numberoftrack);
}
free( tmptracks );
}
return HXCFE_NOERROR;
}
int32_t hxcfe_setNumberOfSide ( HXCFE_FLPGEN* fb_ctx, int32_t numberofside )
{
fb_ctx->floppydisk->floppyNumberOfSide = numberofside;
return HXCFE_NOERROR;
}
int32_t hxcfe_setNumberOfSector ( HXCFE_FLPGEN* fb_ctx, int32_t numberofsector )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].numberofsector_min = numberofsector;
return HXCFE_NOERROR;
}
int32_t hxcfe_setTrackPreGap ( HXCFE_FLPGEN* fb_ctx, int32_t pregap )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].pregap = pregap;
return HXCFE_NOERROR;
}
int32_t hxcfe_pushTrack ( HXCFE_FLPGEN* fb_ctx, uint32_t rpm, int32_t number, int32_t side, int32_t type )
{
fb_track_state * cur_track;
unsigned char * data_to_realloc;
int i;
if(fb_ctx->fb_stack_pointer<(STACK_SIZE-1))
{
fb_ctx->fb_stack_pointer++;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
memcpy(&fb_ctx->fb_stack[fb_ctx->fb_stack_pointer],&fb_ctx->fb_stack[fb_ctx->fb_stack_pointer-1],sizeof(fb_track_state));
i = 0;
while( i < fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].numberofsector )
{
if ( cur_track->sectortab[i].input_data )
{
data_to_realloc = cur_track->sectortab[i].input_data;
cur_track->sectortab[i].input_data = (unsigned char * )malloc(cur_track->sectortab[i].sectorsize);
if(cur_track->sectortab[i].input_data)
memcpy(cur_track->sectortab[i].input_data,data_to_realloc,cur_track->sectortab[i].sectorsize);
free( data_to_realloc );
}
i++;
}
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].rpm = rpm;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].side_number = side;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].track_number = number;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].type = type;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sc_stack[fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sc_stack_pointer].trackencoding = type;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sectorconfig.trackencoding = type;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].numberofsector = 0;
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sc_stack_pointer = 0;
return HXCFE_NOERROR;
}
return HXCFE_BADPARAMETER;
}
int32_t hxcfe_pushSector ( HXCFE_FLPGEN* fb_ctx )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
if( cur_track->sc_stack_pointer < (STACK_SIZE-1) )
{
cur_track->sc_stack_pointer++;
memcpy(&cur_track->sc_stack[cur_track->sc_stack_pointer],&cur_track->sc_stack[cur_track->sc_stack_pointer-1],sizeof(HXCFE_SECTCFG));
cur_track->sc_stack[cur_track->sc_stack_pointer].sector++;
return HXCFE_NOERROR;
}
return HXCFE_INTERNALERROR;
}
int32_t hxcfe_popSector ( HXCFE_FLPGEN* fb_ctx )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
if( cur_track->numberofsector < (NUMBEROFSECTOR_MAX-1) )
{
memcpy(&cur_track->sectortab[cur_track->numberofsector],&cur_track->sc_stack[cur_track->sc_stack_pointer],sizeof(HXCFE_SECTCFG) );
cur_track->numberofsector++;
if(cur_track->numberofsector_min < cur_track->numberofsector )
cur_track->numberofsector_min = cur_track->numberofsector;
memset(&cur_track->sc_stack[cur_track->sc_stack_pointer],0,sizeof(HXCFE_SECTCFG));
if( cur_track->sc_stack_pointer )
{
cur_track->sc_stack_pointer--;
}
return HXCFE_NOERROR;
}
return HXCFE_INTERNALERROR;
}
int32_t hxcfe_pushTrackPFS ( HXCFE_FLPGEN* fb_ctx, int32_t number, int32_t side )
{
return hxcfe_pushTrack (fb_ctx,fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].rpm,number,side,fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].type);
}
int32_t hxcfe_setTrackBitrate ( HXCFE_FLPGEN* fb_ctx, int32_t bitrate )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->bitrate = bitrate;
cur_track->sectorconfig.bitrate = bitrate;
cur_track->sc_stack[fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sc_stack_pointer].bitrate = bitrate;
return HXCFE_NOERROR;
}
int32_t hxcfe_setTrackType( HXCFE_FLPGEN* fb_ctx, int32_t type )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->type = type;
cur_track->sectorconfig.trackencoding = type;
cur_track->sc_stack[fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sc_stack_pointer].trackencoding = type;
return HXCFE_NOERROR;
}
int32_t hxcfe_setTrackInterleave ( HXCFE_FLPGEN* fb_ctx, int32_t interleave )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].interleave = interleave;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorSize( HXCFE_FLPGEN* fb_ctx, int32_t size )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sectors_size = size;
cur_track->sc_stack[cur_track->sc_stack_pointer].sectorsize = size;
return HXCFE_NOERROR;
}
int32_t hxcfe_setTrackSkew ( HXCFE_FLPGEN* fb_ctx, int32_t skew )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].skew = skew;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSideSkew ( HXCFE_FLPGEN* fb_ctx, int32_t skew )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].side_skew = skew;
return HXCFE_NOERROR;
}
int32_t hxcfe_setIndexPosition ( HXCFE_FLPGEN* fb_ctx, int32_t index_number, int32_t position, int32_t allowsector )
{
if(index_number < MAX_NUMBER_OF_INDEX)
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].indexpos[index_number] = position;
}
return HXCFE_NOERROR;
}
int32_t hxcfe_setIndexLength ( HXCFE_FLPGEN* fb_ctx, int32_t index_number, int32_t Length )
{
if(index_number < MAX_NUMBER_OF_INDEX)
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].indexlen[index_number] = Length;
}
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorData( HXCFE_FLPGEN* fb_ctx, uint8_t * buffer, int32_t size )
{
fb_track_state * cur_track;
HXCFE_SECTCFG * cur_sector;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_sector = &cur_track->sc_stack[cur_track->sc_stack_pointer];
free( cur_sector->input_data );
cur_sector->input_data = NULL;
free( cur_sector->weak_bits_mask );
cur_sector->weak_bits_mask = NULL;
if(buffer)
{
cur_sector->input_data = malloc(size);
if( cur_sector->input_data )
{
memcpy(cur_sector->input_data,buffer,size);
}
else
{
return HXCFE_INTERNALERROR;
}
}
cur_sector->sectorsize = size;
return HXCFE_NOERROR;
}
int32_t hxcfe_addSector ( HXCFE_FLPGEN* fb_ctx, int32_t sectornumber, int32_t side, int32_t track, uint8_t * buffer, int32_t size )
{
hxcfe_pushSector (fb_ctx);
hxcfe_setSectorTrackID(fb_ctx,track);
hxcfe_setSectorHeadID(fb_ctx,side);
hxcfe_setSectorID(fb_ctx,sectornumber);
hxcfe_setSectorData(fb_ctx,buffer,size);
hxcfe_popSector (fb_ctx);
return HXCFE_NOERROR;
}
int32_t hxcfe_addSectors( HXCFE_FLPGEN* fb_ctx, int32_t side, int32_t track, uint8_t * trackdata, int32_t buffersize, int32_t numberofsectors )
{
int i,ret;
int startsectorid,sectorsize;
if(fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].numberofsector<0x400)
{
startsectorid = fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].start_sector_id;
sectorsize = fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sectors_size;
for(i = 0; i < numberofsectors ; i++)
{
if(trackdata)
ret = hxcfe_addSector(fb_ctx,startsectorid + i,side,track,&trackdata[i*sectorsize],sectorsize);
else
ret = hxcfe_addSector(fb_ctx,startsectorid + i,side,track,0,sectorsize);
if(ret != HXCFE_NOERROR)
{
return ret;
}
}
return HXCFE_NOERROR;
}
return HXCFE_BADPARAMETER;
}
int32_t hxcfe_setSectorSizeID ( HXCFE_FLPGEN* fb_ctx, int32_t sectorsizeid )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].use_alternate_sector_size_id=0xFF;
cur_track->sc_stack[cur_track->sc_stack_pointer].alternate_sector_size_id=sectorsizeid;
return HXCFE_NOERROR;
}
int32_t hxcfe_setStartSectorID( HXCFE_FLPGEN* fb_ctx, int32_t startsectorid )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].start_sector_id = startsectorid;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorBitrate ( HXCFE_FLPGEN* fb_ctx, int32_t bitrate )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].bitrate=bitrate;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorFill ( HXCFE_FLPGEN* fb_ctx, int32_t fill )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].fill_byte = (unsigned char)fill;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorTrackID( HXCFE_FLPGEN* fb_ctx, int32_t track )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].cylinder = track;
return HXCFE_NOERROR;
}
int32_t hxcfe_setDiskSectorsHeadID( HXCFE_FLPGEN* fb_ctx, int32_t head )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].forced_side_id = head;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorHeadID( HXCFE_FLPGEN* fb_ctx, int32_t head )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].head = head;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorID( HXCFE_FLPGEN* fb_ctx, int32_t id )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].sector = id;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorGap3 ( HXCFE_FLPGEN* fb_ctx, int32_t Gap3 )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].gap3=Gap3;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorEncoding ( HXCFE_FLPGEN* fb_ctx, int32_t encoding )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].trackencoding = encoding;
return HXCFE_NOERROR;
}
int32_t hxcfe_setRPM( HXCFE_FLPGEN* fb_ctx, int32_t rpm )
{
fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].rpm = rpm;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorDataCRC ( HXCFE_FLPGEN* fb_ctx, uint32_t crc )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].use_alternate_data_crc=0xFF;
cur_track->sc_stack[cur_track->sc_stack_pointer].data_crc=crc;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorHeaderCRC ( HXCFE_FLPGEN* fb_ctx, uint32_t crc )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].use_alternate_header_crc=0xFF;
cur_track->sc_stack[cur_track->sc_stack_pointer].header_crc=crc;
return HXCFE_NOERROR;
}
int32_t hxcfe_setSectorDataMark ( HXCFE_FLPGEN* fb_ctx, uint32_t datamark )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->sc_stack[cur_track->sc_stack_pointer].use_alternate_datamark = 0xFF;
cur_track->sc_stack[cur_track->sc_stack_pointer].alternate_datamark = datamark;
return HXCFE_NOERROR;
}
int32_t hxcfe_setInterfaceMode( HXCFE_FLPGEN* fb_ctx, int32_t mode )
{
fb_track_state * cur_track;
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
cur_track->interface_mode = mode;
return HXCFE_NOERROR;
}
int32_t hxcfe_popTrack ( HXCFE_FLPGEN* fb_ctx )
{
HXCFE_CYLINDER* currentcylinder;
fb_track_state * current_fb_track_state;
int i;
uint32_t sui_flag;
if(fb_ctx->fb_stack_pointer)
{
current_fb_track_state=&fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
if( current_fb_track_state->track_number < fb_ctx->floppydisk->floppyNumberOfTrack)
{
if(!fb_ctx->floppydisk->tracks[current_fb_track_state->track_number])
fb_ctx->floppydisk->tracks[current_fb_track_state->track_number] = allocCylinderEntry(current_fb_track_state->rpm,fb_ctx->floppydisk->floppyNumberOfSide);
currentcylinder = fb_ctx->floppydisk->tracks[current_fb_track_state->track_number];
sui_flag=0;
if(!current_fb_track_state->sectorunderindex)
sui_flag=NO_SECTOR_UNDER_INDEX;
currentcylinder->sides[current_fb_track_state->side_number] = tg_generateTrackEx((unsigned short)current_fb_track_state->numberofsector,
current_fb_track_state->sectortab,
current_fb_track_state->interleave,
current_fb_track_state->skew,
current_fb_track_state->bitrate,
current_fb_track_state->rpm,
current_fb_track_state->type,
current_fb_track_state->pregap,
current_fb_track_state->indexlen[0] | sui_flag,current_fb_track_state->indexpos[0]);
for(i=1;i<MAX_NUMBER_OF_INDEX;i++)
{
if(current_fb_track_state->indexlen[i])
{
fillindex(current_fb_track_state->indexpos[i],currentcylinder->sides[current_fb_track_state->side_number],current_fb_track_state->indexlen[i],1,0);
}
}
for(i=0;i<current_fb_track_state->numberofsector;i++)
{
hxcfe_freeSectorConfigData( 0, &current_fb_track_state->sectortab[i] );
}
fb_ctx->fb_stack_pointer--;
return HXCFE_NOERROR;
}
else
{
for(i=0;i<current_fb_track_state->numberofsector;i++)
{
hxcfe_freeSectorConfigData( 0, &current_fb_track_state->sectortab[i] );
}
fb_ctx->fb_stack_pointer--;
return HXCFE_BADPARAMETER;
}
}
return HXCFE_NOERROR;
}
int32_t hxcfe_getCurrentNumberOfTrack ( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->floppydisk->floppyNumberOfTrack;
}
int32_t hxcfe_getCurrentNumberOfSide ( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->floppydisk->floppyNumberOfSide;
}
int32_t hxcfe_getCurrentNumberOfSector ( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].numberofsector_min;
}
int32_t hxcfe_getCurrentSectorSize( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].sectors_size;
}
int32_t hxcfe_getCurrentTrackType ( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].type;
}
int32_t hxcfe_getCurrentRPM ( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].rpm;
}
int32_t hxcfe_getCurrentSkew ( HXCFE_FLPGEN* fb_ctx )
{
return fb_ctx->fb_stack[fb_ctx->fb_stack_pointer].skew;
}
int32_t hxcfe_setDiskFlags( HXCFE_FLPGEN* fb_ctx, int32_t flags )
{
fb_ctx->disk_flags = flags;
return HXCFE_NOERROR;
}
int32_t hxcfe_generateDisk( HXCFE_FLPGEN* fb_ctx, HXCFE_FLOPPY* floppy, void * f, uint8_t * diskdata, int32_t buffersize )
{
int i,j,ret;
int numberoftracks;
int numberofsector,sectorsize;
int bufferoffset,type;
unsigned int rpm,interleave;
unsigned char * track_buffer;
unsigned char fill_byte;
int image_size;
int start_file_ofs;
int skew_per_track;
int skew_per_side;
int auto_side_id,side_id;
fb_track_state * cur_track;
FILE * filehandle;
HXCFE_SIDE* tmp_side;
int disk_bitrate;
if ( !f && !diskdata )
return HXCFE_BADPARAMETER;
filehandle = (FILE*)f;
image_size = 0;
start_file_ofs = 0;
numberoftracks = fb_ctx->floppydisk->floppyNumberOfTrack;
// Increase the track number to add the blank tracks.
if( numberoftracks > 75 && numberoftracks < 79 )
{
hxcfe_setNumberOfTrack ( fb_ctx, 79 );
}
if( numberoftracks > 78 && numberoftracks < 84 )
{
hxcfe_setNumberOfTrack ( fb_ctx, 84 );
}
if( numberoftracks > 38 && numberoftracks < 42 )
{
hxcfe_setNumberOfTrack ( fb_ctx, 42 );
}
if( filehandle )
{
start_file_ofs = ftell(filehandle);
fseek(filehandle,0,SEEK_END);
image_size = ftell(filehandle);
fseek(filehandle,start_file_ofs,SEEK_SET);
}
else
{
image_size = buffersize;
}
cur_track = &fb_ctx->fb_stack[fb_ctx->fb_stack_pointer];
sectorsize = cur_track->sectors_size;
numberofsector = cur_track->numberofsector_min;
interleave = cur_track->interleave;
rpm = cur_track->rpm;
type = cur_track->type;
skew_per_track = cur_track->skew;
skew_per_side = cur_track->side_skew;
auto_side_id = cur_track->forced_side_id;
fill_byte = cur_track->sc_stack[cur_track->sc_stack_pointer].fill_byte;
fb_ctx->floppycontext->hxc_printf(MSG_INFO_1,"Image Size:%dkB, %d tracks, %d side(s), %d sectors/track, interleave:%d,rpm:%d",(image_size-start_file_ofs)/1024,
numberoftracks,
fb_ctx->floppydisk->floppyNumberOfSide,
numberofsector,
interleave,
rpm);
track_buffer = malloc( sectorsize * numberofsector );
if( !track_buffer )
return HXCFE_INTERNALERROR;
for(i = 0 ; i < numberoftracks ; i++ )
{
for(j = 0 ; j < fb_ctx->floppydisk->floppyNumberOfSide ; j++ )
{
if( fb_ctx->disk_flags & FLPGEN_SIDES_GROUPED )
{
bufferoffset = start_file_ofs + \
( numberofsector * sectorsize * numberoftracks * j) + \
( numberofsector * sectorsize * i );
}
else
{
if( fb_ctx->floppydisk->floppyNumberOfSide == 2 )
{
bufferoffset = start_file_ofs + ( numberofsector * sectorsize * ((i<<1) + (j&1)) ) ;
}
else
{
bufferoffset = start_file_ofs + ( numberofsector * sectorsize * i );
}
}
if( filehandle )
{
fseek( filehandle, bufferoffset, SEEK_SET);
if( (bufferoffset + (numberofsector * sectorsize)) < image_size )
{
if( fread( track_buffer, numberofsector * sectorsize, 1, filehandle ) != 1 )
{
fb_ctx->floppycontext->hxc_printf(MSG_ERROR,"hxcfe_generateDisk : Error while reading the file image ! Unexpected end of file ?");
}
}
else
{
memset(track_buffer, fill_byte, sectorsize * numberofsector);
if( bufferoffset < image_size )
{
if(fread(track_buffer,image_size - bufferoffset,1,f) != 1)
{
fb_ctx->floppycontext->hxc_printf(MSG_ERROR,"hxcfe_generateDisk : Error while reading the file image ! Unexpected end of file ?");
}
}
}
}
else
{
if( (bufferoffset + (numberofsector * sectorsize)) < image_size )
{
memcpy(track_buffer,&diskdata[bufferoffset],numberofsector * sectorsize);
}
else
{
memset(track_buffer, fill_byte, sectorsize * numberofsector);
if( bufferoffset < image_size )
{
memcpy(track_buffer,&diskdata[bufferoffset],image_size - bufferoffset);
}
}
}
if(!fb_ctx->floppydisk->tracks[i] || !fb_ctx->floppydisk->tracks[i]->sides[j])
{
//if(!fb_ctx->floppydisk->tracks[i]->sides[j])
{
hxcfe_pushTrack (fb_ctx,rpm,i,j,type);
hxcfe_setTrackSkew( fb_ctx, (skew_per_track*i) + (skew_per_side*j) );
if(auto_side_id < 0)
side_id = j;
else
side_id = auto_side_id;
ret = hxcfe_addSectors(fb_ctx,side_id,i,track_buffer,(sectorsize * numberofsector),numberofsector);
hxcfe_popTrack (fb_ctx);
if ( ret != HXCFE_NOERROR )
goto error;
}
}
}
if( fb_ctx->floppydisk->floppyNumberOfSide == 2 && (fb_ctx->disk_flags & FLPGEN_FLIP_SIDES) )
{
tmp_side = fb_ctx->floppydisk->tracks[i]->sides[0];
fb_ctx->floppydisk->tracks[i]->sides[0] = fb_ctx->floppydisk->tracks[i]->sides[1];
fb_ctx->floppydisk->tracks[i]->sides[1] = tmp_side;
}
}
// Add blank tracks.
for(;i<fb_ctx->floppydisk->floppyNumberOfTrack;i++)
{
for(j = 0 ; j < fb_ctx->floppydisk->floppyNumberOfSide ; j++ )
{
hxcfe_pushTrack (fb_ctx,rpm,i,j,type);
hxcfe_popTrack (fb_ctx);
}
}
disk_bitrate = VARIABLEBITRATE;
if(fb_ctx->floppydisk->tracks[0] && fb_ctx->floppydisk->tracks[0]->sides[0])
{
disk_bitrate = fb_ctx->floppydisk->tracks[0]->sides[0]->bitrate;
}
for(i = 0 ; i < fb_ctx->floppydisk->floppyNumberOfTrack ; i++ )
{
for(j = 0 ; j < fb_ctx->floppydisk->floppyNumberOfSide ; j++ )
{
if(fb_ctx->floppydisk->tracks[i] && fb_ctx->floppydisk->tracks[i]->sides[j])
{
if( fb_ctx->floppydisk->tracks[i]->sides[j]->bitrate != disk_bitrate )
{
disk_bitrate = VARIABLEBITRATE;
}
}
}
}
fb_ctx->floppydisk->floppyBitRate = disk_bitrate;
if ( floppy )
{
memcpy(floppy, fb_ctx->floppydisk , sizeof(HXCFE_FLOPPY));
floppy->floppyiftype = cur_track->interface_mode;
}
fb_ctx->floppycontext->hxc_printf(MSG_INFO_1,"track file successfully loaded and encoded!");
free( track_buffer );
free( fb_ctx->fb_stack );
free( fb_ctx );
return HXCFE_NOERROR;
error:
free( track_buffer );
free( fb_ctx->fb_stack );
free( fb_ctx );
return HXCFE_INTERNALERROR;
}
HXCFE_FLOPPY* hxcfe_getFloppy ( HXCFE_FLPGEN* fb_ctx )
{
int bitrate,trackencoding;
int i,j;
HXCFE_FLOPPY *f;
f=0;
for (j = 0; j < fb_ctx->floppydisk->floppyNumberOfTrack; j++)
{
for (i = 0; i < fb_ctx->floppydisk->floppyNumberOfSide; i++)
{
if(!fb_ctx->floppydisk->tracks[j])
{
hxcfe_pushTrack (fb_ctx,fb_ctx->fb_stack[0].rpm,j,i,fb_ctx->fb_stack[0].type);
hxcfe_popTrack (fb_ctx);
}
else
{
if(!fb_ctx->floppydisk->tracks[j]->sides[i])
{
hxcfe_pushTrack (fb_ctx,fb_ctx->fb_stack[0].rpm,j,i,fb_ctx->fb_stack[0].type);
hxcfe_popTrack (fb_ctx);
}
}
}
}
if(fb_ctx->floppydisk->floppyNumberOfTrack && fb_ctx->floppydisk->floppyNumberOfSide)
{
bitrate = fb_ctx->floppydisk->tracks[0]->sides[0]->bitrate;
trackencoding = fb_ctx->floppydisk->tracks[0]->sides[0]->track_encoding;
for(j=0;j<fb_ctx->floppydisk->floppyNumberOfTrack;j++)
{
for(i=0;i<fb_ctx->floppydisk->tracks[j]->number_of_side;i++)
{
if(fb_ctx->floppydisk->tracks[j]->sides[i])
{
if(bitrate != fb_ctx->floppydisk->tracks[j]->sides[i]->bitrate)
{
bitrate=-1;
}
}
else
{
if(i==1)
{
fb_ctx->floppydisk->tracks[j]->number_of_side--;
}
else
{
fb_ctx->floppydisk->tracks[j]->sides[i]=tg_generateTrack(0,
0,
0,
0,
0,
0,
1,
1,
bitrate,
fb_ctx->floppydisk->tracks[j]->floppyRPM,
(unsigned char)trackencoding,
255,
0,
fb_ctx->fb_stack[0].indexlen[0],
fb_ctx->fb_stack[0].indexpos[0]);
for(i=1;i<MAX_NUMBER_OF_INDEX;i++)
{
if(fb_ctx->fb_stack[0].indexlen[i])
{
fillindex(fb_ctx->fb_stack[0].indexpos[0],fb_ctx->floppydisk->tracks[j]->sides[i],fb_ctx->fb_stack[0].indexlen[i],1,0);
}
}
}
}
}
}
fb_ctx->floppydisk->floppyBitRate=bitrate;
f = fb_ctx->floppydisk;
free( fb_ctx->fb_stack );
free( fb_ctx );
}
return f;
}
HXCFE_FLOPPY* hxcfe_sanityCheck(HXCFE* floppycontext,HXCFE_FLOPPY * floppydisk)
{
int numberoftrack,truenumberoftrack;
int numberofside,oldnumberofside,truenumberofside;
int needanewpass;
int i;
HXCFE_SIDE ** tmpsides;
HXCFE_SIDE * currentside;
if(floppydisk)
{
// Check track parameter.
truenumberoftrack = 0;
if(floppydisk->floppyNumberOfTrack>256)
{
floppydisk->floppyNumberOfTrack=256;
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : More than 256 tracks?!? - fixed to 256. Please Check the Loader !");
}
if(!floppydisk->floppyNumberOfSide)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : 0 Side?!? - fixed to 1. Please Check the Loader !");
floppydisk->floppyNumberOfSide = 1;
}
if(floppydisk->floppyNumberOfSide>2)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : more than 2 Sides (%d) ?!? - fixed to 2. Please Check the Loader !",floppydisk->floppyNumberOfSide);
floppydisk->floppyNumberOfSide = 2;
}
if(floppydisk->floppyBitRate!=-1)
{
if(floppydisk->floppyBitRate > 1000000)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : Over 1MBit/s ?!? - fixed to 1MB/S. Please Check the Loader !");
floppydisk->floppyBitRate = 1000000;
}
if(floppydisk->floppyBitRate < 25000)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : Under 25kBit/s ?!? - fixed to 250KB/S. Please Check the Loader !");
floppydisk->floppyBitRate = 250000;
}
}
numberofside = floppydisk->floppyNumberOfSide;
if(!floppydisk->tracks)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : No track allocated ? Please Check the Loader !");
floppydisk->tracks=(HXCFE_CYLINDER**)calloc( 1, sizeof(HXCFE_CYLINDER*)*floppydisk->floppyNumberOfTrack );
if(!floppydisk->tracks)
goto alloc_error;
}
numberoftrack = floppydisk->floppyNumberOfTrack;
for( i = 0; i < numberoftrack ; i++ )
{
if( floppydisk->tracks[truenumberoftrack] )
{
truenumberoftrack++;
}
}
if( truenumberoftrack != numberoftrack)
{
truenumberoftrack=0;
while( truenumberoftrack<numberoftrack )
{
if(!floppydisk->tracks[truenumberoftrack] )
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : Track entry %d missing !",truenumberoftrack);
floppydisk->tracks[truenumberoftrack] = allocCylinderEntry(0,floppydisk->floppyNumberOfSide);
}
truenumberoftrack++;
}
}
do
{
needanewpass = 0;
numberofside = floppydisk->floppyNumberOfSide;
truenumberoftrack=0;
while( truenumberoftrack<numberoftrack )
{
truenumberofside=0;
while(truenumberofside<numberofside)
{
if(floppydisk->tracks[truenumberoftrack]->number_of_side != numberofside)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : Bad number of side (%d should be %d) at Track entry %d",floppydisk->tracks[truenumberoftrack]->number_of_side,numberofside,truenumberoftrack);
if(floppydisk->tracks[truenumberoftrack]->number_of_side < numberofside )
{
tmpsides = floppydisk->tracks[truenumberoftrack]->sides;
oldnumberofside = floppydisk->tracks[truenumberoftrack]->number_of_side;
// Realloc buffer
floppydisk->tracks[truenumberoftrack]->number_of_side = numberofside;
floppydisk->tracks[truenumberoftrack]->sides = (HXCFE_SIDE**)calloc( 1, sizeof(HXCFE_SIDE*)*numberofside);
if(!floppydisk->tracks[truenumberoftrack]->sides)
goto alloc_error;
if(tmpsides && oldnumberofside)
floppydisk->tracks[truenumberoftrack]->sides[0] = tmpsides[0];
}
else
{
if(floppydisk->tracks[truenumberoftrack]->number_of_side <= 2)
floppydisk->floppyNumberOfSide = floppydisk->tracks[truenumberoftrack]->number_of_side;
else
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : track %d - more than 2 Sides (%d) ?!? - fixed to 2. Please Check the Loader !",truenumberoftrack,floppydisk->floppyNumberOfSide);
floppydisk->tracks[truenumberoftrack]->number_of_side = 2;
}
needanewpass = 1;
}
}
truenumberofside++;
}
truenumberoftrack++;
}
}while(needanewpass);
numberoftrack = floppydisk->floppyNumberOfTrack;
numberofside = floppydisk->floppyNumberOfSide;
truenumberoftrack=0;
while( truenumberoftrack<numberoftrack )
{
truenumberofside=0;
while(truenumberofside<numberofside)
{
currentside=floppydisk->tracks[truenumberoftrack]->sides[truenumberofside];
if(!currentside)
{
currentside=(HXCFE_SIDE*)calloc( 1, sizeof(HXCFE_SIDE) );
if(!currentside)
goto alloc_error;
}
floppydisk->tracks[truenumberoftrack]->sides[truenumberofside]=currentside;
if(!currentside->databuffer)
{
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : Track %d/Side %d not allocated ?!?",truenumberoftrack,truenumberofside);
if(truenumberofside)
{
if(floppydisk->tracks[truenumberoftrack]->sides[0]->tracklen)
{
currentside->tracklen = floppydisk->tracks[truenumberoftrack]->sides[0]->tracklen;
}
else
currentside->tracklen = 12500*8;
}
else
currentside->tracklen = 12500*8;
currentside->databuffer = calloc( 1, currentside->tracklen/8 );
if(!currentside->databuffer)
goto alloc_error;
currentside->indexbuffer = calloc( 1, currentside->tracklen/8 );
if(!currentside->indexbuffer)
goto alloc_error;
if(floppydisk->floppyBitRate!=-1)
currentside->bitrate=floppydisk->floppyBitRate;
else
currentside->bitrate=250000;
fillindex(0,currentside,2500,1,0);
}
truenumberofside++;
}
truenumberoftrack++;
}
}
return floppydisk;
alloc_error:
floppycontext->hxc_printf(MSG_WARNING,"Sanity Checker : Memory allocation error !",truenumberoftrack);
return NULL;
}
fs_config fs_config_table[]=
{
{"fatst", "",FS_720KB_ATARI_FAT12,0},
{"fatst902", "",FS_902KB_ATARI_FAT12,0},
{"fatst360", "",FS_360KB_ATARI_FAT12,0},
{"amigados", "3\"5 880KB DSDD AmigaDOS",FS_880KB_AMIGADOS,1},
{"amigados_hd", "3\"5 1760KB DSHD AmigaDOS",FS_1760KB_AMIGADOS,2},
{"fat160a", "5\"25 & 8\" 160KB SSDD 300RPM FAT12",FS_5P25_300RPM_160KB_MSDOS_FAT12,0},
{"fat160b", "5\"25 & 8\" 160KB SSDD 360RPM FAT12",FS_5P25_360RPM_160KB_MSDOS_FAT12,0},
{"fat180a", "5\"25 180KB SSDD 300RPM FAT12",FS_5P25_300RPM_180KB_MSDOS_FAT12,0},
{"fat180b", "5\"25 180KB SSDD 360RPM FAT12",FS_5P25_360RPM_180KB_MSDOS_FAT12,0},
{"fat320ssa", "5\"25 320KB SSDD 300RPM FAT12",FS_5P25_SS_300RPM_320KB_MSDOS_FAT12,0},
{"fat320ssb", "5\"25 320KB SSDD 360RPM FAT12",FS_5P25_SS_360RPM_320KB_MSDOS_FAT12,0},
{"fat320dsa", "5\"25 320KB DSDD 300RPM FAT12",FS_5P25_DS_300RPM_320KB_MSDOS_FAT12,0},
{"fat320dsb", "5\"25 320KB DSDD 360RPM FAT12",FS_5P25_DS_360RPM_320KB_MSDOS_FAT12,0},
{"fat360a", "5\"25 & 8\" 360KB DSDD 300RPM FAT12",FS_5P25_DS_300RPM_360KB_MSDOS_FAT12,0},
{"fat360b", "5\"25 & 8\" 360KB DSDD 360RPM FAT12",FS_5P25_DS_360RPM_360KB_MSDOS_FAT12,0},
{"fat640", "3\"5 640KB DSDD FAT12",FS_3P5_DS_300RPM_640KB_MSDOS_FAT12,0},
{"fat720", "3\"5 720KB DSDD FAT12",FS_720KB_MSDOS_FAT12,0},
{"fat738", "3\"5 738KB DSDD FAT12",FS_738KB_MSDOS_FAT12,0},
{"fat800", "3\"5 800KB DSDD FAT12",FS_800KB_MSDOS_FAT12,0},
{"fat820", "3\"5 820KB DSDD FAT12",FS_820KB_MSDOS_FAT12,0},
{"fat1200", "5\"25 1.2MB DSHD FAT12",FS_5P25_300RPM_1200KB_MSDOS_FAT12,0},
{"fat1230", "5\"25 1.23MB DSHD FAT12",FS_5P25_300RPM_1230KB_MSDOS_FAT12,0},
{"fat1440", "3\"5 1.44MB DSHD FAT12",FS_1_44MB_MSDOS_FAT12,0},
{"fat1476", "3\"5 1.478MB DSHD FAT12",FS_1_476MB_MSDOS_FAT12,0},
{"fat1600", "3\"5 1.6MB DSHD FAT12",FS_1_600MB_MSDOS_FAT12,0},
{"fat1640", "3\"5 1.64MB DSHD FAT12",FS_1_640MB_MSDOS_FAT12,0},
{"fat1680", "3\"5 1.68MB DSHD FAT12",FS_1_68MB_MSDOS_FAT12,0},
{"fat1722", "3\"5 1.722MB DSHD FAT12",FS_1_722MB_MSDOS_FAT12,0},
{"fat1743", "3\"5 1.743MB DSHD FAT12",FS_1_743MB_MSDOS_FAT12,0},
{"fat1764", "3\"5 1.764MB DSHD FAT12",FS_1_764MB_MSDOS_FAT12,0},
{"fat1785", "3\"5 1.785MB DSHD FAT12",FS_1_785MB_MSDOS_FAT12,0},
{"fat2540", "3\"5 2.50MB DSDD FAT12",FS_2_50MB_MSDOS_FAT12,0},
{"fat2880", "3\"5 2.88MB DSED FAT12",FS_2_88MB_MSDOS_FAT12,0},
{"fat3381", "3\"5 3.38MB DSHD FAT12",FS_3_38MB_MSDOS_FAT12,0},
{"fatbigst", "3\"5 3.42MB DSDD Atari FAT12",FS_3_42MB_ATARI_FAT12,0},
{"fat5355", "3\"5 5.35MB DSHD FAT12",FS_5_35MB_MSDOS_FAT12,0},
{"fat5355b", "3\"5 5.35MB DSHD FAT12",FS_5_35MB_B_MSDOS_FAT12,0},
{"fat6789", "3\"5 6.78MB DSHD FAT12",FS_6_78MB_MSDOS_FAT12,0},
{"fatbig", "",FS_16MB_MSDOS_FAT12,0},
{"fat4572", "3\"5 4.50MB DSHD FAT12",FS_4_50MB_MSDOS_FAT12,0},
{0,0,0,0}
};
HXCFE_FLOPPY * hxcfe_generateFloppy( HXCFE* floppycontext, char* path, int32_t fsID, int32_t * err_ret )
{
int ret;
HXCFE_FLOPPY * newfloppy;
HXCFE_IMGLDR * imgldr_ctx;
plugins_ptr func_ptr;
int moduleID;
int i;
image_plugin* plugin_ptr;
floppycontext->hxc_printf(MSG_INFO_0,"Create file system (source path : %s) ...",path);
plugin_ptr = (image_plugin*)floppycontext->image_handlers;
newfloppy = 0;
imgldr_ctx = hxcfe_imgInitLoader(floppycontext);
if(imgldr_ctx)
{
if( fsID == FS_880KB_AMIGADOS || fsID == FS_1760KB_AMIGADOS )
moduleID = hxcfe_imgGetLoaderID (imgldr_ctx,PLUGIN_AMIGA_FS);
else
moduleID = hxcfe_imgGetLoaderID (imgldr_ctx,PLUGIN_FAT12FLOPPY);
i=0;
while(fs_config_table[i].name && (fs_config_table[i].fsID != fsID))
{
i++;
}
if(hxcfe_checkLoaderID(imgldr_ctx,moduleID)==HXCFE_NOERROR && fs_config_table[i].name)
{
ret = plugin_ptr[moduleID].infos_handler(imgldr_ctx,GETFUNCPTR,&func_ptr);
if(ret==HXCFE_NOERROR)
{
newfloppy = calloc( 1, sizeof(HXCFE_FLOPPY) );
if(newfloppy)
{
floppycontext->hxc_printf(MSG_INFO_0,"file loader found!");
ret=func_ptr.libLoad_DiskFile(imgldr_ctx,newfloppy,path,fs_config_table[i].name);
if(ret!=HXCFE_NOERROR)
{
free( newfloppy );
newfloppy = NULL;
}
if(err_ret)
*err_ret=ret;
hxcfe_imgDeInitLoader(imgldr_ctx);
}
return newfloppy;
}
}
floppycontext->hxc_printf(MSG_ERROR,"Bad plugin ID : 0x%x",moduleID);
ret=HXCFE_BADPARAMETER;
if(err_ret)
*err_ret=ret;
hxcfe_imgDeInitLoader(imgldr_ctx);
}
return newfloppy;
}
int32_t hxcfe_getTrackBitrate( HXCFE* floppycontext, HXCFE_FLOPPY * fp, int32_t track, int32_t side )
{
if(fp)
{
return fp->tracks[track]->sides[side]->bitrate;
}
return 0;
}
int32_t hxcfe_getTrackEncoding( HXCFE* floppycontext, HXCFE_FLOPPY * fp, int32_t track, int32_t side )
{
if(fp)
{
return fp->tracks[track]->sides[side]->track_encoding;
}
return 0;
}
int32_t hxcfe_getTrackLength( HXCFE* floppycontext, HXCFE_FLOPPY * fp, int32_t track, int32_t side )
{
if(fp)
{
return fp->tracks[track]->sides[side]->tracklen;
}
return 0;
}
int32_t hxcfe_getTrackRPM( HXCFE* floppycontext, HXCFE_FLOPPY * fp, int32_t track )
{
if(fp)
{
return fp->tracks[track]->floppyRPM;
}
return 0;
}
int32_t hxcfe_getTrackNumberOfSide( HXCFE* floppycontext, HXCFE_FLOPPY * fp, int32_t track )
{
if(fp)
{
return fp->tracks[track]->number_of_side;
}
return 0;
}
int track_hash( HXCFE* floppycontext, HXCFE_FLOPPY * floppydisk, int track, int side, int type, uint32_t * crc32 )
{
HXCFE_SECTORACCESS* ss;
HXCFE_SECTCFG* sc;
ss = hxcfe_initSectorAccess(floppycontext,floppydisk);
if( ss )
{
do
{
sc = hxcfe_getNextSector(ss,track,side,type);
if( sc )
{
///////////////////////////////////////
// Data Block
///////////////////////////////////////
if( sc->startdataindex == sc->startsectorindex )
{
// Header less sector
}
else
{
if( sc->use_alternate_data_crc )
{
// CRC error
}
else
{
if( crc32 )
{
if(sc->input_data && !sc->use_alternate_data_crc)
{
*crc32 = std_crc32(*crc32, sc->input_data, sc->sectorsize);
}
}
}
}
hxcfe_freeSectorConfig( ss, sc );
}
}while(sc);
hxcfe_deinitSectorAccess( ss );
}
return 0;
}
int32_t hxcfe_getHash( HXCFE* floppycontext, HXCFE_FLOPPY * fp, int32_t track, int32_t side, int32_t sector, uint32_t formats, int hashtype, uint32_t flags, void * hashbuffer, int hashmaxsize )
{
if(fp)
{
int i, maxtrack,maxside;
uint32_t crc32;
crc32 = 0x00000000;
if(track < 0)
{
track = 0;
maxtrack = fp->floppyNumberOfTrack;
}
else
{
maxtrack = track + 1;
}
if(side < 0)
{
side = 0;
maxside = fp->floppyNumberOfSide;
}
else
{
maxside = side + 1;
}
for(track=0; track < maxtrack; track++)
{
for(side=0; side < maxside; side++)
{
//////////////////////////////////////////
// Sector drawing
for(i=0;i<32;i++)
{
if( formats & (0x00000001<<i) )
{
track_hash( floppycontext, fp, track, side, i, &crc32 );
}
}
}
}
memcpy(hashbuffer,&crc32,sizeof(uint32_t));
}
return HXCFE_NOERROR;
}