SCSI - Small Computers System Interface
CD-R writers revealed
There is no literature about low level CD-R burning. This article
discloses the SCSI3 command sequence to burn a track on a CD-R using
a MMC-1 device.
This page talks about SCSI CD recorders. Because of many requests that I had
received by mail, and since some programmers reported their experiences with ATAPI CD
recorders, I have added a paragraph that deals with ATAPI devices.
Please before sending mails check whether your answer is already in this web page.
Thank you.
Igor, a professional programmer from Russia
reports the following (dec. 3rd, 2003):
- he wrote his code in C++ for his ATAPI Sony CD Recorder. The only things
that he had to change in the assembly code provided in this article (apart from being
translated into C++) are the following:
- use MODE SELECT (10) instead of MODE SELECT (6) to send the Write Parameters Mode
Page to the target device
- do not send any block descriptor together with the Write Parameters Mode Page
Here is the code that Igor wrote to send the MODE SELECT (10) to his target:
BYTE buffer[60];
SRB_ExecSCSICmd srbExec;
memset(buffer, 0, sizeof(buffer));
memset(&srbExec, 0, sizeof(srbExec));
srbExec.SRB_Cmd = (SRB_DIR_OUT | SC_EXEC_SCSI_CMD);
srbExec.SRB_HaId = SCSI_HaId;
srbExec.SRB_Target = SCSI_Id;
srbExec.SRB_Lun = SCSI_Lun;
srbExec.SRB_Flags = SRB_EVENT_NOTIFY;
srbExec.SRB_PostProc = (PFNPOST)hEventSRB;
srbExec.SRB_SenseLen = SENSE_LEN;
srbExec.SRB_CDBLen =10;
srbExec.SRB_BufPointer = buffer;
srbExec.SRB_BufLen = sizeof(buffer);
srbExec.CDBByte[0] = SCSI_MODE_SEL10;
srbExec.CDBByte[1] = 0x10; // Set PF bit = 1
srbExec.CDBByte[8] = sizeof(buffer); // Allocation Length
buffer[2] = 0x20; // Set medium type, no block descriptors
buffer[8] = 0x5; // don't save parameters; mode page #5
buffer[9] = 0x32; // page size = 50 bytes
buffer[10] = TrackMode | (isTest ? 0x10 : 0x0);
buffer[11] = 0x04 | (IsMultiSession ? 0xC0 : 0x0); // data track
buffer[12] = 0x08; // MODE-1 CDROM
buffer[13] = 0x00; // CD-ROM disc
buffer[23] = 0x96; // Audio Pause Length = default value is 150
buffer[58] = 0x08; // ? (taken from cdrecord)
// execute
Execute(&srbExec)
- Igor says that he tested Adaptec's ASPI 4.60 with his ATAPI drive and it works OK
- talking about cdrecord, Igor also says that cdrecord has 2 very good switches:
"-v" and "-VV". They tell cdrecord to print all data it sends and receives
to/from the target CD Recorder. It helped him solve the problem with MODE SELECT command
and find out how to load/eject the medium
XcalibEr (may 26th, 2003) and
Nils from Germany
(july 31th, 2003) both confirm the experience reported by Richard (see below).
Richard, a friend programmer from Germany
told me that the project described in this page works with his ATAPI CD
writer as well, with no modifications. The only trick to get the result is the following:
- install Adaptec's ASPI support on your PC as usual
- replace WNASPI32.DLL with the one that comes with Nero Burning software
I did not test this because I have no ATAPI CD writer, neither I use Nero. But what
Richard says makes a big sense, because ATAPI writers derived their command set from
SCSI devices, and they work in a very similar manner. Furthermore: Adaptec only cares
about SCSI devices, so WNASPI32.DLL that comes from them only works with SCSI devices.
The company that wrote Nero, on the other hand, they want Nero to work both with SCSI and
ATAPI devices, so they developed themselves (or asked Adaptec to develop for them)
a version of WNASPI32.DLL that works with ATAPI devices.
CD-R writer device type didn't exist in the SCSI2 standard. This limit
has been suppressed in the SCSI3 standard.
CD-R writers (as well as CD-RW, DVD-R and DVD-RW writers) respond to the
following sets of SCSI3 commands:
- SPC (SCSI3 Primary Commands)
- MMC (SCSI3 Multi Media Commands)
This situation is favorable for the programmer that finally can easily
deal with these kind of devices.
Please note that more than one MMC specification and more than one SPC
specification have been released by T10 in order
to keep pace with the evolving technology.
Currently MMC spans from release 1 to 4, and SPC from release 1 to 3.
You can download MMC-1, MMC-2, MMC-3, MMC-4, SPC-1, SPC-2 and SPC-3
specifications from T10's site.
For each CD-R, CD-RW, DVD-R, or DVD-RW writer there exists a MMC/SPC pair
of commands sets according to the "generation" of the device. For example
my Plextor CD-R 820 writer responds to MMC-1 and SPC-1 specifications.
Newer devices respond to MMC-2, SPC-2 and later. Download the specification
for your device from T10's site. If you don't
know which generation your device is, download MMC-1 and SPC-1 and you
will be safe: generations are backward compatible, and this choice will
give you a solid starting point.
When programming any device of this kind you should also be provided, as
usual, with the SCSI command set reference released from the
maunfacturer of the device. This requirement is not strictly required
but highly recommended. I used the manufacturer's reference mainly to
confirm that my device was a first generation (MMC-1/SPC-1), to interpret
some vendor unique sense data, and to get info about some minor features.
Objective of this project is burning a file into a MODE-1 track on
a blank CD-R disc, and close the disc.
The file to burn should have been already prepared on the hard disk.
If the file were an ISO 9660 file system image
file, then the resulting disc would be a true ISO 9660 MODE-1 CD-R.
Along the way we will also see:
- how to get information about the disc inserted into a CD device
- how to read a sector
- how to clone (=duplicate) an ISO 9660 file system MODE-1 CD-ROM
This project puts the basis for the following further developments: write
more than one track on a CD-R disc, duplicating audio CDs and DVDs.
The only true document you should be in possess of to follow and understand
this project is the MMC-1 specification published by the T10
technical Committee.
You can download it here
(search for SCSI-3 Multimedia Commands (MMC){Date: 1997/05/06, Rev: 10a, Status: Published,
Project: 1048-M, File: mmc-r10a.pdf (942631 bytes)}).
I strongly suggest to print and bind a copy of it, and to keep it at hand.
IMPORTANT: this document will be frequently recalled through all this article.
It will be referred to as the T10-MMC-1 spec for short.
To implement this project you should be provided with a MMC-1 compliant
CD-R (or CD-RW) writer device. Because generations are backwards
compatible, any MMC-2, MMC-3 or MMC-4 compliant CD-R or CD-RW writer
should work as well.
Possibly you should be provided also with a printed copy of the SCSI
command set reference released by the manufacturer of your device.
This is not strictly necessary, but very useful.
In case you don't know whether your device is compliant to any of the
MMC specifications, you can always start implementing this project with
no fear, because usually devices protect themselves against wrong or
unexisting commands. All that you could get returned (in the worst case)
should be a check condition status that, followed by a request sense, will
help discovering unsupported commands or features.
Test mode in a CD-R/CD-RW writer device acts like true burning of
a CD-R disc but the laser is turned off, and nothing is actually
written on the media.
This mode is used, as you can easily guess, for testing purposes.
It has proven to be very useful in my burning experiments, making me save
dozens of bucks in badly burned medias because of wrong SCSI command
sequences.
I experimentally discovered that test mode is valid and possible only when
issuing WRITE 10 SCSI3 commands, and *not* when issuing other
commands like CLOSE TRACK/SESSION.
When you send the target a CLOSE TRACK/SESSION command in test mode you
will *always* be returned a check condition from the target
even if everything in the system is perfectly OK.
(Test mode is a writing parameter, and it is sent to the target by means of
the Write Parameters Mode Page.)
I am the unfortunate owner of a Plasmon 120 CDs juke box, as described here, and as you can see in this
photo.
I had the idea to utilize it as a CD duplicator. In other words I
would like to get up to 120 copies of a MODE-1 CD-ROM leaving my juke box
working unattended.
Here are described, in short, all the steps that I performed to reach the
objective of duplicating n copies of a CD-ROM:
- I checked the Plasmon product list to see the CD-R writer
device that would fit into my juke box: it is model CDR32XD-F
- I sent a mail to Plasmon UK to get the SCSI command set for their
CDR32XD-F unit. Soon I was sent by e-mail the required document attached
in PDF format. Many thanks to Plasmon UK for providing me with the
required documentation
- I printed and bound a copy of the PDF file, and started studying it.
I discovered the following:
- Plasmon CDR32XD-F is produced by Plextor, and is equivalent to
Plextor PX-W1210TS (a 12x CD-R writable and 10x CD-RW rewritable
device)
- the SCSI3 command set for Plextor devices strictly matches the
MMC-1 specification released by T10 Technical Committee, hence Plasmon
CDR32XD-F and all Plextor models are MMC-1 compliant devices
- all models from Plextor share the same SCSI3 command set
that I was sent by Plasmon UK
- casually the SCSI CD-R writer in my laboratory is a Plextor 820
(bought in 1999)
- this lucky circumstance made me start experimenting using my Plextor
820, without buying the Plasmon CDR32XD-F (for the moment)
- my first homework has been getting info about the disk inserted into
the device
- then I started burning experiments in test mode trying to
determine the correct SCSI3 command sequence to correctly burn a file
into a track of a blank CD-R disc, and close the disc
- I had to make several dozen different experiments before finding
a reasonable SCSI3 command sequence that would not end up in a check
condition from the target
- during all these experiments I have been wasting time because of some
major difficulties, the most time consuming of which were:
- first of all I tried a session at once style of writing, but
whichever the cue sheet I had prepared, the first WRITE 10 command
has always been blocking the target, so badly that I had to write
a routine to reset the SCSI bus; thus I decided to abandone
session at once style of writing and started track at once
- although I soon discovered the correct SCSI command sequence
in track at once mode, I continued receiving a check condition from the
target at the end of the command sequence, making me think that
the sequence was wrong; actually the sequence was right, but I
was using test mode to economize recordable discs, and it took
me a discrete amount of time before discovering that CLOSE
TRACK/SESSION command returns check condition when burning in
test mode
- when I was able to correctly burn a track in a CD-R I had to face
some bad ISO 9660 file system image files generated by Easy CD Creator
rel. 3.01, that made me waste many and many hours (before discovering
that Easy CD Creator rel. 3.5 generates good ISO 9660 image files)
- finally I found a complete solution to clone MODE-1 CD-ROMs
For you to understand next paragraphs you need to know about the following
issues.
The original CD, according to the red book, was designed to
accomodate audio data tracks and was organized in frames.
An audio CD contains a sequence of frames in a spiral fashion, starting near
the center hole of the disc and evolving up to the outer diameter of it.
Although frames are sequentially ordered, CD readers/writers are *direct
access* devices because of their capability to access the media randomly. Every
frame is 2352 bytes long, and can accomodate one 75th of second of audio
sampled at 44 kHz (75 frames hold one second of audio).
Each frame in the disc is not addressed by its ordinal position from
the beginning of the spiral, but is addressed in a MM:SS:FF (minutes, seconds,
frames) notation that is more suitable when dealing with audio.
A common 74 minutes audio CD holds 74x60x75 = 333.000 frames.
When someone had the great idea to use CDs for holding computer
data, a new specification was written (the yellow book) and the
new CD type was named MODE-1 CD-ROM.
The yellow book introduced many changes:
- the "frame" was renamed "sector" or, better, block
- MM:SS:FF addressing scheme was substituted by the more intuitive
LBA (Logical Block Address) addressing scheme
- each block would have been rearranged to contain 2048 bytes of
computer data, plus some bytes of EDC (Error Detection Code) and
some bytes of ECC (Error Correction Code)
A 74 minutes audio CD would have been seen like a spiral stream of
333.000 blocks starting at LBA 0 and ending at LBA 332.999. Usually
CDs hold some blocks more because of the manufacturing process.
You see that 333.000 blocks at 2 kB per block make a 640 MB (actually
666 MB) CD-ROM.
The introduction of EDC and ECC was necessary to maximize the probability
that bytes would have been read exactly as they were written. You should think
that reading the famous pits on the CD surface is not a deterministic
process, so to speak, and yet the eight to fourteen byte coding
scheme "trick" has been adopted to reduce errors.
You should also think that one or more wrong bytes in a audio track are
not perceived by the human ears, but one or more wrong bytes in a
computer data track would be absolutely unacceptable. This is why the original
2352 bytes of the original frame have been rearranged in a 2 kBytes of
user data and some EDC plus ECC to guarantee that bytes are properly
returned when reading pits on the surface of the disc.
Curiosity: MODE-2 CD-ROM is almost identical to MODE-1 CD-ROM, the difference
being in that EDC and ECC are not used and the space is used to accomodate
more user data. This results in MODE-2 CD-ROM being more capable but less
reliable than MODE-1 CD-ROM. MODE-2 CD-ROMs are used to hold, say, audio
and video streams of data (e.g.: mpeg videos, etc.).
Once the yellow book standardized CD-ROM data discs, everybody could start
writing 2 kBytes blocks of data here and there on the CD surface. But this was
not sufficient to keep ordered files into CD-ROMs. For this reason the
ISO 9660 file system (formerly High Sierra) was invented
to standardize the way of writing files and directories into CD-ROMs.
Because of some ISO 9660 file system limits, the Joliet specification
was successively released. I think you know about these issues.
The ISO 9660 (or Joliet) specification can be found on the web, but for
the purpose of this project, duplicating CDs, it is not important as you
will soon realize. The only thing that we must take care of is that
both ISO 9660 and Joliet file systems must start at LBA 16 of a MODE-1 CD-ROM.
Blocks from LBA 0 to LBA 15 can contain any data, they don't matter.
Usually these blocks are filled with zeroes.
Final note: the orange book was successively released to introduce
CD-R, the kind of disc we are going to deal with in this project. CD-ROM
and CD-R, from a MODE-1 perspective, are perfectly equivalent. The only
difference being that the former is printed with a "glass master" in
huge plants, and the latter can be burned at home with any CD-R writer.
Commands involved in writing a MODE-1 CD-ROM are:
- TEST UNIT READY: this is a very basic command that you already
should know about; it must be issued at the beginning of any SCSI command
sequence to check whether a device is ready to accept further commands
- READ DISC INFORMATION: this command retrieves the Disk
Information Block for the disc inserted into the device. This block
is described in Table 130 of the T10-MMC-1 spec, and is used to hold
all the info retrieved by this command. Bits 1 and 0 in byte 2 in the
Disk Information Block (Disc Status) are described in Table 131
of the T10-MMC-1 spec, and we will use them to recognize wheter the disc
inserted into the writer is empty or not. Please note that byte 3 in the
Disk Information Block (Number of First Track on Disc) is #1
even if the disc is empty
- READ TRACK INFORMATION: this command retrieves the Track
Information Block for any given track of the disc
inserted into the device. The block is described in Table 142 of the
T10-MMC-1 spec. We will use this command to get info about track #1
in the empty disc inserted into the writer device, and in particular to
retrieve the LBA start address of that track. Issuing this command
for the purposes of this project is superfluous because we are always
going to burn empty discs, and #1 track start address in an empty disc
is always LBA zero
- MODE SELECT: this command is used to send the Write Parameters
Mode Page (WPMP) to the target device. This "mode page" will
be covered next paragraph
- WRITE 10: this command is used to actually burn blocks of
user data into the CD-R disc. The behaviour of this command is influenced
by the values that have been sent to the device in the Write Parameters
Mode Page. You can burn up to 32 blocks (=64 kB of data) each WRITE 10.
A sequence of WRITE 10 commands is used to burn user data to the media.
The first WRITE 10 command takes 10 to 20 seconds before actually burn
data because the target device needs to spin up the disc and to calibrate
the laser beam intensity. Any successive WRITE 10 command is very fast
because the disc is already spinning and the laser beam has already been
calibrated
- SYNCHRONIZE CACHE: this command must be issued immediately after the last
WRITE 10 command in a sequence. It assures that all remaining data in the
data buffer of the writer device are actually burned to the media
- CLOSE TRACK/SESSION: as its name says, this command is used
to close either a track or a session. Closing a track/session makes the
target device burn the lead in and the lead out to the
CD-R, completing the process of writing the track/session (important note:
CLOSE TRACK/SESSION returns *check condition* in test mode). We will
call this command with bytes 2 and 5 of the CDB respectively set to 2
and 0 (byte 2 is described at Table 118 in the T10-MMC-1 specification)
- READ 10: this command reads one or more blocks in a burned disc.
It is not required when writing, but we will use it to generate an ISO
9660 image file from an existing CD-ROM for the purpose of duplicating it
The Write Parameters is is one of several mode pages defined for the kind
of devices we are going to deal with. It is described in table 108 of the
T10-MMC-1 spec, and contains parameters needed for the correct execution
of WRITE 10 command at write time.
Not all the values in the WPMP will be necessarily used. They will be used
as applicable at writing time. If one or more paramenters hold values
incompatible with the track being burned, a check
condition status is returned by the target when the WRITE 10 is attempted.
The WPMP is sent to the target, as any other mode page, by means of a
MODE SELECT command. The WPMP is sent togheter with a 8 bytes long Block
Descriptor (see MODE SELECT command).
The following are the parameters that we will use to burn a MODE-1 CD-ROM
track and close the disc (please refer to Table 108 in T10-MMC-1 spec). You can use different
parameters as suggested in square brackets according to your eventual needs,
provided you know what you are going to do. Please note that special
comments are given only when T10-MMC-1 spec alone is not sufficient
to understand how to set a parameter:
- byte 0: 0x05 (don't save parameters; mode page #5)
- byte 1: 0x32 (page length)
- byte 2: 0x01 (no test mode [if you want to run in test mode
set bit 4 to 1]; track at once)
- byte 3: 0x46 (Multi-session: Next session not allowed [you can
set it differently, see table 110 in T10-MMC-1 spec]; Track Mode: data
track, recorded uninterrupted, digital copy permitted [see paragraph
3.1.10 and Table 61 in T10-MMC-1 spec])
- byte 4: 0x08 (MODE-1 CD-ROM [see Table 111 in T10-MMC-1 spec])
- byte 5: 0x00 (reserved)
- byte 6: 0x00 (reserved)
- byte 7: 0x00 (no host application code)
- byte 8: 0x00 (session format: CD-ROM disc [see table 112 in
T10-MMC-1 spec])
- byte 9: 0x00 (reserved)
- bytes 10 to 13: all zeroes (Packet Size not required when
writing track at once, we are not using packet writing)
- bytes 14 and 15: all zeroes (Audio Pause Length not used when
writing MODE-1 CD-ROM)
- bytes 16 to 31: all zeroes (Media Catalog Number not required
[see table 63 in T10-MMC-1 spec])
- bytes 32 to 47: all zeroes (International Standard Recording Code
not required, [see table 65 in T10-MMC-1 spec])
- byte 48: 0x00 (Sub-header Byte 0 left to zero)
- byte 49: 0x00 (Sub-header Byte 1 left to zero)
- byte 50: 0x00 (Sub-header Byte 2 left to zero)
- byte 51: 0x00 (Sub-header Byte 3 left to zero)
My experiences with CD-R and CD-RW writer devices are enclosed in the DLL
that I am going to introduce.
The DLL is written in win32asm. The source code is given, and you can
compile it yourself, or download a ready to use compiled version
of it (at the end of this paragraph). To compile the DLL you must have
MASM32 v.6 installed in your PC. You can download the free compiler at
hutch's site.
The source code is either well commented or self explanatory,
but you can send me inquiries to help clarifying any instruction that
(despite my efforts to make it clear) might result obscure.
C++ programmers can write their own version of the DLL in c++, although
this would result in complicating a simple thing.
Commented C++ source code examples that utilize the DLL are also given
in the next paragraphs.
The DLL offers 5 built in functions, 2 of which (FFAspiStart and FFAspiStop)
are already described in Build your own ASPI DLL
project. The functions are:
- FFAspiStart: to start ASPI operations; takes one parameter:
the handle (HWND) of the main window of the calling program, used to send
messages to the user in case ASPI can't be properly initialized
- FFAspiStop: to stop ASPI operations; takes no parameters
- FFDiscInfo: useful to get info about a disc inserted into a
CD-R or CD-RW writer device. It sends the target a READ DISC INFORMATION
SCSI3 command, retrieves the Disc Information Block, and makes it
readable to humans; the function takes the following parameters:
- (HWND) the handle to the main window of the calling program
- (int) the Host Adapter card number: usually 0 unless you have
more than one host adapter card inserted into the bus of the PC
- (int) the SCSI Id of the target
- (int) the SCSI LUN of the target
An example of using this function is given here
- FFCDReadSect: this function reads a block (a sector) in a disc
inserted into a CD-R or CD-RW writer device; it sends the target a READ
10 SCSI3 command, gets the block, and returns 2048 bytes of data; the
function takes the following parameters:
- (HWND) the handle to the main window of the calling program
- (int) the Host Adapter card number: usually 0 unless you have
more than one host adapter card inserted into the bus of the PC
- (int) the SCSI Id of the target
- (int) the SCSI LUN of the target
- (int) number of the sector to read: LBA address of the block
- (char*) pointer to the buffer that will receive the data
An example of using this function is given here
- FFCDWrite: this function burns a file into a MODE-1 track in
a blank CD-R disc and closes the disc. The track is burned in track
at once style of writing; if the file were a ISO 9660 image you get a
perfect CD-ROM of user data. Essentially this function does the following:
- check the target device for readyness
- read the Disc Information Block for the media inserted into the
target device; exit if the CD-R disc is not empty
- read the Track Information Block for track #1 in the disc; as
already described above this command is superfluous because track
#1 in an empty disc always starts at LBA number zero
- send the Write Parameters Mode Page by means of a MODE SELECT command
- read 8 kB from the input file and burn 4 blocks into the CD-R disc
- the previous step is repeated until the end of the input file
is reached (see the note (*) below)
- synchronize the cache to flush residual data from the buffer to
the disc
- close the track
The function should be passed the following parameters:
- (HWND) the handle to the main window of the calling program:
it serves for the purpose of sending messages to the user in case the
target returns check condition
- (int) the Host Adapter card number: usually 0 unless you have
more than one host adapter card inserted into the bus of the PC
- (int) the SCSI Id of the target: obvious
- (int) the SCSI LUN of the target: obvious as well
- (HANDLE) the handle of the file to be burned: the calling
program is responsible for opening and closing the image file
An example of using this function is given here.
(*) Note: the last call to WRITE 10 in FFCDWrite always burns 4 blocks (8 kB of user data), even if the
last read from the file returned less than 8 kB. This is not correct
but perfectly acceptable. It's up to you, if you want, to modify
FFCDWrite to burn less than 4 blocks according to the actual number of
bytes read in the last access to the input file. I use FFCDWrite *as is*
and the garbage that it leaves at the end of the track does not affect
the functionality of my cloned MODE-1 CD-ROMs.
One note more: you can burn up to 32 blocks (64 kB of user data) for each
call to WRITE 10 SCSI3 command. But the number of blocks does not affect
the overall burning performance.
The FFCDWrite function can be modified as follows:
- leave the disc opened (don't close the disc): in this case you should
modify the Multi-session Field Definition field in byte 3 of the Write
Parameters Mode Page according to Table 110 in T10-MMC-1 spec, and
byte 2 in the CDB of the CLOSE TRACK/SESSION command according to Table
118 in T10-MMC-1 spec
- write more than one track in the disc: in this case for any successive
track you should determine its starting LBA by getting the Disk Information
Block of the last track in the disc
Four file types are required to build the DLL:
- one ASM file that contains the data segment and the DLL
entry point
- one DEF file that contains the name of the DLL and the
name of the functions that have to be exported
- some INC files that have to be included into the ASM file
- one BAT file that acts as the *makefile* for the DLL to build
The INC files are not actually required, but using them helps
maintaining neat listings and a clear structure of the DLL.
Remember that to build the DLL you should have MASM32 installed in your PC.
Directions to build the DLL are the following:
- make a working directory in your hard disk and name it MMC1DLL:
you will use this directory to keep the following files
- cut this file and paste it into an
ASCII file named MMC1DLL.ASM
- cut this file and paste it into an
ASCII file named MMC1DLL.DEF
- cut this file and paste it into an
ASCII file named MAKEDLL.BAT
- cut this file and paste it into an
ASCII file named FFASPI.INC
- cut this file and paste it into an
ASCII file named FFCDR.INC
- cut this file and paste it into an
ASCII file named WNASPI32.INC (to be put into C:\MASM32\INCLUDE
directory)
- cut this file and paste it into an
ASCII file named SCSIDEFS.INC (to be put into C:\MASM32\INCLUDE
directory)
- run MAKEDLL.BAT and have the DLL done, togheter with its LIB import
library file for static linking.
Use the FFDiscInfo function defined into the MMC1DLL.DLL
described above.
To get the c++ example source code follow this link.
To clone (duplicate) a MODE-1 CD-ROM you should do the following:
- prepare an ISO 9660 (or Joliet) file system image file
- burn it into a blank disc
These steps are described in the next two paragraphs.
The ISO 9660 (or Joliet) image file is required because files in any MODE-1
CD-ROM are supposed to be organized according to one of these widespread
standards. Differently data would not be widespreadly read.
From now on we will be only talking about an IS0 9660 file system image file.
Everything we will say about it will also be valid for any Joliet file
system image file.
A *valid* ISO 9660 image file should start with 32.768 zeroes. Then
at offset 32.768 (0x8000) you should find the following sequence of bytes:
0x01, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00.
You can generate the file using Easy CD Creator, or you can do it yourself
(as desribed below).
If you use Easy CD Creator (or any equivalent program) always check that
the ISO 9660 image file that has been generated is valid according
to the criteria provided above. Differently you might have a delusion.
A do-it-yourself way of getting a valid ISO 9660 image file of an
existing CD-ROM is the following procedure:
- put a good ISO 9660 MODE-1 CD-ROM into the CD-R writer device
- prepare a program to read sequentially all the blocks in the
CD-ROM starting at LBA zero and ending at the last burned block
- write the blocks sequentially into a file in the hard disk
The file obtained this way is an ISO 9660 image of the CD-ROM inserted
into the CD-R writer device (provided the CD-ROM was an ISO 9660,
of course). As simple as this !
To get the c++ example source code of such a program follow this link.
After burning a CD-R, as described in the next paragraph, you can
use the above sample code to get the ISO 9660 image file of the just-burned CD-R.
Then you can compare it with the original ISO 9660 image file that was used
to burn the disc: this will prove that the two files are perfectly equal
(except for the tails of the files, but don't care, it is acceptable).
You can burn the ISO 9660 image file once you have it done and ready to
use. The file is to be burned into a blank CD-R disc inserted into your
CD-R (or CD-RW) writer device, starting at LBA zero.
To do this simply write a little c++ program that calls the FFCDWrite
function into the MMC1DLL.DLL.
To get the c++ example source code follow this link.
Important note: the disc is ready to use just after burning,
and you can browse it in any CD-ROM reader. Before browsing the disc in
the *same* unit it was burned in, please eject the the disc and insert
it again to let the operating system scan its contents (otherwise the
disc appears empty).
Next steps in the future of this project are the following:
- buy the CD-R writer device and mount it into my Plasmon D-Series
juke box
- buy a CD label printer and build a robot to load-print-unload medias
automatically (unattended)
- invent some trick to wrap the jewel box
I don't know whether these investments will be remunerative, because here
in Italy duplicating CD-Rs is worth less than a couple of bucks per CD copy,
and it is not sure a big bargain from my standpoint.
But anycase doing this kind of things is funny. I don't know whether I
will actually build the robot to load-print-unload CDs, but I am already
thinking about this project. It's only a matter of building a mechanical
arm, with some limit switches and electric motors. All these items will be
operated, in turn, by means of my old Analog Devices RTI-815
input/output and DAC/ADC board.
I bought my RTI-815 in 1989. It is an excellent I/O board. These
are its characteristics:
- 10 analog inputs (90 KHz sampling rate)
- 2 analog outputs
- 8 digital inputs
- 8 digital outputs
The board can be easily programmed in asm. I implemented some funny
projects ten years ago.
I put my best efforts to make this project clear and
understandable, but I am always been writing in a hurry. If you notice
any error, inconsistence, obscure phrase, or so I will be glad to repair
it provided you send me a mail. Thanks for your cooperation.
My friend Khalid Belasri, a young Moroccan engineer, sent the following link:
IDiscMaster::RecordDisc.
By following the link you will find the Microsoft's approach to burning a track into a
MODE-1 CD-R using the Device I/O section of the Platform SDK.
This is the description of IDiscMaster::RecordDisc function: "The RecordDisc method
burns the staged image to media in the active disc recorder"; and this is its prototype:
HRESULT RecordDisc(
boolean bSimulate,
boolean bEjectAfterBurn
);
Try it ! (I didn't already).
THE FOLLOWING BUG HAS BEEN FIXED as of nov. 4th 2002
Khalid also made me note a little bug in my assembly code. The doubleword LBA is initialized
(LBA=0) in the data segment of
MMC1DLL.ASM and never again. This means that LBA will be filled with zero only once when
the application loads MMC1DLL.DLL (using LoadLibrary() API call), and FFCDWrite will work
properly only the first time it is called from the application program. Any subsequent
call will fail because LBA is not reset.
Actually LBA should be initialized each time FFCDWrite is called, and not just once at
LoadLibrary time. I will fix this as soon as I can. In the meantime you can use FFCDWrite
provided you load MMC1DLL.DLL (LoadLibrary), call FFCDWrite, unload the DLL (FreeLibrary)
and then reload MMC1DLL.DLL (LoadLibrary again) before calling FFCDWrite again.
Sorry for the inconvenience.
END BUG REPORT
|