🔒 Locked
CD checker
Advertisement
Original Post
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
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
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
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
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.
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.
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
...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
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
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
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
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):
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.
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.
Here is what I am calling
Winmain (blah blah)
then all the usual game stuff load up, cutscene, levels etc.
The CD doesnt even blink
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
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.
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.
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
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
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
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
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement