ADFLib et PureBASIC
Publié : lun. 02/juin/2014 13:36
Un ami vient d'acheter un lecteur USB Gotek pour remplacer son lecteur de disquettes Amiga. Seul problème, le lecteur ne lit que les ADF et les DMS, et les démos et intros nécessitent un environnement genre Workbench pour démarrer, ou de taper leur nom dans un shell/CLI.
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 :
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);
;