Il m'a demandé de faire un petit convertisseur, pour créer automatiquement des ADF autoboot à partir de fichiers Amiga exe.
J'ai regardé du côté de l'excellente bibliothèque de fonctions ADFLib, mais je n'ai pas trouvé de DLL facile à utiliser en PureBASIC. Du coup j'ai légérement modifié les sources et le projet pour créer une bibliothèque statique directement utilisable en PureBASIC, grâce à Dev-C++.
Le résultat est donc la bibliothèque statique compilée adflib.a, et un exemple qui crée des ADF grâce à un modèle de fichier ADF en y copiant les programmes Amiga sélectionnés. J'ai aussi joint les fichiers projets pour Dev-C++.
Vous trouverez l'archive complète sur PBFrance (merci à GallyHC) :
http://www.pbfrance.com/?url=source&cmd=viewer&val=29
Voici le code d'exemple :
Code : Tout sélectionner
;*****************************************************************************
;
; ADFLib for PureBASIC example
; Creates ADF files from a master and copy exe files from a source directory.
;
; (C)opyright J. Benoist (djes) on 2014
;
; ADFLib documentation is in the main ADFlib-master directory.
;
; Notes :
; Beware of non-checked headers !
; C sources modified strdup->_strdup to avoid msvcrt dependancy
; Static library .a created, no dll needed.
;
;*****************************************************************************
IncludeFile "incpb\adf_str.pbi"
IncludeFile "incpb\adf_blk.pbi"
EnableExplicit
Import "adflib.a"
adfEnvInitDefault()
adfEnvCleanUp()
adfInstallBootBlock(*vol,*code) ;PREFIX RETCODE adfInstallBootBlock(struct Volume *vol,uint8_t*);
adfMount(*dev, nPart.i, readOnly.i) ;PREFIX struct Volume* adfMount( struct Device *dev, int nPart, BOOL readOnly );
adfUnMount(*vol) ;PREFIX void adfUnMount(struct Volume *vol);
adfVolumeInfo(*vol) ;PREFIX void adfVolumeInfo(struct Volume *vol);
adfMountDev(filename$, readOnly.i) ;PREFIX struct Device* adfMountDev( char* filename,BOOL ro);
adfUnMountDev(*dev) ;PREFIX void adfUnMountDev( struct Device* dev);
adfCreateFlop(*dev, volName$, volType.l);PREFIX RETCODE adfCreateFlop(struct Device* dev, char* volName, int volType );
adfDeviceInfo(*dev) ;PREFIX void adfDeviceInfo(struct Device *dev);
adfCreateDumpDevice(filename$, cylinders.l, heads.l, sectors.l);PREFIX struct Device* adfCreateDumpDevice(char* filename, int32_t cyl, int32_t heads, int32_t sec);
adfToRootDir(*vol) ;PREFIX RETCODE adfToRootDir(struct Volume *vol);
adfCreateDir(*vol, parent.l, name$) ;PREFIX RETCODE adfCreateDir(struct Volume* vol, SECTNUM parent, char* name);
adfChangeDir(*vol, name$) ;PREFIX RETCODE adfChangeDir(struct Volume* vol, char *name);
adfParentDir(*vol) ;PREFIX RETCODE adfParentDir(struct Volume* vol);
adfRemoveEntry(*vol, parent.l, name$) ;PREFIX RETCODE adfRemoveEntry(struct Volume *vol, SECTNUM pSect, char *name);
adfGetDirEnt(*vol, parent.l ) ;PREFIX struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect );
adfGetRDirEnt(*vol, parSect.l, recurs.l ); PREFIX struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs );
printEntry(*entry) ;PREFIX void printEntry(struct Entry* entry);
adfFreeDirList(*list) ;PREFIX void adfFreeDirList(struct List* List);
adfFreeEntry(*Entry) ;PREFIX void adfFreeEntry(struct Entry *);
adfRenameEntry(*vol, oldDir.l, old$, newDir.l, new$) ;PREFIX RETCODE adfRenameEntry(struct Volume *vol, SECTNUM, char *old,SECTNUM,char *pNew);
adfSetEntryAccess(*Volume, parent.l, name$, newAcc.l) ;PREFIX RETCODE adfSetEntryAccess(struct Volume*, SECTNUM, char*, int32_t);
adfSetEntryComment(*vol, parSect.l, name$, newCmt$) ;PREFIX RETCODE adfSetEntryComment(struct Volume*, SECTNUM, char*, char*);
adfOpenFile(*vol, name$, mode$) ;PREFIX struct File* adfOpenFile(struct Volume *vol, char* name, char *mode);
adfFlushFile(*file) ;PREFIX void adfFlushFile(struct File *file);
adfCloseFile(*file) ;PREFIX void adfCloseFile(struct File *file);
adfFileRealSize(size.l, blockSize.l, *dataN, *extN);PREFIX int32_t adfFileRealSize(uint32_t size, int blockSize, int32_t *dataN, int32_t *extN);
adfReadFile(*file, n.l, *buffer) ;PREFIX int32_t adfReadFile(struct File* file, int32_t n, uint8_t *buffer);
adfEndOfFile(*file) ;PREFIX BOOL adfEndOfFile(struct File* file);
adfWriteFile(*file, n.l, *buffer) ;PREFIX int32_t adfWriteFile(struct File *file, int32_t n, uint8_t *buffer);
adfFileSeek(*file, pos.l) ;PREFIX void adfFileSeek(struct File *file, uint32_t pos);
EndImport
;*****************************************************************************
Procedure TheEnd(Msg$)
MessageRequester("Error", Msg$, #PB_MessageRequester_Ok)
End
EndProcedure
;*****************************************************************************
Define ExeFilename$, Dest$
ExeFilename$ = OpenFileRequester("Please choose some exe files","","Exe files|*.exe|All files|*.*", 0, #PB_Requester_MultiSelection)
If ExeFilename$ = ""
TheEnd("No file selected...")
EndIf
Dest$ = PathRequester("Please select ADFs destination directory", GetPathPart(ProgramFilename()))
If Dest$ = ""
TheEnd("No destination choosen...")
EndIf
While ExeFilename$
Debug "---------------------------------------"
Debug "Processing file " + ExeFilename$
Debug " to dir " + Dest$
Define *dev.Device, *vol.Volume
Define NewADFFilename$
Define *file.File, Length.l, *MemoryID, bytes.l, written.l
NewADFFilename$ = Dest$ + GetFilePart(ExeFilename$) + ".adf" : Debug "New ADF file to create : " + NewADFFilename$
If CopyFile("MasterA500-1200.adf", NewADFFilename$)
;Master could also be created with things like this, but it wouldn't be so easily customisable by user.
;*dev = adfCreateDumpDevice("newfloppy.adf", 80, 2, 11)
;adfCreateFlop(*dev, "empty", #FSMASK_DIRCACHE )
Debug "Copying master file"
adfEnvInitDefault()
*dev.Device = adfMountDev(NewADFFilename$ , #False);
*vol.Volume = adfMount(*dev, 0, #False);
adfRemoveEntry(*vol, *vol\curDirPtr, "Intro.exe") : Debug "Removing original intro.exe file"
*file = adfOpenFile(*vol, "Intro.exe", "w") : Debug "Creating new intro.exe"
If *file <> 0
If ReadFile(0, ExeFilename$) : Debug "Opening original exe file"
Length = Lof(0) ; Lit la taille en octets du fichier
If Length <> 0
*MemoryID = AllocateMemory(Length) : Debug "Allocating exe memory : " + Str(Length) + " bytes"
If *MemoryID
bytes = ReadData(0, *MemoryID, Length) : Debug "Copying exe from original path"
If bytes <> 0
written = adfWriteFile(*file, Length, *MemoryID) : Debug "... to ADF."
If written <> bytes
MessageRequester("Error", "Something wrong occured while writing " + ExeFilename$ + " in the ADF", #PB_MessageRequester_Ok)
EndIf
Else
MessageRequester("Error", "Can't read " + ExeFilename$ + " content", #PB_MessageRequester_Ok)
EndIf
Else
MessageRequester("Error", "Can't allocate " + Str(Length) + " bytes for " + ExeFilename$, #PB_MessageRequester_Ok)
EndIf
Else
MessageRequester("Error", ExeFilename$ + " is empty...", #PB_MessageRequester_Ok)
EndIf
Else
MessageRequester("Error", "Can't open " + ExeFilename$, #PB_MessageRequester_Ok)
EndIf
adfCloseFile(*file)
Else
MessageRequester("Error", "Can't create Intro.exe in the " + GetFilePart(ExeFilename$) + " adf file", #PB_MessageRequester_Ok)
EndIf
adfUnMount(*vol)
adfUnMountDev(*dev)
Else
TheEnd("Can't copy master file 'MasterA500-1200.adf' to '" + ExeFilename$ + ".ADF'")
EndIf
adfEnvCleanUp()
ExeFilename$ = NextSelectedFileName()
Wend
Debug "--- END"
MessageRequester("Information", "Done.", #PB_MessageRequester_Ok)
End
;--- Feel free to try these others functions
; *cell.List = adfGetDirEnt(*vol, *vol\curDirPtr);
; *List = *cell
; While *cell
; *Entry.Entry = *cell\content
; If *Entry\type = #ST_DIR
; Debug *Entry\name$ + "/"
; Else
; Debug *Entry\name$
; If *Entry\name$ = "Intro.exe"
; adfRemoveEntry(*vol, *vol\curDirPtr, *Entry\name$)
; adfRenameEntry(*vol, *vol\curDirPtr, *Entry\name$, *vol\curDirPtr, "Test")
; *file.File = adfOpenFile(*vol, *Entry\Name$, "rw");
; adfFlushFile(*file)
; adfCloseFile(*file)
; EndIf
; EndIf
; *cell = *cell\Next;
; Wend
;
; adfFreeDirList(*List);
;