// $Id: cdrom.cpp,v 1.2 2000/08/12 12:52:56 mbickel Exp $ // // $Log: cdrom.cpp,v $ // Revision 1.2 2000/08/12 12:52:56 mbickel // Made DOS-Version compile and run again. // // Revision 1.1 2000/05/30 18:39:28 mbickel // Added support for multiple directories // Moved DOS specific files to a separate directory // // Revision 1.5 2000/05/23 20:40:37 mbickel // Removed boolean type // // Revision 1.4 2000/04/27 16:25:16 mbickel // Attack functions cleanup // New vehicle categories // Rewrote resource production in ASC resource mode // Improved mine system: several mines on a single field allowed // Added unitctrl.* : Interface for vehicle functions // currently movement and height change included // Changed timer to SDL_GetTicks // // Revision 1.3 2000/03/29 09:58:42 mbickel // Improved memory handling for DOS version // Many small changes I can't remember ;-) // // Revision 1.2 1999/11/16 03:41:13 tmwilson // Added CVS keywords to most of the files. // Started porting the code to Linux (ifdef'ing the DOS specific stuff) // Wrote replacement routines for kbhit/getch for Linux // Cleaned up parts of the code that gcc barfed on (char vs unsigned char) // Added autoconf/automake capabilities // Added files used by 'automake --gnu' // // /* This file is part of Advanced Strategic Command; http://www.asc-hq.de Copyright (C) 1994-1999 Martin Bickel and Marc Schellenberger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "cdrom.h" #define xshowstatus call_real_int ri(cdromintmemsize); const char* ttdef[5] = {"2 audio-channels without pre-emphasis","2 audio-channels with pre-emphasis", "4 audio-channels without pre-emphasis", "4 audio-channels with pre-emphasis","Data Track"}; const char* cerror[17] = {"No Error","Write-protect violation","Unknown unit","Drive not ready","Unknown command","CRC error", "Bad drive request structure length","Seek error","Unknown media","Sector not found", "Printer out of paper","Write fault","Read fault","General failure","Reserved","Reserved", "Invalid disk change"}; tcdrom::tcdrom( void ) { if ( testcdromavailable() == 1 ) { getcdrominfo(); activecdrom = driveletter[0]; getcdromdrives(); } else { printf("No CD-Rom detected !\n"); numberofdrives = 0; } } void tcdrom::readcdinfo( void ) { pascal_byte lt,ht,m,s,f,t,e; int i = 0; lt = 0; ht = 0; while ( ( (lt > ht) || ( lt > 99 ) || ( ht > 99 ) || ( ht < 1 ) || ( lt < 1 ) || ( e > 0 ) ) && ( i < 20 )) { lt = 0; ht = 0; getcdinfo(<,&ht,&m,&s,&f); e = geterror(); i++; } /* endwhile */ cdinfo.firsttrack= 0; cdinfo.lasttrack= 0; if (i == 20 ) return; cdinfo.firsttrack= lt; cdinfo.lasttrack= ht; cdinfo.smin = m; cdinfo.ssec = s; cdinfo.sframe = f; cdinfo.start = getnormalsector(m,s,f); getcdlength(&m,&s,&f); cdinfo.min = m; cdinfo.sec = s; cdinfo.frame = f; cdinfo.size = getnormalsector(m,s,f); for (i=0 ;i < ht ;i++ ) { cdinfo.track[i] = new( ttrackinf ); gettrackinfo(i,&m,&s,&f,&t); cdinfo.track[i]->smin = m; cdinfo.track[i]->ssec = s; cdinfo.track[i]->sframe = f; cdinfo.track[i]->type = t; cdinfo.track[i]->start = getnormalsector(m,s,f); gettracklength(i,&m,&s,&f); cdinfo.track[i]->min = m; cdinfo.track[i]->sec = s; cdinfo.track[i]->frame = f; cdinfo.track[i]->size = getnormalsector(m,s,f); } /* endfor */ } void tcdrom::playtrack(pascal_byte nr) { if (cdinfo.track[nr]->type > 3) return; stopaudio(); playaudio(cdinfo.track[nr]->start,cdinfo.track[nr]->size); } void tcdrom::playtrackuntilend(pascal_byte nr) { if (cdinfo.track[nr]->type > 3) return; stopaudio(); playaudio(cdinfo.track[nr]->start,cdinfo.size-cdinfo.track[nr]->start); } tcdrom::~tcdrom( void ) { for (int i=0 ;i < cdinfo.lasttrack ;i++ ) if (cdinfo.track[i] != NULL) free ( cdinfo.track[i] ); } char tcdrom::testcdromavailable(void) { ri.setuprmi(); rmi.eax = 0x1500; rmi.ebx = 0x0; ri.real_call(0x2f); if (rmi.ebx == 0) return false; else return true; } pascal_byte tcdrom::geterror( void ) { word st; if ((ioctl->requestheader.status & 0x8000) > 0) { st = ioctl->requestheader.status & 255; return ( st <255 ) ? ++st : 255; } else return 0; } pascal_byte tcdrom::checkerror( void ) { int e; if (ioctl == NULL) printf("\nError : IOCTL is NULL !!!\n\n"); else { e = geterror(); if (e > 0 ) if ( e <= 16 ) printf("\nError : %s\n\n",cerror[e]); else printf("\nError : Unknown Error\n\n"); } return e; } char tcdrom::openclosecdrom(void) { ioctl = ( tioctlo *) ri.protectedsegment; ds = ( tdevicestatus * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*ds); ds->controlblockcode = 6; ds->status = 0; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 12; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = 1; if (((ds->status & 0x1) == 0)) { ds->controlblockcode = 0; //return true; } else { ds->controlblockcode = 5; //return false; } ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; call_real_int(0x2f); return true; } char tcdrom::testcdromopen(void) { ioctl = ( tioctlo *) ri.protectedsegment; ds = ( tdevicestatus * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*ds); ds->controlblockcode = 6; ds->status = 0; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; call_real_int(0x2f); memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 12; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = 1; if (((ds->status & 0x1) == 0)) { return true; } else { return false; } } void tcdrom::playaudio(int ss, int numbersectors) { tplayaudio *pa; pa = ( tplayaudio *) ri.protectedsegment; memset(pa,0,sizeof(*pa)); ioctl->requestheader.len = sizeof(pa); ioctl->requestheader.commandcode = 132; pa->adressingmode = 0; pa->startsector = ss; pa->numberofsectors = numbersectors; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); } void tcdrom::stopaudio(void) { tstopresume *sr; sr = ( tstopresume *) ri.protectedsegment; memset(sr,0,sizeof(*sr)); ioctl->requestheader.len = sizeof(sr); ioctl->requestheader.commandcode = 133; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); } char tcdrom::checkbusy(void) { ioctl = ( tioctlo *) ri.protectedsegment; ds = ( tdevicestatus * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*ds); ds->controlblockcode = 6; ds->status = 0; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); if ((ioctl->requestheader.status & 512) > 0) return true; else return false; } int tcdrom::getcdsize(void) { tcdsize *cds; ioctl = ( tioctlo *) ri.protectedsegment; cds = ( tcdsize * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*cds); cds->controlblockcode = 8; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); return cds->size; } void tcdrom::getcdinfo(pascal_byte *l,pascal_byte *h,pascal_byte *min,pascal_byte *sec,pascal_byte *frame) { tcdinfo *cdi; ioctl = ( tioctlo *) ri.protectedsegment; cdi = ( tcdinfo * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*cdi); cdi->controlblockcode = 10; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); *l = cdi->lowesttrack; *h = cdi->highesttrack; *min = (cdi->leadout & 0x00FF0000) >> 16; *sec = (cdi->leadout & 0x0000FF00) >> 8; *frame = cdi->leadout & 0x000000FF; } void tcdrom::getcdlength(pascal_byte *min,pascal_byte *sec,pascal_byte *frame) { pascal_byte m, s, f, m1, s1, f1,ht,lt,t; getcdinfo(<,&ht,&m1,&s1,&f1); gettrackinfo(0,&m,&s,&f,&t); *min = m1 - m; if (s > s1) { if (*min > 0) *min = *min - 1; else *min = 59; *sec = 60 - s + s1; } else *sec = s1 - s; if (f > f1) { if (*sec > 0) *sec = *sec - 1; else *sec = 59; *frame = 74 - f + f1; } else *frame = f1 - f; } void tcdrom::gettracklength(pascal_byte tracknr,pascal_byte *min,pascal_byte *sec,pascal_byte *frame) { pascal_byte m, m1, s, s1, f, f1, l, h, m2, s2, f2,t; getcdinfo(&l,&h,&m2,&s2,&f2); gettrackinfo(tracknr,&m,&s,&f,&t); if (tracknr < h-1) gettrackinfo(tracknr + 1,&m1,&s1,&f1,&t); else { m1 = m2; s1 = s2; f1 = f2; } *min = m1 - m; if (s > s1) { if (*min > 0) *min = *min - 1; else *min = 59; *sec = 60 - s + s1; } else *sec = s1 - s; if (f > f1) { if (*sec > 0) *sec = *sec - 1; else { *sec = 59; *min = *min - 1; } *frame = 74 - f + f1; } else *frame = f1 - f; } void tcdrom::getactivetimes(pascal_byte *min,pascal_byte *sec,pascal_byte *frame,pascal_byte *amin,pascal_byte *asec,pascal_byte *aframe) { tqinfo *qi; ioctl = ( tioctlo *) ri.protectedsegment; qi = ( tqinfo * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*qi); qi->controlblockcode = 12; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); *amin = qi->amin; *asec = qi->asec; *aframe = qi->aframe; *min = qi->min; *sec = qi->sec; *frame = qi->frame; } int tcdrom::getheadlocation(void) { tlocatehead *lh; ioctl = ( tioctlo *) ri.protectedsegment; lh = ( tlocatehead * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*lh); lh->controlblockcode = 1; lh->adressingmode = 0; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); return lh->headlocation; } void tcdrom::seeksector(int ss) { tseek *s; s = ( tseek *) ri.protectedsegment; memset(s,0,sizeof(*s)); s->requestheader.len = sizeof(tseek); s->requestheader.commandcode = 131; s->adressingmode = 0; s->startsector = ss; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); } void tcdrom::gettrackinfo(pascal_byte tracknr,pascal_byte * min,pascal_byte * sec,pascal_byte * frame,pascal_byte * type) { ttrackinfo *ti; tracknr++; ioctl = ( tioctlo *) ri.protectedsegment; ti = ( ttrackinfo * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*ti); ti->controlblockcode = 11; ti->tracknumber = tracknr; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); *min = (ti->startpoint & 0x00FF0000) >> 16; *sec = (ti->startpoint & 0x0000FF00) >> 8; *frame = ti->startpoint & 0x000000FF; ti->controlinfo &= 0xF0; if ( ( ti->controlinfo & 0x80 ) > 0) *type = ( ( ti->controlinfo & 0x10 ) > 0 ) ? 3 : 2; else *type = ( ( ti->controlinfo & 0x10 ) > 0 ) ? 1 : 0; if ( ( ti->controlinfo & 0x40 ) > 0) *type = 4; } void tcdrom::getaudioinfo() { ioctl = ( tioctlo *) ri.protectedsegment; ac = ( taudiochannel * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*ac); ac->controlblockcode = 4; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); ta.volume[0] = ac->volumechannel0; ta.volume[1] = ac->volumechannel1; ta.volume[2] = ac->volumechannel2; ta.volume[3] = ac->volumechannel3; ta.channel[0] = ac->inputchannel0; ta.channel[1] = ac->inputchannel1; ta.channel[2] = ac->inputchannel2; ta.channel[3] = ac->inputchannel3; } void tcdrom::setaudiochannel() { ioctl = ( tioctlo *) ri.protectedsegment; ac = ( taudiochannel * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 12; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = 9; ac->controlblockcode = 3; ac->volumechannel0 = ta.volume[0] ; ac->volumechannel1 = ta.volume[1] ; ac->volumechannel2 = ta.volume[2] ; ac->volumechannel3 = ta.volume[3] ; ac->inputchannel0 = ta.channel[0] ; ac->inputchannel1 = ta.channel[1] ; ac->inputchannel2 = ta.channel[2] ; ac->inputchannel3 = ta.channel[3] ; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); } char tcdrom::lockunlockcdrom(void) { tlockdoor *ld; ioctl = ( tioctlo *) ri.protectedsegment; ds = ( tdevicestatus * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*ds); ds->controlblockcode = 6; ds->status = 0; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); ld = ( tlockdoor * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 12; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = 2; ld->controlblockcode = 1; if (((ds->status & 0x2) == 0)) ld->lockfunction = 0; else ld->lockfunction = 1; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); if (((ds->status & 0x2) == 0)) return false; else return true; } void tcdrom::resumeaudio(void) { tstopresume *sr; sr = ( tstopresume *) ri.protectedsegment; memset(sr,0,sizeof(*sr)); ioctl->requestheader.len = sizeof(sr); ioctl->requestheader.commandcode = 136; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); } float tcdrom::get_mscdex_version(void) { ri.setuprmi(); rmi.eax = 0x150C; ri.real_call(0x2f); return rmi.bh + (rmi.bl / 100); } void tcdrom::getcdrominfo(void) { ri.setuprmi(); rmi.eax = 0x1500; ri.real_call(0x2f); numberofdrives = rmi.bx; driveletter[0] = rmi.cx; } void tcdrom::getcdromdrives(void) { char *drives; drives = ( char *) ri.protectedsegment; ri.setuprmi(); rmi.eax = 0x150D; rmi.ebx = 0; rmi.es = ri.realsegment; ri.real_call(0x2f); for (int i=0;i < numberofdrives ;i++ ) driveletter[i+1]=drives[i]; } void tcdrom::changecdromdrive(char nr) { if ( (nr < 0) || ( nr > numberofdrives-1 ) ) return; activecdrom = driveletter[nr]; } int tcdrom::getnormalsector(pascal_byte m,pascal_byte s,pascal_byte f) { return (int(m) * 60 * 75) + (int(s) * 75) + int(f) - 150; } void tcdrom::getsectortime(int sector,pascal_byte *m,pascal_byte *s,pascal_byte *f) { int v; sector+=150; *f = sector % 75; v = sector / 75; *m = v / 60; *s = v % 60; } void* tcdrom::getdevheaderadress(void) { tgetdevheader *dh; ioctl = ( tioctlo *) ri.protectedsegment; dh = ( tgetdevheader * ) &ioctl[1]; memset(ioctl,0,sizeof(*ioctl)); ioctl->requestheader.len = sizeof(tioctlo); ioctl->requestheader.commandcode = 3; ioctl->buffer = ( ( ri.realsegment << 16 ) + 28 ); ioctl->buffersize = sizeof(*dh); dh->controlblockcode = 0; dh->adress = 0; ri.setuprmi(); rmi.eax = 0x1510; rmi.ebx = 0; rmi.ecx = activecdrom; rmi.es = ri.realsegment; ri.real_call(0x2f); return dh->adress; }