Skip to main content
gamedev.net
🔒 Locked

CD checker

Started by funkman 22 replies 1.8k views
Original Post
funkman
funkman
Hi guys, Need a little help. Anyone knows how to write a simple CD checker (that is to check if the game CD is in the drive) Cheers
S1CA
S1CA
Here''s (roughly) what I did for the CD check in the engine for Pac-Man:Adventures in Time (and a few other PC titles which used the same engine):


1. Put a fairly unique file in the root of your CD/DVD (say KEWLGAME.DAT), with some unique contents (a GUID for example).

2. Use GetLogicalDrives() or GetLogicalDriveStrings
() with GetDriveType() to determine which drives in the system are CD/DVD drives (remember there may be more than one, and the user may have a multichanger). Do this every time your app starts - users do change drive letters around.

3. Before doing any CD access call SetErrorMode() to prevent blue screens and error boxes when the system can''t read from a CD/DVD that''s still mounting.

4. If your software has been run previously, set up a registry key with the "last known" drive location of the game CD. ALWAYS check that location first - if you don''t, people with multichangers will hate you if the game CD is in the last of their mounted drives.

5. For each CD/DVD drive (starting at the one in the registry - see above), try to open your file, then try to read from your file and finally compare the contents of the file with your "unique" contents from step 1.

6. IMO it''s better to use the Win32 API calls directly here rather than fopen()/iostream stuff because you get much more control and much more informative error codes back.

7. Don''t rely on AutoRun or WM_DEVICECHANGE notifications - many users disable them. Sometimes properly (so WM_DEVICECHANGE still works and AutoRun doesn''t), often incorrectly (so neither work).


--
Simon O''Connor
3D Game Programmer &
Microsoft DirectX MVP
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
Filami
Filami
Interesting post
Techno Grooves
funkman
funkman
Many thanks, very much appreciated.
funkman
funkman
I''m struggling a bit with my cd-checker. Could you possibly give me a short sample code.

Cheers

P.S. oh yes sorry for crossposting, I was a bit desperate
funkman
funkman
Managed to figure out myself but thanks a million anyway.
I should be hanging around more oten in here, might make my life a lot easier.

One more question. I wonder if anyone had any experience using NDL middleware NetImmerse (or Gamebryo as it is called now).

Again appreciate your help.

Cheers
funkman
funkman
Sorry, another CD checker related question.
How do I you control the message box that appears when the CD is not in the drive. Currently if I press "Continue" it will launch the game anyway?
Erzengeldeslichtes
Erzengeldeslichtes
You can check the return value of the message box, however in most instances you really only need 2 buttons: one for try again, and one for exit. If you put up a message box, check its return value for the exit code. If exit was pressed, tell the program to quit. If try again was pressed, run the cd check again.
----Erzengel des Lichtes光の大天使Archangel of LightEverything has a use. You must know that use, and when to properly use the effects.♀≈♂?
funkman
funkman
The thing is its a standard Windows message box, I''m just checking if the CD is in and if its not Windows does the rest. However for some bizzare reason if i press Continue or even Cancel it still starts the game
funkman
funkman
Just to explain a bit more. Lets take as an example code posted above by Anonymous. Mine is very similar in structure and if you implement and run it, when CD is not in the CD-ROM drive it will display a standard windows message box "No CD" and no matter what you press it will still launch the game.
S1CA
S1CA
So the "No CD" is a message box YOU ask Windows to display...
...i.e. by calling MessageBox() or similar ?

If so, it''s very likely there''s something wrong with how you handle the return code from the MessageBox() function. Post the relevent code (i.e. the bit that calls MessageBox() and decides what to do based on its return code) and it should be pretty easy to determine where you''re going wrong.


If your code isn''t asking Windows to display a message box, and it''s something Windows has produced, then see point 3 of my first reply.

--
Simon O''Connor
3D Game Programmer &
Microsoft DirectX MVP
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
funkman
funkman
More problems
Seems like I''m missing something realy stupid and going around in a continious circle. I thought that the code posted earlier might be better then mine and solve problems so I modified it

int CDInDrive(char *signature, char *dest)
{
char buffer[260], *p;

//lets get a selection of drive strings

ZeroMemory(buffer, 260);
GetLogicalDriveStrings(260, buffer);
SetErrorMode (SEM_NOOPENFILEERRORBOX);

for (p=buffer; *p||*(p+1);)
{
char path[260];
FILE *fp;

//construct a path to the CD Information File

wsprintf(path, "%s%s", p, "aa.dat");

//validate that it is a CD drive (stops the A: thrashing)

if (GetDriveType(p) == DRIVE_CDROM)
{
//Attemp to open it

if ((fp=fopen(path, "rb")) != NULL)
{
char instore[48];
int s;

//Can the title be read?

if (fread(instore, 1, 19, fp)==19)
{
instore[19]=0;

//is it the correct title?

if(!strcmp(instore, "AAA"))
{
//seek past the CR/LF

fseek(fp, 2, SEEK_CUR);
s=strlen(signature);

//can the signature be read?

if (fread(instore, 1, s, fp) ==31)
{
instore[s]=0;

//is it the correct signature

if (!strcmp(instore, signature))
{
//copy the drive string if its desired

if (dest !=NULL) strcpy(dest, p);

//CD is in a drive!

return (1);
}
}
}

}

fclose(fp);
}
}
//Move onto the next drive string

while (*p++){}
}
return (0);
}


Then I''m calling CDInDrive("AAA", "d:\\"); at the beggining of my app. It doesnt read the file and as long as there us any CD in the drive the game will run. If there is no CD at all it will display the message box but no matter what you press the game still runs. Could you point me my mistakes.

Thanks for your help

P.S I know you warned me about using fopen() but it should work anyway. If I''ll make this work I will proceed further
S1CA
S1CA
Can you post the piece of code that actually calls CDInDrive(), in particular the piece of code which displays the message box. The actual "check" code looks like its doing its job (from a quick scan) - I think it''s what you''re doing in response to the CD not being in the drive that''s at fault.

You should have something like (pseudo-C):


blah main()
{
startUpStuff();

// loop until the CD is found OR the user chooses to cancel
while (CDinDrive(blah)==0)
{
// no CD found, throw up error for user to decide
ok_cancel = MessageBox( "No CD in the drive", blah );
if (ok_cancel==CANCEL)
{
// user clicked cancel to exit the app .
cleanUpAnythingAllocated();
// exit from main() (or WinMain etc).
return -1;
}

// if we get here, then the user clicked OK instead of cancel
// so we go round the loop and check for the CD again.
}

runTheGame();

return 0;
}



It''s also definately worth single stepping your code in the debugger to see exactly what''s happening at every stage - that''s a very important skill to get used to.
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
funkman
funkman
Here is what I am calling

Winmain (blah blah)

CDInDrive("BBB", "d:\\");

int ok_cancel;

while (CDInDrive("BBB", "d:\\") == 0)
{
ok_cancel = MessageBox (hMain, "Please Insert CD", "blah", MB_OKCANCEL | MB_ICONEXCLAMATION);
if (ok_cancel == IDCANCEL)
{
// user clicked cancel to exit the app

DestroyWindow(hMain);
return -1;

}
}


then all the usual game stuff load up, cutscene, levels etc.
The CD doesnt even blink
S1CA
S1CA
Try putting a breakpoint on the "if (ok_cancel == IDCANCEL)" line and see if it ever gets hit. If it does, step through the code to see where that "return -1" returns to.

That code will only work if it''s inside the WinMain() or main() function - i.e. so that the return -1 returns from WinMain()/main().


The CD light doesn''t need to blink, nor does the drive even need to spin to check if the CD is in - if you haven''t changed the CD, Windows keeps the contents and commonly/recently read files cached. When you insert a new CD, it checks to see if its the same as the old CD and will often still use the cached contents if it is.

If you use CreateFile() rather than fopen() you have more control over whether caching (etc) is used.
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
funkman
funkman
Just to get it clear. What is *signature and *destination in my CDInDrive? Is signature the name of the disk or a text in a specified file? For destination I just put drive letter? Since the original code for CDInDrive is checking for a file "aa.dat"
Also I do not fully understand what is this looking for -
if(!strcmp(instore, "AAA"). When i call fopen it has "rb" parameters - thats binary read only right? Think my problem is in actual CD now

funkman
funkman
Just to get it clear. What is *signature and *destination in my CDInDrive? Is signature the name of the disk or a text in a specified file? For destination I just put drive letter? Since the original code for CDInDrive is checking for a file "aa.dat"
Also I do not fully understand what is this looking for -
if(!strcmp(instore, "AAA"). When i call fopen it has "rb" parameters - thats binary read only right? Think my problem is in actual CD now

funkman
funkman
Also my machine has 3 CD drives E: F: G: If I put the CD in one of those drives the next time I will launch my app it will search for a CD in that drive and wouldnt look for it in any other. Guess I''m not clearing something
funkman
funkman
Dont want to seem stupid, but is CR/LF (carriege return/line feed ?)format just a standard text format. Could be created in Wordpad etc?

Thanks again for help
funkman
funkman
All is working sweet now. Million thanks to you all, hope this post will be of use for many other forum members.

Thanks again.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.