smashly Posted June 20, 2011 Posted June 20, 2011 Hi, thank you for sharing. I'm just curious as to why your using a third party iso maker, since autoit can read and write with it's own built in functions or even WinAPI udf create, read and write functions. I tried autoit's native fileopen, fileread, filesetpos and it works fine on accessing a ISO9660 cd/dvd in a drive. Basically the cd2iso can be translated into autoit native language completely. Cheers
UEZ Posted June 20, 2011 Author Posted June 20, 2011 (edited) @smashly: I searched for a very simple ISO creation program and decided to make my own one using a 3rd party app because I thought it will not easy to do it with AutoIt directly and I never searched for a way to do it with build-in function in AutoIt but that's what I want to do next. The interessting question is the comparison of both ways (build-in vs. 3rd party) regarding speed (benchmark). How long does it take to create the iso with your AutoIt native code and cd2iso? Anyone tried to use SPTI API from Microsoft? Br, UEZ Edited June 20, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smashly Posted June 20, 2011 Posted June 20, 2011 (edited) Hi again, Here's ae proof of concept just using AutoIt to read/write an iso.expandcollapse popupGlobal Const $ISO9660_SECTOR_SIZE = 2048 Global Const $ISO9660_SYSTEM_AREA_SECTORS = 16 Global Const $ISO9660_DATA_AREA_OFFSET = $ISO9660_SYSTEM_AREA_SECTORS * $ISO9660_SECTOR_SIZE Global $fd_in, $fd_out, $bSector, $Quit Global $sDrive = "d:";drive to read from, no trailing slash! HotKeySet("{Esc}", "_Quit") _main($sDrive, @ScriptDir & "\test2.iso") Func _main($in_path, $out_path) Local $ret = 0 ConsoleWrite(StringFormat("Copying drive... %s to %s", $in_path, $out_path) & @LF); If Not $ret Then $ret = _Open("\\.\" & $in_path, $out_path) If Not $ret Then $ret = _CopySystemArea(); If Not $ret Then $ret = _CopyDataArea(); _Cleanup() EndFunc ;==>_main Func _Open($in_path, $out_path) _Cleanup() $fd_in = FileOpen($in_path, 16) If $fd_in = -1 Then ConsoleWrite("Could not open: " & $in_path) Return 1 EndIf $fd_out = FileOpen($out_path, 18) If $fd_out = -1 Then ConsoleWrite("Could not create: " & $out_path) Return 1 EndIf Return 0 EndFunc ;==>_Open Func _CopySystemArea() Local $ret = 0 For $i = 1 To $ISO9660_SYSTEM_AREA_SECTORS $ret = _CopySector() If $ret Then ExitLoop Next Return $ret EndFunc ;==>_CopySystemArea Func _CopyDataArea() Local $ret, $num_sectors, $iCur, $iLast = -1 $num_sectors = (DriveSpaceTotal($sDrive) * 1024 * 1024) / $ISO9660_SECTOR_SIZE For $i = $ISO9660_SYSTEM_AREA_SECTORS + 1 To $num_sectors ; Corrected from UEZ $iCur = Round(100 * $i / $num_sectors) If $iLast <> $iCur Then $iLast = $iCur ConsoleWrite(StringFormat("Copying... %d %", $iLast) & @LF); EndIf $ret = _CopySector() If $ret Then ExitLoop If $Quit Then ConsoleWrite("Copying Aborted!" & @LF); Return 1 EndIf Next ConsoleWrite("Copying complete!" & @LF); Return $ret EndFunc ;==>_CopyDataArea Func _ReadSector() Local $nread = 0 $bSector = FileRead($fd_in, $ISO9660_SECTOR_SIZE) $nread = @extended Return ($nread <> $ISO9660_SECTOR_SIZE) EndFunc ;==>_ReadSector Func _WriteSector() Local $nwritten = 0 $nwritten = FileWrite($fd_out, $bSector) Return ($nwritten <> 1) EndFunc ;==>_WriteSector Func _CopySector() Local $ret = _ReadSector() If Not $ret Then $ret = _WriteSector() Return $ret EndFunc ;==>_CopySector Func _Cleanup() If $fd_in Then FileClose($fd_in) $fd_in = 0 EndIf If $fd_out Then FileClose($fd_out) $fd_out = 0 EndIf EndFunc ;==>_Cleanup Func _Quit() $Quit = 1 EndFunc ;==>_QuitBasically I very roughly translated cd2iso.cpp source. Mind you I skipped a couple of things like the Check to See if the CD is "CD001" and I also cheated in the way I get the total number of sectors..lol But that's what AutoIt is all about, improvising ways to write code as you see fit..lol Edit: As for time, it takes 4~5 mins for me to copy a 4.01 GB DVD disk (Retail STALKER CoP game) using this above code. Edit2: I tried the same DVD with your ISO Creator v0.98 build 2011-06-20 beta v1 and it created a 34KB iso..doh Edit3: I tried the same DVD with your ISO Creator v0.98 build 2011-06-20 beta v2 and it says maybe there's no media inserted. .. doh Cheers Edited June 20, 2011 by smashly
UEZ Posted June 20, 2011 Author Posted June 20, 2011 (edited) I overflew the source code which smartee provided but never did a deep analyse of it. When I see your code it looks very easy to understand.Anyway, I just installed MS Visual Studio to start with C++ soon.In line 51 there is a bug -> it must be For $i = $ISO9660_SYSTEM_AREA_SECTORS + 1 To $num_sectors otherwise ISO file is truncated with 2048 bytes.And now the suprise for me:cd2iso needs approx. 54 seconds to create the ISO from my v1 code and your code only 19 seconds - crazy!When did you download the versions? Because I did some modifications meanwhile! Timestamp should be 20.06.2011 10:18 CEST.Did you get the same size when you create manually with cd2iso the iso using the cmd box?Br,UEZ Edited June 20, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smashly Posted June 20, 2011 Posted June 20, 2011 I overflew the source code which smartee provided but never did a deep analyse of it. When I see your code it looks very easy to understand.Anyway, I just installed MS Visual Studio to start with C++ soon.In line 51 there is a bug -> it must be For $i = $ISO9660_SYSTEM_AREA_SECTORS + 1 To $num_sectors otherwise ISO file is truncated with 2048 bytes.And now the suprise for me:cd2iso needs approx. 54 seconds to create the ISO from my v1 code and your code only 19 seconds - crazy!When did you download the versions? Because I did some modifications meanwhile! Timestamp should be 20.06.2011 10:18 CEST.Did you get the same size when you create manually with cd2iso the iso using the cmd box?Br,UEZHi,Nice catch on the $num_sectors -1 part.The error I get with your code v1 and v2 is the cd2iso.exe/dll code that's causing it.If it can't find the "CD001" at the standard ISO9960 address then it fails.The standard address would be at (2048 * 16) + 1, the next 5 bytes after that should return "CD001".But it doesn't always seem to be that way.Major prob is the way cd2iso gets the number of sectors.The number of sectors can be retrieved at (2048 * 16) + 80, the next 8 bytes after that are the volume_space_size.But it doesn't always seem to be at that address..lolhence me skipping those checks..lol
UEZ Posted June 20, 2011 Author Posted June 20, 2011 I don't know whether a game CD/DVD is a little bit different because of any copy protection. Maybe the sector size is different depending on the CD/DVD format and thus the 0x00008000 might be different where .CD001. is saved. If I look at 0x00008050 I can see that the 1st 4 bytes are saved in litte endian the next 4 byte in big endian format (palindrome). Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smashly Posted June 20, 2011 Posted June 20, 2011 Hi, Yep I noticed litte endian and big endian for the 8 bytes for volume_space_size. But on some Data DVD 9960 when you query the address of volume_space_size there is only 0000000000000000. As for the copy protection of my game, it didn't have any problem copying using my example..lol The created iso loads and installs fine. (I use a NoDVD exe with any of my purchased legit games). Oh well, as I said I was just showing that AutoIt can do the same thing as the 3rd party app And from your testing faster as well Cheers
smartee Posted June 20, 2011 Posted June 20, 2011 (edited) @smashly Great idea My benchmarks favor v1 though: 609mb iso with v1: 53 secs 609mb iso with @smashly's solution: 1min 10secs I like smashly's solution alot though because its more "native" and I'm sure it beats the heck out of the dll route. @smashly does the md5 of the ISO match the original for the DVD that cd2iso refuses to copy? EDIT:added question,typo Edited June 20, 2011 by smartee
UEZ Posted June 20, 2011 Author Posted June 20, 2011 (edited) Can somebody test non standard ISO9660 (2048 bytes) CDs/DVDs with ISO Creator / cd2iso and the AutoIt script provided smashly if available?Is the content (MD5) the same? Any problem creating the ISO files? Etc.Thanks,UEZ Edited June 20, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smartee Posted June 20, 2011 Posted June 20, 2011 @UEZ but cd2iso only works with the ISO9660 format, try any other and it fails smashly's version however, because of the check it skips, treats all formats as ISO9660 and so attempts a save. However, sector copying is not done correctly and is unreliable thus MD5s of the images will not match as I just verified using a 609mb UDF ISO.
UEZ Posted June 20, 2011 Author Posted June 20, 2011 (edited) Hmm, ok that what I assumed. It is not easy to handle all the available formats... Currently I'm in the office and can only test standard iso files. Thanks, UEZ Edited June 20, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smashly Posted June 20, 2011 Posted June 20, 2011 Hi, You need to find out the standards for the formats you want to support. As for the checks add them in so that it abides to only 9960 standards and fails if not. cd2iso does nothing special, but it's a good way to learn header info of a cd. Cheers
AZJIO Posted June 20, 2011 Posted June 20, 2011 Checked the boot disk (CD-R). Created in 6 minutes. Checked in the program VirtualBox. Works fine (v1).v2 gave an error:An error has occured.Maybe no media is inserted to the drive!?! My other projects or all
smartee Posted June 20, 2011 Posted June 20, 2011 @AZJIO: The most reliable versions would be v1 that uses original exe, and post #34's version with the dll (because its source is almost identical to the exe source) everything else is "under construction" really
UEZ Posted June 20, 2011 Author Posted June 20, 2011 Checked the boot disk (CD-R). Created in 6 minutes. Checked in the program VirtualBox. Works fine (v1).v2 gave an error:This was my fault I forgot to modify the code also for v2. To work on both at same time is sometimes very exhausting!Updated both versions again and again and again ...Sorry,UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smashly Posted June 21, 2011 Posted June 21, 2011 Hi, I tested further with the MD5 side of things. I used a an iso created from a bin image using UltraIso. I used HashTab to retrieve an md5 of the iso that UtraIso saved. MD5 for UtraIso: B0B095F1B71C67C9F7652930E342E8F4 I mounted the new image with ms virtual CD: I used v1 Iso Creator with create MD5 to create an iso from the mounted iso. MD5 Generated by v1 Iso Creator: EAE477DB4922C616B228662C64546F89 I then used my own script to generate a new iso as well. MD5 for my own script using HashTab: EAE477DB4922C616B228662C64546F89 I then tried a UDF iso I created with UltraIso. MD5 for the UltraIso UDF iso: 12BD378D520D54684A93DF366B54188D Mounted the udf iso with daemon tools. Used my script to generate a new iso from the mounted UDF iso. MD5 for the UDF iso I created from my script: 12BD378D520D54684A93DF366B54188D. I couldn't test the UDF iso with cd2iso as it won't blind copy data. As for the sector size in the way I copy, it's got nothing to do with the layout of the created iso. Since I'm only writing byte data directly from the device being read. If there's no more bytes for the device to be read then the script stops. So for example I can read and write 1 byte at a time and the layout will still be the same regardless. When you look at at what cd2iso is doing, it's reading bytes and appending the bytes in 2048 blocks. It's no actually writing the header or system data area, it's merely copying the byte data being read from the device. It checks the for a header and reads it but it doesn't actually alter or correct the header it reads. It just copies the first 16 chunks and then proceeds to copy the rest of the chunks till the total amount of chunks is reached or the device doesn't have any more bytes to give. So as I've said cd2iso doesn't do anything magical, but it's does give you a good idea of how to check the 9960 iso format. Where this could be handy if you wanted to create an iso from scratch, eg: user adds files/folders and output them as an iso. Then the header data and chunck size is needed to write the iso 9960 standard. Cheers
smartee Posted June 21, 2011 Posted June 21, 2011 @smashly, The only way to reliably get the data size is by reading the header data for sector size and number of sectors (that is why cd2iso doesn't "blind copy" formats it doesn't recognize). I thought you knew that when you said "I also cheated in the way I get the total number of sectors..lol"
smashly Posted June 21, 2011 Posted June 21, 2011 (edited) Hi again, Here you can try both copy methods, the *cough* proper read following the 9960 and bail out if it can't read the CD001 or Sector count is invalid. You can also try the blind copy alternative with this example.expandcollapse popupOpt("MustDeclareVars", 1) Global $sDrive = "D:" ; In Drive Global $sOutIso = @ScriptDir & "\testWin7.iso" ; Out iso Global $ahFiles, $Quit, $iProgress, $iStart = TimerInit() HotKeySet("{Esc}", "_Quit") AdlibRegister('_ShowTip', 200) $ahFiles = _CD2ISO($sDrive, $sOutIso) ; Default Enforce 9960 ; Check for errors Switch @error Case 0 ConsoleWrite("Copying complete!" & @LF) Case 1 ConsoleWrite("ERROR: Could not open: " & $sDrive & @LF) Case 2 ConsoleWrite("ERROR: Could not create: " & $sOutIso & @LF) Case 4 ConsoleWrite("ERROR: Enforced ISO9960 unable to read SYSTEM_AREA_SECTORS." & @LF) Case 5 ConsoleWrite("ERROR: Enforced ISO9960 unable to write SYSTEM_AREA_SECTORS." & @LF) Case 6 ConsoleWrite("ERROR: Enforced ISO9960 CD001 not detected." & @LF) Case 7 ConsoleWrite("ERROR: Enforced ISO9960 invalid sector count." & @LF) Case 8 ConsoleWrite("ERROR: Enforced ISO9960 failed to finalise write SYSTEM_AREA_SECTORS." & @LF) Case 9 ConsoleWrite("ERROR: Unable to get sector count via DriveSpaceTotal()." & @LF) Case 10 ConsoleWrite("ERROR: Problem reading sector in DATA_AREA_SECTORS." & @LF) Case 11 ConsoleWrite("ERROR: Problem writing DATA_AREA_SECTORS to: " & $sOutIso & @LF) Case 12 ConsoleWrite("Copy Aborted By User!" & @LF) EndSwitch ;close file handles if open. _CloseFiles($ahFiles) ; $iEnforce9960 - 1 Makes the copy compliant with 9960 standard and reads the Source for 'CD001' and sector count based on 2048 sector size. ; 0 Ignores the 9660 standard and copies anyway, sectors are based $iSectorSize and the count is calculated by native autoit DriveSpaceTotal(). ; $iSectorSize - is only used if $iEnforce9960 is set to 0 ; Returns a 1D 2 element array, Array[0] InFile Handle, Array[1] OutFile Handle Func _CD2ISO($sDrive, $sOutIso, $iEnforce9960 = 1, $iSectorSize = 2048) Local $aInOut[2], $iSectors = 0, $bSector, $iSecSize, $iSectorsWritten $aInOut[0] = FileOpen("\\.\" & StringReplace($sDrive, "\", ""), 16) If $aInOut[0] = -1 Then Return SetError(1, 0, $aInOut) $aInOut[1] = FileOpen($sOutIso, 18) If $aInOut[1] = -1 Then Return SetError(2, 0, $aInOut) If $iEnforce9960 Then ; Read the first 16 sectors and write them to the output file. $iSecSize = 2048 For $i = 1 To 16 $bSector = FileRead($aInOut[0], $iSecSize) If (@extended <> $iSecSize) Then Return SetError(4, 0, $aInOut) If Not FileWrite($aInOut[1], $bSector) Then Return SetError(5, 0, $aInOut) Next ; Read the next sector (17) and check for the standard identifier "CD001" $bSector = FileRead($aInOut[0], $iSecSize) If Not StringInStr(BinaryToString(BinaryMid($bSector, 2, 5)), "CD001") Then Return SetError(6, 0, $aInOut) ; Check for the the total sector count, if this value is less then 17 then there's a problem $iSectors = Int(BinaryMid($bSector, 81, 4)) If $iSectors < 17 Then Return SetError(7, 0, $aInOut) ; Write sector 17 to the iso (contains header info) If Not FileWrite($aInOut[1], $bSector) Then Return SetError(8, 0, $aInOut) $iSectorsWritten = 17 Else ; Alternate method to copy blindly without the CD001 check $iSecSize = $iSectorSize $iSectors = (DriveSpaceTotal($sDrive) * 1024 * 1024) / $iSecSize If @error Then Return SetError(9, 0, $aInOut) EndIf ; Copy the DATA_AREA_SECTORS if $iEnforce9960, else it's copying data from first to last byte at the specified $iSectorSize For $i = ($iSectorsWritten + 1) To $iSectors $iProgress = Round(100 * $i / $iSectors) ; Using this in my tooltip $bSector = FileRead($aInOut[0], $iSecSize) If (@extended <> $iSecSize) Then Return SetError(10, 0, $aInOut) If Not FileWrite($aInOut[1], $bSector) Then Return SetError(11, 0, $aInOut) If $Quit Then Return SetError(12, 0, $aInOut) Next Return SetError(0, 0, $aInOut) EndFunc ;==>_CD2ISO Func _CloseFiles($aInOut) If $aInOut[0] Then FileClose($aInOut[0]) If $aInOut[1] Then FileClose($aInOut[1]) EndFunc ;==>_CloseFiles Func _Quit() $Quit = 1 EndFunc ;==>_Quit Func _ShowTip() Local $iMS = TimerDiff($iStart) ToolTip(StringFormat("Copying From: %s To %s", $sDrive, $sOutIso) & @LF & _ StringFormat("Progress: %d %", $iProgress) & @LF & _ StringFormat('Time Elapsed: %02d:%02d', Mod($iMS / 1000, 3600) / 60, Mod(Mod($iMS / 1000, 3600), 60)) & @LF & @LF & _ 'Press "Esc" to Abort', @DesktopWidth / 2, @DesktopHeight / 2, "", 0, 2) EndFunc ;==>_ShowTip Let me know how it goes, as it's not perfect, but neither is cd2iso..lol Cheers Edited June 21, 2011 by smashly
UEZ Posted June 21, 2011 Author Posted June 21, 2011 I added v3 version to the 1st post which is written without using any 3rd party appl. for creating the ISO file. Thanks to smashly for directing me to the right direction! It needs to be tested against several standard ISO 9660 CD/DVDs... Please post any problems, bugs, any suggestions, etc. Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
smashly Posted June 22, 2011 Posted June 22, 2011 (edited) Hi again, Looking good, but I can't test your code atm as I'm sitting by the beach with my laptop which isn't configured to play with code. A couple of things I would suggest would be when you check for CD001: Read the first 16 sectors and store or write them, then read sector 17. This way you can just check for CD001 from what's returned on sector 17 read. FileSetPos and then read 5 bytes on a real CD/DVD rom drive may fail at times (on a virtual cd drive it seems fine in most cases). When you check for CD001 don't forget that you should compare for cd001 (it's not case sensitive). This is why the code I posted above is done in the manner it is:If $iEnforce9960 Then ; Read the first 16 sectors and write them to the output file. $iSecSize = 2048 For $i = 1 To 16 $bSector = FileRead($aInOut[0], $iSecSize) If (@extended <> $iSecSize) Then Return SetError(4, 0, $aInOut) If Not FileWrite($aInOut[1], $bSector) Then Return SetError(5, 0, $aInOut) Next ; <-- This done so I don't use SetFilePos() as it sometimes fails on a real CD/DVD drive. ; Read the next sector (17) and check for the standard identifier "CD001" $bSector = FileRead($aInOut[0], $iSecSize) If Not StringInStr(BinaryToString(BinaryMid($bSector, 2, 5)), "CD001") Then Return SetError(6, 0, $aInOut);<-- Allows for CD001 or cd001 When I'm at home I'll try your code out. Cheers Edited June 22, 2011 by smashly
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now