Page 1 sur 2

ADFLib et PureBASIC

Publié : lun. 02/juin/2014 13:36
par djes
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 :

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);
; 

Re: ADFLib et PureBASIC

Publié : lun. 02/juin/2014 15:00
par Backup
il me semble qu'avec Total Commander , il existe un Pluggin qui peut creer/extraire de l'ADF

ici :
http://www.ghisler.com/plugins.htm
AmigaDX
3.6
2012/06/03 32+64 bit With this plugin you can extract/view ADF, DMS, ADZ, HDF, HDZ, DMP file types for Amiga Emulators (WinUAE, U*AE). You can also create/modify ADF files. If you are an old Amiga user who have installed WinUAE or other Amiga emulator then this plugin is for you. Source available.
mais , bon boulot quand meme
bien que ça risque d’intéresser peut de monde non ?

Re: ADFLib et PureBASIC

Publié : lun. 02/juin/2014 15:14
par Micoute
le principal est d'y prendre du plaisir ! non ?

Re: ADFLib et PureBASIC

Publié : lun. 02/juin/2014 15:17
par djes
Dobro a écrit :il me semble qu'avec Total Commander , il existe un Pluggin qui peut creer/extraire de l'ADF

ici :
http://www.ghisler.com/plugins.htm
AmigaDX
3.6
2012/06/03 32+64 bit With this plugin you can extract/view ADF, DMS, ADZ, HDF, HDZ, DMP file types for Amiga Emulators (WinUAE, U*AE). You can also create/modify ADF files. If you are an old Amiga user who have installed WinUAE or other Amiga emulator then this plugin is for you. Source available.
mais , bon boulot quand meme
bien que ça risque d’intéresser peut de monde non ?
Oui, je l'ai utilisé pour faire quelques essais. Le seul problème est que traiter quelques milliers de fichiers de la sorte devient un peu pénible... Pour le reste Micoute a raison ;)

Re: ADFLib et PureBASIC

Publié : lun. 02/juin/2014 16:31
par Ar-S
J'ai pas bien pigé, ça créé des ADF à partir de quoi, d'un lecteur physique de disquette amiga/usb ?
Il faut tout de même un emulateur genre WinUAE pour les lire ou pas, pas bien compris non plus ce amiga.exe ?

Re: ADFLib et PureBASIC

Publié : lun. 02/juin/2014 19:07
par djes
Non, sur Amiga, les démos et les jeux étaient parfois diffusés sous forme de disquettes plus ou moins cryptées, qu'on mettait dans la machine au démarrage, et parfois sous forme de fichiers. Le plus souvent c'était un seul gros fichier exécutable contenant tout, images, musiques et code.
Avec un disque dur, on peut facilement démarrer l'os, mettre tous les fichiers dans un dossier et les exécuter les uns après les autres. Sans disque dur, ou avec le lecteur Gotek, on est obligé de démarrer la machine avec une disquette d'amorçage (virtuelle dans le cas du gotek, c'est à dire un fichier adf ou dms), puis ensuite lancer le jeu ou la démo en cliquant sur son icône ou en tapant son nom dans une fenêtre de la console (genre dos ou ligne de commande).

Le programme d'exemple crée des disquettes virtuelles adf qui vont démarrer automatiquement et lancer la démo dans la foulée.
Pour l'utilisateur du lecteur gotek (ou de winuae), il suffira de sélectionner le fichier adf pour voir la démo correspondante sans avoir à rien faire.
Bon, en fait, winuae n'en a pas besoin, puisqu'il reconnaît les programmes Amiga dans avoir besoin de disquette de démarrage.
Je profite simplement de ce programme pour permettre à tous d'utiliser l'adflib, et donc de gérer les adf par code PureBASIC. Je sais que ça servira quand même à quelques utilisateurs, assez peu nombreux il est vrai.

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 13:06
par Flype
Et bien moi je trouve ça super. En plus c'est propre.
Je préfère de loin la méthode Import que OpenLibrary.
Merci djes, je pense que ça peut me servir.

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 13:09
par Backup
t'avais perdu l'adresse du forum ? :mrgreen:

nous aussi on trouve ça super ;)

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 13:15
par Flype
;-) Non, je la connais par coeur :)

Content de vous faire un coucou à tous. Toujours aussi actifs à ce que je vois !

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 13:18
par Backup
c'est toujours sympath de revoir les Anciens :D

Image

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 15:17
par Ollivier
Salut Flype, vraiment content de te voir aussi. J'espère que ça va. Moi, à part un intense mal de crâne inopiné, tout va bien, ça roule impeccable comme sur des chaussettes.

@DJ e/s

Excuse pour le hs, j'y connais rien aux Amiga. Mais là, c'était plus amigo qu'amiga.

Bon... Je vais me coucher...

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 18:51
par djes
Salut Flype :wink:

Ollivier> Pas de souci, nul n'est parfait :mrgreen:
Ps: J'ai commencé sur un PC un peu comme le tiens, maintenant il me sert d'ordinateur de bord pour ma ford "T"

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 18:58
par Flype
@Ollivier
Mon Amiga est largement plus puissant que ton PQ ;-)

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 19:28
par SPH
Flype a écrit :@Ollivier
Mon Amiga est largement plus puissant que ton PQ ;-)
Tu as quoi comme amiga ? Un peg ?

Re: ADFLib et PureBASIC

Publié : dim. 03/août/2014 19:45
par Flype
Oh non, juste un 1200 avec une carte accélératrice 1230 à 50 MHz.
Une bécane d'origine, de 1992, ma préférée ;-) parfaite pour entretenir ma nostalgie.