/*************************************************************************** sub.c - description ------------------- begin : Sun Nov 16 2003 copyright : (C) 2003 by Pete Bernert email : BlackDove@addcom.de ***************************************************************************/ /*************************************************************************** * * * 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. See also the license.txt file for * * additional informations. * * * ***************************************************************************/ //*************************************************************************// // History of changes: // // 2003/11/16 - Pete // - generic cleanup for the Peops release // //*************************************************************************// ///////////////////////////////////////////////////////// #include "stdafx.h" #define _IN_SUB #include "externals.h" /* TODO (#1#): SUB CHANNEL STUFF */ ///////////////////////////////////////////////////////// unsigned char * pCurrSubBuf=NULL; // ptr to emu sub data (or NULL) int iUseSubReading=0; // subdata support (by file or directly) char szSUBF[260]; // sub file name SUB_CACHE * subCache=NULL; // cache memory SUB_DATA * subHead=NULL; int iSUBNum=0; // number of subdata cached unsigned char SubCData[96]; // global data subc buffer unsigned char SubAData[96]; // global audio subc buffer ///////////////////////////////////////////////////////// void BuildSUBCache(void) { FILE * subfile; unsigned char buffer[16], * p; SUB_DATA * plast=NULL,* px; if(iUseSubReading) // some subreading wanted? { if(iUseSubReading==1) iUseCaching=0; // -> direct read? no caching done, only 1 sector reads memset(SubCData,0,96); // -> init subc pCurrSubBuf=SubCData; // -> set global ptr } else // no plugin subreading? { pCurrSubBuf=NULL; // -> return NULL as subc buffer to emu } memset(SubAData,0,96); // init audio subc buffer if(iUseSubReading!=2) return; // no subfile wanted? if(szSUBF[0]==0) return; // no filename given? subfile=fopen(szSUBF, "rb"); // open subfile if(subfile==0) { MessageBox(NULL,"No SBI/M3S file found!",libraryName,MB_OK); return; } memset(buffer,0,5); // read header fread(buffer, 4, 1, subfile); iSUBNum=0;subHead=NULL; if(strcmp((char *)buffer,"SBI")==0) // ah, SBI file { while(fread(buffer, 4, 1, subfile)==1) // -> read record header { iSUBNum++; // -> one more sub cache block px=(SUB_DATA *)malloc(sizeof(SUB_DATA)); // -> get cache buff //!!!!!!!!!!!!!!!!!!!!!!!!!!!! // -> and fill it... /* TODO (#1#): addr2time subchannel */ px->addr=time2addrB(buffer); px->pNext=NULL; px->subq[0]=0x41; px->subq[1]=0x01; px->subq[2]=0x01; p=&px->subq[3]; addr2timeB(px->addr,p); px->subq[6]=0x00; p=&px->subq[7]; addr2timeB(px->addr+150,p); if(buffer[3]==1) { fread(px->subq,10, 1, subfile); } else if(buffer[3]==2) { fread(&px->subq[3],3, 1, subfile); } else if(buffer[3]==3) { fread(&px->subq[7],3, 1, subfile); } if(plast==NULL) // add new cache block to linked list { plast=subHead=px; } else { plast->pNext=px;plast=px; } } } else // M3S file? { // -> read data, and store all unsigned char min,sec,frame,xmin,xsec,xframe; // -> subs which are different from BOOL b1,b2,goon=TRUE;int iNum=0; // -> the expected calculated values xmin=2; xsec=58; xframe=0; min=3; sec=0; frame=0; fread(buffer+4, 12, 1, subfile); do { if(itod(min) != buffer[7]|| itod(sec) != buffer[8]|| itod(frame) != buffer[9]) b1=TRUE; else b1=FALSE; if(itod(xmin) != buffer[3]|| itod(xsec) != buffer[4]|| itod(xframe) != buffer[5]) b2=TRUE; else b2=FALSE; if(buffer[1]!=1) b1=b2=TRUE; if(buffer[2]!=1) b1=b2=TRUE; if(b1 || b2) { iSUBNum++; px=(SUB_DATA *)malloc(sizeof(SUB_DATA)); px->pNext=NULL; memcpy(px->subq,buffer,10); buffer[7]=itod(min); buffer[8]=itod(sec); buffer[9]=itod(frame); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! px->addr=time2addrB(&buffer[7]); if(plast==NULL) {plast=subHead=px;} else {plast->pNext=px;plast=px;} } xframe=xframe+1; if(xframe>74) { xsec+=1; xframe-=75; if(xsec>59) { xmin+=1; xsec-=60; if(xmin>99) { goon=FALSE; } } } frame=frame+1; if(frame>74) { sec+=1; frame-=75; if(sec>59) { min+=1; sec-=60; if(min>99) { goon=FALSE; } } } iNum++; if(iNum>(60*75)) goon=FALSE; } while(goon && (fread(buffer, 16, 1, subfile)==1)); if(iNum!=(60*75)) goon=FALSE; else if(iSUBNum==(60*75)) goon=FALSE; if(!goon) { MessageBox(NULL,"Bad SBI/M3S file!",libraryName,MB_OK); fclose(subfile); FreeSUBCache(); return; } } subCache=NULL; if(iSUBNum) // something in cache? { // -> create an array with the used addresses, for fast searching access SUB_CACHE * psc;int i; subCache=(SUB_CACHE *)malloc(iSUBNum*sizeof(SUB_CACHE)); psc=subCache;px=subHead; for(i=0;ipNext) { psc->addr = px->addr; psc->pNext = (void *)px; } iSUBNum--; } fclose(subfile); } ///////////////////////////////////////////////////////// // func for calculating 'right' subdata void FakeSubData(unsigned long adr) { SubCData[12]=0x41; SubCData[13]=0x01; SubCData[14]=0x01; /* TODO (#1#): addr2time fake sub data */ //!!!!!!!!!!!!!!!!!!!!!!!???? addr2timeB(adr, &SubCData[15]); // SubCData[18]=0x00; addr2timeB(adr+150,&SubCData[19]); } ///////////////////////////////////////////////////////// // check, if for a given addr we have special subdata in cache void CheckSUBCache(long addr) { SUB_CACHE * pcstart, * pcend, * pcpos; pcstart=subCache; // ptrs to address arrays (start/end) pcend =subCache+iSUBNum; if(addr>=pcstart->addr && // easy check, if given addr is between start/end addr<=pcend->addr) { while(1) // now search for sub { if(addr==pcend->addr) {pcpos=pcend;break;} // got it! break pcpos=pcstart+(pcend-pcstart)/2; // get the 'middle' address if(pcpos==pcstart) break; // no more checks can be done if(addraddr) // look further... { pcend=pcpos; continue; } if(addr>pcpos->addr) { pcstart=pcpos; continue; } break; } if(addr==pcpos->addr) // found some cached data? { SUB_DATA * p=(SUB_DATA *)pcpos->pNext; // -> ptr to data memcpy(&SubCData[12],p->subq,10); // -> get the data return; // -> done } } FakeSubData(addr); // no subcdata avail, so fake right one } ///////////////////////////////////////////////////////// // free all sub cache bufs void FreeSUBCache(void) { SUB_DATA * p=subHead; void * pn; while(p) { pn=p->pNext; free(p); p=(SUB_DATA *)pn; } subHead=NULL; if(subCache) free(subCache); subCache=NULL; } /////////////////////////////////////////////////////////