Jump to content

ISO Creator v1.16 build 2015-07-13 beta


UEZ
 Share

Recommended Posts

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

Link to comment
Share on other sites

  • Replies 76
  • Created
  • Last Reply

Top Posters In This Topic

@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 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Hi again,

Here's ae proof of concept just using AutoIt to read/write an iso.

Global 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   ;==>_Quit
Basically 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 by smashly
Link to comment
Share on other sites

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 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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

Hi,

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..lol

hence me skipping those checks..lol

Link to comment
Share on other sites

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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 :huh2:

And from your testing faster as well ;)

Cheers

Link to comment
Share on other sites

@smashly Great idea :huh2:

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 by smartee
Link to comment
Share on other sites

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 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@UEZ but cd2iso only works with the ISO9660 format, try any other and it fails :huh2:

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.

Link to comment
Share on other sites

Hmm, ok that what I assumed. It is not easy to handle all the available formats... :huh2:

Currently I'm in the office and can only test standard iso files.

Thanks,

UEZ

Edited 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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

Link to comment
Share on other sites

@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 :huh2:

Link to comment
Share on other sites

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 :huh2: 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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

Link to comment
Share on other sites

@smashly, :huh2: 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" ;)

Link to comment
Share on other sites

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.

Opt("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 by smashly
Link to comment
Share on other sites

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! :huh2:

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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 by smashly
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...