/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 1997 by Ton Roosendaal, Frank van Beek and Joeri Kassenaar. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 1997 by Ton Roosendaal, Frank van Beek and Joeri Kassenaar. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* * psxutil.c * * de lijst en malloc functies uit de util.c * * */ #include #include #include #include #include #include #include "psxutil.h" #include #include #include #include #include int MallocSize = 0x200000; void * MallocStart = (void *) 0x80200000; #define MALLOCSIZE MallocSize #define MALLOCSTA MallocStart /* #define MALLOCSIZE 0x200000 #define MALLOCSTA 0x80200000 */ /* DEBUG */ extern ListBase * osview; typedef struct checkpoint { struct checkpoint * next, * prev; char * file; int line; char * string; int time; }checkpoint; #ifdef CHECK_DEBUG #define CHECKPOINT(x) {checkpoint * cp = NEW(checkpoint); cp->string = # x; cp->line = __LINE__; cp->file = __FILE__; cp->time = GetRCnt(RCntCNT1); addtail(osview, cp);} #else #define CHECKPOINT(x) #endif short psx_init_done = FALSE; /* addhead(listbase,link) addtail(listbase,link) remlink(listbase,link) insertlink(listbase,prevlink,newlink) freelist(listbase) freelistN(listbase) long countlist(listbase) void *mallocN(len,str) void *callocN(len,str) short freeN(adr) short fileselect(tekst,dir) */ short totblock = 0, is_cd = 0; long mem_in_use = 0; long current_mem_level = 0; ListBase _membase = {0, 0}, *membase = &_membase; ListBase _dir_list = {0, 0}, * dir_list = & _dir_list; ListBase _s_list = {0, 0}, * s_list = &_s_list; volatile int _line = 0; volatile char * _file = 0; char tmpname[128]; char gurustr[128]; int noguru = 0; cdsector * cdcache = 0; // geven aan welke indexen gebruikt zijn volatile uchar s_in_use[256]; // hoeveel blokken zijn er in gebruik (s_used - s_freed) ushort s_used = 0, s_freed = 0; Stream * active_stream = 0; volatile Stream * urgent_stream = 0; volatile char s_status[32], s_result[8]; volatile int s_read_sector = 0, s_next_sector = 0, s_retry = 0; #define MAX_RETRY 10 #define CDLREAD CdlReadN void cdreadycallback(uchar , uchar * ); void addhead(listbase,link) struct ListBase *listbase; struct Link *link; { if (link == 0) return; if (listbase == 0) return; link->next = listbase->first; link->prev = 0; if (listbase->first) ((struct Link *)listbase->first)->prev = link; if (listbase->last == 0) listbase->last = link; listbase->first = link; } void addtail(listbase,link) struct ListBase *listbase; struct Link *link; { if (link == 0) return; if (listbase == 0) return; link->next = 0; link->prev = listbase->last; if (listbase->last) ((struct Link *)listbase->last)->next = link; if (listbase->first == 0) listbase->first = link; listbase->last = link; } void remlink(listbase,link) struct ListBase *listbase; struct Link *link; { if (link == 0) return; if (listbase == 0) return; if (link->next) link->next->prev = link->prev; if (link->prev) link->prev->next = link->next; if (listbase->last == link) listbase->last = link->prev; if (listbase->first == link) listbase->first = link->next; } void insertlink(listbase,prevlink,newlink) struct ListBase *listbase; struct Link *prevlink,*newlink; { /* newlink komt na prevlink */ if (newlink == 0) return; if (listbase == 0) return; if(listbase->first==0) { /* lege lijst */ listbase->first= newlink; listbase->last= newlink; return; } if (prevlink== 0) { /* inserten voor eerste element */ newlink->next= listbase->first; newlink->prev= 0; newlink->next->prev= newlink; listbase->first= newlink; return; } if (listbase->last== prevlink) /* aan einde lijst */ listbase->last = newlink; newlink->next= prevlink->next; prevlink->next= newlink; if(newlink->next) newlink->next->prev= newlink; newlink->prev= prevlink; } void insertlinkbefore(listbase, nextlink, newlink) struct ListBase *listbase; struct Link *nextlink,*newlink; { /* newlink komt voor nextlink */ if (newlink == 0) return; if (listbase == 0) return; if(listbase->first==0) { /* lege lijst */ listbase->first= newlink; listbase->last= newlink; return; } if (nextlink== 0) { /* inserten aan einde lijst */ newlink->prev= listbase->last; newlink->next= 0; ((struct Link *)listbase->last)->next= newlink; listbase->last= newlink; return; } if (listbase->first== nextlink) /* aan begin lijst */ listbase->first = newlink; newlink->next= nextlink; newlink->prev= nextlink->prev; nextlink->prev= newlink; if(newlink->prev) newlink->prev->next= newlink; } void freelist(listbase) struct ListBase *listbase; { struct Link *link,*next; if (listbase == 0) return; link= listbase->first; while(link) { next= link->next; free(link); link= next; } listbase->first=0; listbase->last=0; } long countlist(listbase) struct ListBase *listbase; { Link * link; long count = 0; if (listbase){ link = listbase->first; while(link) { count++; link= link->next; } } return(count); } #ifdef malloc #undef malloc #endif #ifdef calloc #undef calloc #endif #ifdef free #undef free #endif ListBase _freememlist = {0, 0}, * freememlist = & _freememlist; ListBase _blocklist = {0, 0}, * blocklist = & _blocklist; checkmemory() { int totsize = 0; FreeBlock * fblock; MemBlock * mblock; mblock = blocklist->first; while (mblock) { totsize += mblock->size; mblock = mblock->next; } if (totsize != MallocSize) { sprintf(gurustr, "malloc: totsize != mallocsize\n %d != %d", totsize, MallocSize); guru(gurustr); printf("freeblocks:\n"); fblock = freememlist->first; while (fblock) { printf(" %08x %d\n", fblock, fblock->block.size); fblock = fblock->next; } printf("memoryblocks:\n"); mblock = blocklist->first; while (mblock) { printf(" %08x %d\n", mblock, mblock->size); mblock = mblock->next; } } } void InitHeap(unsigned long * start, unsigned long size) { FreeBlock * fblock; if (1) { sprintf(gurustr, "in InitHeap (0x%x %d = %d kB)", start, size, (size + 512) >> 10); //guru(gurustr); MallocStart = start; MallocSize = size; fblock = (FreeBlock *) MallocStart; fblock->block.size = MallocSize; fblock->block.tag = MEMFREE; addtail(freememlist, fblock); addtail(blocklist, &fblock->block); } else { InitHeap2(start, size); } } int mallocNmalloc = FALSE; int best_memblock(size_t len) { FreeBlock * fblock; int size, bestsize = 0; size = len; if (size <= 0) return(0); size = (size + 3) & ~3; size += sizeof(FreeBlock); fblock = freememlist->first; while (fblock) { if (fblock->block.size >= size) { return(size); } if (fblock->block.size > bestsize) bestsize = fblock->block.size; fblock = fblock->next; } if (bestsize) bestsize -= sizeof(FreeBlock); return (bestsize); } void * malloc(size_t len) { FreeBlock * fblock, * best = 0, * nblock; MemBlock * mblock, * mblock2; int bestsize = 0x7fffffff, newsize, size; size = len; if (mallocNmalloc == FALSE) printf("\n externalMalloc: size %d\n\n", len); if (size <= 0) return(0); size = (size + 3) & ~3; size += sizeof(FreeBlock); fblock = freememlist->first; while (fblock) { if (fblock->block.size >= size) { if (fblock->block.size < bestsize) { bestsize = fblock->block.size; best = fblock; if (bestsize == size) break; } } fblock = fblock->next; } if (best == 0) return(0); fblock = best; if (fblock->block.tag != MEMFREE) { guru("Malloc freetag corrupt"); return(0); } // moeten we splitsen ? newsize = fblock->block.size - size; if (newsize >= sizeof(FreeBlock) + 32) { nblock = (FreeBlock *) (((uchar *) fblock) + size); nblock->block.size = newsize; nblock->block.tag = MEMFREE; addhead(freememlist, nblock); mblock = &fblock->block; mblock2 = &nblock->block; insertlink(blocklist, mblock, mblock2); fblock->block.size -= newsize; } fblock->block.tag = MEMBLCK; remlink(freememlist, fblock); fblock++; // printf("Malloc: %08x size %d\n", fblock, len); return(fblock); } void * calloc(size_t len, size_t count) { uchar * pnt; guru("hi hi, in calloc\n"); pnt = malloc(len * count); if (pnt) bzero(pnt, len * count); return(pnt); } void * realloc(void * pnt, size_t len) { guru("realloc not implemented"); return(0); } void free(void * vp) { FreeBlock * fblock; MemBlock * pblock, * nblock, * mblock; short add_to_list = TRUE; if (vp == 0) { guru("freeing null pointer"); return; } mblock = vp; mblock--; // printf("Free: %08x\n", vp); if (mblock->tag != MEMBLCK) { guru("free: block corrupt"); return; } mblock->tag = MEMFREE; // samenvoegen met vorige ?? pblock = mblock->prev; if (pblock) { if (pblock->tag == MEMFREE) { pblock->size += mblock->size; remlink(blocklist, mblock); mblock = pblock; add_to_list = FALSE; } } // samenvoegen met volgende ?? nblock = mblock->next; if (nblock) { if (nblock->tag == MEMFREE) { remlink(blocklist, nblock); fblock = (FreeBlock *) ((uchar *) nblock - sizeof(FreeBlock) + sizeof(MemBlock)); remlink(freememlist, fblock); mblock->size += nblock->size; } } if (add_to_list) { fblock = (FreeBlock *) ((uchar *) mblock - sizeof(FreeBlock) + sizeof(MemBlock)); addhead(freememlist, fblock); } } void MemorY_ErroR(block,error) char *block,*error; { printf("Memoryblock %s: %s\n",block,error); } void (*memory_error)() = MemorY_ErroR; void *mallocN(len,str) long len; char *str; { MemHead *memh; MemTail *memt; static char buf[128]; if(len<=0) { sprintf(gurustr, "Malloc error: len=%d in %s\n",len,str); guru(gurustr); return 0; } mallocNmalloc = TRUE; len = (len + 3 ) & ~3; /* eenheden van 4 */ memh=(MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail)); mallocNmalloc = FALSE; if(memh!=0) { if( ((int)memh)+len > (int) MALLOCSTA + MALLOCSIZE ) { sprintf(gurustr, "Malloc beyond max: \nlen=%d in %s\n",len, str); sprintf(gurustr, "Malloc overflow in %s: \n%x > %x\n", str, (int)memh+len, (int) MALLOCSTA + MALLOCSIZE); guru(gurustr); // return 0; } memh->tag1 = MEMTAG1; memh->name = str; memh->nextname = 0; memh->len = len; memh->level = current_mem_level; memh->tag2 = MEMTAG2; memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len); memt->tag3 = MEMTAG3; addtail(membase,&memh->next); if (memh->next) memh->nextname = MEMNEXT(memh->next)->name; totblock++; mem_in_use += len; return (++memh); } sprintf(buf, "Malloc returns nill: len=%d in %s\n",len,str); guru(buf); return 0; } void *callocN(len,str) long len; char *str; { void *poin; poin= mallocN(len, str); if(poin) bzero(poin, len); return poin; } void rem_memblock(memh) MemHead *memh; { remlink(membase,&memh->next); if (memh->prev){ if (memh->next) MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name; else MEMNEXT(memh->prev)->nextname = 0; } totblock--; mem_in_use -= memh->len; free(memh); } void printmemlist() { MemHead *membl; membl = membase->first; if (membl) membl = MEMNEXT(membl); while(membl) { printf("%s len: %d\n",membl->name,membl->len); if(membl->next) membl= MEMNEXT(membl->next); else break; } } char *check_memlist(memh) MemHead *memh; { MemHead *forw,*back,*forwok,*backok; char *name; forw = membase->first; if (forw) forw = MEMNEXT(forw); forwok = 0; while(forw){ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break; forwok = forw; if (forw->next) forw = MEMNEXT(forw->next); else forw = 0; } back = (MemHead *) membase->last; if (back) back = MEMNEXT(back); backok = 0; while(back){ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break; backok = back; if (back->prev) back = MEMNEXT(back->prev); else back = 0; } if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT"); if (forw == 0 && back == 0){ /* geen foute headers gevonden dan maar op zoek naar memblock*/ forw = membase->first; if (forw) forw = MEMNEXT(forw); forwok = 0; while(forw){ if (forw == memh) break; if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break; forwok = forw; if (forw->next) forw = MEMNEXT(forw->next); else forw = 0; } if (forw == 0) return (0); back = (MemHead *) membase->last; if (back) back = MEMNEXT(back); backok = 0; while(back){ if (back == memh) break; if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break; backok = back; if (back->prev) back = MEMNEXT(back->prev); else back = 0; } } if (forwok) name = forwok->nextname; else name = "No name found"; if (forw == memh){ /* voor alle zekerheid wordt dit block maar uit de lijst gehaald */ if (forwok){ if (backok){ forwok->next = (MemHead *)&backok->next; backok->prev = (MemHead *)&forwok->next; forwok->nextname = backok->name; } else{ forwok->next = 0; membase->last = (struct Link *) &forwok->next; } } else{ if (backok){ backok->prev = 0; membase->first = &backok->next; } else{ membase->first = membase->last = 0; } } } else{ memory_error(name,"Aditional error in header"); return(0); } return(name); } short freeN(memh) MemHead *memh; { short error = 0; MemTail *memt; char *name; if (memh == 0){ memory_error("free","attempt to free NULL pointer"); return(-1); } if (((long) memh) & 0x3){ memory_error("free","attempt to free illegal pointer"); return(-1); } memh--; if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) { memory_error(memh->name,"double free"); return(-1); } if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) { memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len); if (memt->tag3 == MEMTAG3){ rem_memblock(memh,memt); memh->tag1 = MEMFREE; memh->tag2 = MEMFREE; memt->tag3 = MEMFREE; return(0); } error = 2; memory_error(memh->name,"end corrupt"); name = check_memlist(memh); if (name != 0){ if (name != memh->name) memory_error(name,"is also corrupt"); } } else{ error = -1; name = check_memlist(memh); if (name == 0) memory_error("free","pointer not in memlist"); else memory_error(name,"error in header"); } totblock--; /* hier moet een DUMP plaatsvinden */ return(error); } void freelistN(listbase) struct ListBase *listbase; { struct Link *link,*next; if (listbase == 0) return; link= listbase->first; while(link) { next= link->next; freeN(link); link= next; } listbase->first=0; listbase->last=0; } void sleep(int sec) { sec *= 25; for (; sec > 0; sec--) { VSync(0); } } void psx_init(short force) { if (psx_init_done == 0 || force) { psx_init_done = 1; PadInit(0); SetVideoMode(MODE_PAL); ResetGraph(0); /* reset graphic subsystem (0:cold,1:warm) */ SetGraphDebug(0); /* set debug mode (0:off, 1:monitor, 2:dump) */ SetDispMask(1); /* enable to display (0:inhibit, 1:enable) */ // psx_cls(0, 0, 0); } } void psx_cls(uchar r, uchar g, uchar b) { RECT rect; short x; psx_init(FALSE); /* clear image */ rect.w = 1024; rect.h = 512; rect.x = 0; rect.y = 0; ClearImage(&rect, r, g, b); r += 0x7f; g += 0x7f; b += 0x7f; rect.w = 1; for (x = 64; x < 1024; x += 64) { rect.x = x; ClearImage(&rect, r, g, b); } } void guru (char * string) { DISPENV Disp; DRAWENV drawenv; RECT rect; int pad = (PADR1 | PADR2); if (noguru > 0) return; if (is_cd || 1) { psx_init(FALSE); if (PadRead(1) & PADL1) return; /* clear image */ rect.w = 320; rect.h = 200; rect.x = 0; rect.y = 0; ClearImage(&rect, 128, 0, 0); SetDefDispEnv(&Disp, 0, 0, 320, 256); Disp.screen.h = Disp.disp.h; Disp.screen.w = 256; Disp.screen.y = (288 - 256) / 2; VSync(0); PutDispEnv(&Disp); FntLoad(960, 256); SetDumpFnt(FntOpen(8, 8, 296, 64, 0, 512)); PutDrawEnv(SetDefDrawEnv(&drawenv, Disp.disp.x + 10, Disp.disp.y, 300, 200)); FntPrint(string); FntFlush(-1); while (PadRead(1) & PADRdown) VSync(0); while ((PadRead(1) & pad) == pad) VSync(0); sleep (1); while ((PadRead(1) & pad) != pad) { if (PadRead(1) & PADRdown) break; VSync(0); } ClearImage(&rect, 224, 224, 32); VSync(0); VSync(0); VSync(0); VSync(0); } else { printf("\n G U R U :\n %s\n\n", string); } } void init_psxutil() { uchar result[8]; ResetCallback(); // first check if we're running on the pc or the ps CdInit(); CdSetDebug(0); if (CdControl(CdlNop, 0, result)) is_cd = 1; else is_cd = 0; // initialiseer malloc if (is_cd) { // dit is 1.5 megabyte (vanaf 0.48Mb) gereserveerd // InitHeap2((void *) 0x80078000, 0x180000); } else { // dit is 2 megabyte (vanaf 2 Mb)gereserveerd // InitHeap2((void *) MALLOCSTA, MALLOCSIZE); } // onschuldige initialiseer functies psx_init(TRUE); // initialiseer filesysteem if (is_cd) { extern long cd_init(); // _96_remove(); // psx_cls(0, 128, 0); // _96_init(); // psx_cls(0, 0, 128); cd_init(); } else { PCinit(); // filesysteem reset } } void end_psxutil() { if (is_cd) { extern long cd_exit(); cd_exit(); } if(totblock) { printf("ERROR totblock %d\n", totblock); printmemlist(); } checkmemory(); } void set_dcache(int val) { static unsigned long oldsp=0; if(val) { oldsp= SetSp(DCACHE_TOP); } else { SetSp(oldsp); } } void error(str) { printf("ERROR: %s\n", str); } int streaming_is_on = FALSE; /* #### ##### ##### ###### ## # # # # # # # # # ## ## #### # # # ##### # # # ## # # # ##### # ###### # # # # # # # # # # # # #### # # # ###### # # # # */ void streaming_pause() { if (CdReadyCallback(0) == cdreadycallback) CdControl(CdlPause, 0, 0); if (active_stream) { active_stream->busy = FALSE; active_stream = 0; } } void streaming_stop() { streaming_pause(); streaming_is_on = FALSE; } void stream_start(Stream * stream) { CdlLOC cdloc; if (stream == 0) { guru("stream_start: stream = NULL"); return; } if ((int) stream == -1) { guru("stream_start: stream = -1"); return; } if (stream->index == 0) { guru("stream_start: stream->index = NULL"); return; } if (active_stream) active_stream->busy = FALSE; stream->done = FALSE; stream->busy = TRUE; if (stream->lastsector > stream->maxsector) stream->lastsector = stream->maxsector; if ((stream->sectorseek < stream->firstsector) | (stream->sectorseek > stream->lastsector)) stream->sectorseek = stream->firstsector; active_stream = stream; s_next_sector = active_stream->start + active_stream->sectorseek; CdIntToPos (s_next_sector, &cdloc); if (CdControl(CDLREAD, (uchar *) &cdloc, 0) != 1) guru("CdControl"); } void cdreadycallback(uchar status, uchar * result) { ushort s_full; int index, offset; cdheader header; CdlLOC cdloc; if ((active_stream != 0) && (active_stream->done == FALSE) && (active_stream->index != 0)) { // file is nog niet removed en zo switch (status) { case CdlDataReady: // er is een nieuw blok gelezen s_full = s_used - s_freed; if (s_full < 256) { // er is een block vrij: zoeken (dit kan 4 keer zo snel met longs....) for (index = 1; index < 256; index++) { if (s_in_use[index] == FALSE) break; } // lees sector in cache if (index != 256) { CdGetSector(&header, 3); if (CdGetSector(&cdcache[index].data, 512)) { // hier nog controleren of sector de juiste is... s_read_sector = CdPosToInt(&header.cdloc); if (s_read_sector == s_next_sector) { s_retry = 0; offset = s_read_sector - active_stream->start; if (offset < 0 || offset > active_stream->maxsector) { guru("Reading wrong sector !!"); } else { // is block al gecached ?? if (active_stream->index[offset] == 0) { s_used++; s_in_use[index] = TRUE; active_stream->index[offset] = index; } else { // we gaan springen want dit gedeelte is nog gecached... for (index = offset; index <= active_stream->lastsector; index++) { if (active_stream->index[index] == 0) break; } active_stream->sectorseek = index; if (active_stream->sectorseek > active_stream->lastsector) active_stream->done = TRUE; } if (offset == active_stream->sectorseek) { // deze sector werd ook verwacht, niemand heeft sectorseek veranderd active_stream->sectorseek++; if (active_stream->sectorseek > active_stream->lastsector) { // dit was de laatste sector. We zijn nu dus klaar. active_stream->done = TRUE; } else { // is er een belangrijke file waar op gewacht wordt ? if (urgent_stream == 0) { s_next_sector = active_stream->start + active_stream->sectorseek;; // ALLES EINDELIJK HELEMAAL GOED !! return; } } } } } else s_retry++; } else guru("CdGetSector"); } else guru("s_used / s_freed incorrect"); } else { // Hele cache is vol, we proberen het nog een keer // Dit is echter geen disk error s_retry = 0; } break; case CdlDiskError: strcpy((void *) s_status, "CdlDiskError"); break; default: sprintf((void *) s_status, "Unknown: %d", status); break; } } if (active_stream) { if (active_stream->done == TRUE) { active_stream->busy = FALSE; active_stream = 0; } } if ((active_stream == 0) || (urgent_stream != 0)) { // look for new file and start again if (active_stream) active_stream->busy = FALSE; if (urgent_stream) { active_stream = (void *) urgent_stream; urgent_stream = 0; } else { active_stream = s_list->first; while(active_stream) { if (active_stream->done == FALSE) break; active_stream = active_stream->next; } } } if (active_stream == 0) streaming_pause(); else stream_start(active_stream); } void streaming_exit() { // controleren of er nog een callback is, en die dan netjes stop zetten !! // HOE ? streaming_stop(); // cache sluiten if (cdcache) freeN(cdcache); cdcache = 0; } void streaming_init() { unsigned char mode; int i; static int first = TRUE; if (first) { first = FALSE; // guru("stream init"); } strcpy((void *) s_status, "no error"); // double speed: CdlModeSpeed, we lezen sector headers: CdlModeSize1 mode = CdlModeSpeed | CdlModeSize1; CdControlB(CdlSetmode, &mode, 0); // VSync(3) != 3 * VSync(0) VSync(0); VSync(0); VSync(0); VSync(0); // cache openen if (cdcache == 0) cdcache = mallocstructN(cdsector, 256, "cdcache"); if (cdcache == 0) guru("Not enough memory for cdcache !"); // indexen goedzetten s_in_use[0] = TRUE; for (i = 1; i <= 255; i++) s_in_use[i] = FALSE; // variabelen goed zetten s_used = 1; s_freed = 0; } void streaming_start() { Stream * stream = 0; static int first = TRUE; if (first) { first = FALSE; // guru("streaming start"); } // is er iets te streamen ? if (s_list->first == 0) return; // is init al gedaan ? if (cdcache == 0) streaming_init(); if (is_cd == 0) return; if (CdReadyCallback(cdreadycallback) != cdreadycallback) { // streaming was niet (meer) bezig streaming_is_on = TRUE; if (urgent_stream) { stream = (Stream *) urgent_stream; urgent_stream = 0; stream_start(stream); return; } else { for (stream = s_list->first; stream; stream = stream->next) { if (stream->done == FALSE) { stream_start(stream); return; } } } // error CdReadyCallback(0); streaming_is_on = FALSE; } } void stream_add(Stream * stream) { static int first = TRUE; if (first) { first = FALSE; // guru("add_stream"); } if (stream == 0) { guru("stream_add: stream = NULL"); return; } if ((int) stream == -1) { guru("stream_add: stream = -1"); return; } stream->done = stream->busy = 0; // some bounds checks if (stream->lastsector > stream->maxsector) stream->lastsector = stream->maxsector; if (stream->firstsector > stream->lastsector) stream->firstsector = 0; if (stream->sectorseek > stream->lastsector) stream->sectorseek = stream->firstsector; if (stream->sectorseek < stream->firstsector) stream->sectorseek = stream->firstsector; if (stream->index == NULL) { // nieuwe stroom altijd rewinden stream->sectorseek = stream->firstsector; stream->index = callocN(stream->maxsector + 1, "stream->index"); EnterCriticalSection(); addtail(s_list, stream); ExitCriticalSection(); } streaming_start(); } void stream_remove(Stream * stream) { int i, index; if (stream == 0) { guru("stream_remove: stream = NULL"); return; } if ((int) stream == -1) { guru("stream_remove: stream = -1"); return; } if (stream->index) { EnterCriticalSection(); stream->done = TRUE; if (stream == active_stream) active_stream = 0; remlink(s_list, stream); ExitCriticalSection(); for (i = 0; i <= stream->maxsector; i++) { if (index = stream->index[i]) { s_in_use[index] = 0; s_freed++; } } freeN(stream->index); stream->index = 0; } } void stream_close(Stream * stream) { int i, index; extern long my_close(long); if (stream == 0) { guru("stream_close: stream = NULL"); return; } if ((int) stream == -1) { guru("stream_close: stream = -1"); return; } close((int) stream); } Stream * stream_open(char * name) { int fd; extern long my_open(char *, ulong); fd = open(name, O_RDONLY); if (fd == -1) { sprintf(gurustr, "stream_open: can not open %s\n", name); guru(gurustr); fd = 0; } return((Stream *) fd); } void stream_set_minmax(Stream * stream, int min, int max) { if (stream == 0) { guru("stream_set_minmax: stream = NULL"); return; } if ((int) stream == -1) { guru("stream_set_minmax: stream = -1"); return; } if (max < min) { int t; t = max; max = min; min = t; } if (min < 0) min = 0; if (min > stream->maxsector) min = stream->maxsector; if (max == -1) max = stream->maxsector; if (max < 0) max = 0; if (max > stream->maxsector) max = stream->maxsector; stream->firstsector = min; stream->lastsector = max; stream->done = FALSE; streaming_start(); } /* ###### # # ###### # # # # ##### # # ##### # # # # # # # # # # ###### ###### */ char * cd_pc_name(char * name) { int i, slen; tmpname[0] = 0; tmpname[1] = 0; if (name) { if (name[0] == '.') { if (name[1] == '/') name += 2; else if (name[1] == '\\') name += 2; } if (is_cd == 0) { strcpy(tmpname, name); } else { if ((name[0] != '/') && (name[0] != '\\')) strcat(tmpname, "\\"); strcat(tmpname, name); slen = strlen(tmpname); // if its not a directory cat ;1 at the end if (tmpname[slen - 1] != '/' && tmpname[slen - 1] != '\\') { // het is een file if (strrchr(tmpname, '.') == 0) strcat(tmpname, "."); strcat(tmpname, ";1"); } } } // forward slash moet backward slash worden // lowercase moet uppercase worden slen = strlen(tmpname); for (i = slen - 1; i >= 0; i--) { char c = tmpname[i]; if (c == '/') tmpname[i] = '\\'; else if (c >= 'a' && c <= 'z') tmpname[i] = c + 'A' - 'a'; } return(tmpname); } long my_open(char * name, ulong flag) { long fd, i, error; CdlFILE _cdfile, *cdfile = &_cdfile; Stream * stream = 0; CD_File * cd_file = 0; CD_Dir * cd_dir; char * newname, * filename; newname = cd_pc_name(name); filename = strrchr(newname, '\\'); if (is_cd == 0) { fd = PCopen(newname, 0, 0); if (fd != -1) { stream = CLN(Stream); if (stream) { stream->fd = fd; stream->bytesize = PClseek(fd, 0, SEEK_END); } else PCclose(fd); } } else { if (dir_list->first) { if (filename) { filename[1] = 0; cd_dir = dir_list->first; while (cd_dir) { if (strcmp(cd_dir->name, newname) == 0) break; cd_dir = cd_dir->next; } if (cd_dir) { newname = cd_pc_name(name); filename = strrchr(newname, '\\'); filename++; cd_file = cd_dir->filelist.first; while(cd_file) { if (strcmp(cd_file->name, filename) == 0) break; cd_file = cd_file->next; } } } if (cd_file == 0) { sprintf(gurustr, "Can't find file for %s\n", name); guru(gurustr); } } newname = cd_pc_name(name); filename = strrchr(newname, '\\'); if (cd_file) { stream = CLN(Stream); stream->start = cd_file->start; stream->bytesize = cd_file->bytesize; strcpy(stream->name, cd_file->name); } else { // zet eventueel streaming stop stream = active_stream; if (stream) streaming_pause(); // zoeken error = (CdSearchFile(cdfile, newname) == 0); // streamen weer starten if (stream) { urgent_stream = stream; streaming_start(); } // verdere afhandeling if (error) { guru(newname); return(-1); } stream = CLN(Stream); stream->start = CdPosToInt(&cdfile->pos); stream->bytesize = cdfile->size; } } if (stream == 0) { guru(newname); return(-1); } else { if (filename) name = filename + 1; else name = newname; if (strlen(newname) < sizeof(stream->name)) name = newname; if (name == 0) name = "UNKNOWN"; if (strlen(name) >= sizeof(stream->name)) { name += strlen(name) - (sizeof(stream->name) + 1); } strcpy(stream->name, name); stream->maxsector = stream->lastsector = (stream->bytesize - 1) >> 11; } return((long) stream); } long my_lseek(long fd, long pos, long flag) { Stream * stream; if (fd == -1) return (-1); if (fd == 0) return (-1); stream = (Stream *) fd; switch (flag){ case SEEK_SET: stream->byteseek = pos; break; case SEEK_CUR: stream->byteseek += pos; break; case SEEK_END: stream->byteseek = stream->bytesize - pos; break; } if (stream->byteseek < 0) stream->byteseek = 0; if (stream->byteseek > stream->bytesize) stream->byteseek = stream->bytesize; return(stream->byteseek); } long my_read(int fd, void * buf, long size) { int start, end, sect, i, index; Stream * stream; char * name; CHECKPOINT(read1) if (fd == -1) { guru("read fd = -1"); return (-1); } if (fd == 0) { guru("read fd = 0"); return (-1); } stream = (Stream *) fd; name = stream->name; if (size <= 0) { if (size == 0) return(0); sprintf(gurustr, "%s: read size %d", name, size); guru(gurustr); return(-1); } if (buf == 0) { sprintf(gurustr, "%s: buf = 0", name); guru(gurustr); return(-1); } if (stream->byteseek + size > stream->bytesize) { // sprintf(gurustr, "myread: size to big \n%d + %d > %d", stream->byteseek, size, stream->bytesize); // guru(gurustr); size = stream->bytesize - stream->byteseek; } if (is_cd == 0) { PClseek(stream->fd, stream->byteseek, SEEK_SET); size = PCread(stream->fd, buf, size); if (size > 0) stream->byteseek += size; } else { // calc start = stream->byteseek >> 11; end = (stream->byteseek + size - 1) >> 11; if (end > stream->maxsector) end = stream->maxsector; if (end > stream->lastsector) { guru("end > stream->lastsector: adjusting"); stream->lastsector = end; } if (start < stream->firstsector) { guru("start < stream->firstsector: adjusting"); stream->firstsector = start; } sect = end - start + 1; if (streaming_is_on == FALSE) { CdlLOC cdloc; char * tbuf; unsigned char mode = CdlModeSpeed; int largest; largest = best_memblock(sect << 11); if (largest < (sect << 11)) { int totdone = 0, newsize, partdone; // korte blokken gaan lezen ivm met geheugen largest = (largest - 2048) & (~2047); printf("my_read: read of %d to large, reading chunks of %d\n", size, largest); while (size) { if (size > largest) newsize = largest; else newsize = size; partdone = read(fd, buf, newsize); if (partdone != -1) totdone += partdone; if (partdone != newsize) break; buf += partdone; size -= partdone; } size = totdone; if (size == 0) size = -1; } else { // seek CdIntToPos (stream->start + (stream->byteseek >> 11), &cdloc); CdControl(CdlSetloc, (u_char *) &cdloc, 0); // malloc tbuf = mallocN(sect << 11, "my_read"); if (tbuf== 0) return (-1); // read if (CdRead(sect, (void *) tbuf, CdlModeSpeed) == 0) { guru("cdread"); size = -1; } else { // guru("read started"); while ((sect = CdReadSync(1, 0)) > 0) { // sprintf(gurustr, "CdReadSync %d\n", sect); // guru(gurustr); } if (sect < 0) { guru("cdreadSync"); size = -1; } } // memcpy if (size > 0) { memcpy(buf, tbuf + (stream->byteseek & 2047), size); stream->byteseek += size; } freeN(tbuf); } } else { u_short s_full, s_free; int first, oldseek, len, index, remaining, prevstart; uchar * from, * to; CHECKPOINT(read2) if (stream->index == 0) { sprintf(gurustr, "read() %s: Can't mix stream / non-stream files !"); guru(gurustr); return(-1); } // free cache blocks before starting point prevstart = stream->prevstart; if (start < prevstart) prevstart = 0; if (stream->sectorseek < prevstart) prevstart = 0; for (i = prevstart; i < start; i++) { if (index = stream->index[i]) { stream->index[i] = 0; s_in_use[index] = 0; s_freed++; } } stream->prevstart = start; // look if data is cached CHECKPOINT(read3) /* Als een file aan het eind al voor een groot gedeelte gecached is, en er wordt een plaatje aan het begin gelezen, wordt er maar net genoeg ruimte voor dat ene plaatje vrijgemaakt. Daarna stopt de caching weer direct. Oplossing : grotere ruimte vrijmaken */ do { sect = 0; for (i = end; i >= start; i--) { if (stream->index[i] == 0) { sect++; first = i; } } if (sect) { // not all data is present... // is the cache full ? s_full = s_used - s_freed; s_free = 256 - s_full; if (s_free < sect) { // not eneough space to hold the data // solution: free from the end of this file for (i = stream->maxsector; i > end ; i--) { if (index = stream->index[i]) { stream->index[i] = 0; s_in_use[index] = 0; s_freed++; s_free++; if (s_free >= sect) break; } } if (s_free < sect) { guru("Cache is full, what now ?"); return(-1); } } if ((stream->busy == FALSE) || (stream->sectorseek < (first - 10)) || (stream->sectorseek > (first + 1))) { stream->sectorseek = first; } oldseek = stream->sectorseek; if (stream->busy == FALSE) urgent_stream = stream; // restart streaming if it was stopped streaming_start(); // wait for things to happen while (stream->busy == FALSE) { } while (stream->sectorseek == oldseek && stream->busy == TRUE) { } } } while (sect); CHECKPOINT(read4) // alle data is nu voorhanden to = buf; remaining = size; for (i = start; i <= end ; i++) { index = stream->index[i]; from = (uchar *) & cdcache[index].data; len = 2048; len -= stream->byteseek & 0x7ff; from += stream->byteseek & 0x7ff; if (len > remaining) len = remaining; memcpy(to, from, len); to += len; stream->byteseek += len; remaining -= len; } CHECKPOINT(read5) } } return (size); } long my_close(long fd) { Stream * stream; if (fd == -1) return (-1); if (fd == 0) return (-1); stream = (Stream *) fd; if (stream->index) stream_remove(stream); if (is_cd == 0) PCclose(stream->fd); freeN(stream); return(fd); } int cd_tonext(char *str) { int len= 0; while(*str!=' ' && isgraph( *str ) ) { str++; len++; if(len>256) return(len); } while(*str==' ' || isgraph( *str )==0 ) { str[0]= 0; str++; len++; if(len>256) return(len); } return(len); } long cd_init() { Stream * stream; CdlFILE _cdfile, *cdfile = &_cdfile; int fd, size, len, slen, org_cd = is_cd; uchar * buf, * pnt; char * name; CD_Dir * cd_dir; CD_File * cd_file; if (is_cd == 0) return(-1); if (dir_list->first) return (1); // open file.lst en anders auto.lst noguru++; fd = open("file.lst", O_RDONLY); if (fd == -1) fd = open("auto.lst", O_RDONLY); noguru--; if (fd == -1) { guru("no file.lst or auto.lst found"); return(-1); } if (is_cd) { stream = (Stream *) fd; } else { stream = CLN(Stream); stream->bytesize = lseek(fd, 0, SEEK_END); lseek(fd, 0, 0); } // lees file in en maak een index van alle files buf = mallocN(stream->bytesize, "cd_init"); if (buf) { size = stream->bytesize; if (read(fd, buf, size) == size) { pnt = buf; is_cd = TRUE; cd_dir = CLN(CD_Dir); strcpy(cd_dir->name, cd_pc_name("/")); addtail(dir_list, cd_dir); while (size > 1) { len = cd_tonext(pnt); slen = strlen(pnt); if (slen) { if (pnt[slen - 1] == ':') { // newdir pnt[slen - 1] = '/'; cd_dir = CLN(CD_Dir); name = cd_pc_name(pnt); strcpy(cd_dir->name, name); addtail(dir_list, cd_dir); // sprintf(gurustr, "newdir: %s\n", cd_dir->name); // guru(gurustr); } else if (pnt[slen - 1] == '/') { // skipping directories // sprintf(gurustr, "skipping %s\n", pnt); // guru(gurustr); } else { // regular file cd_file = CLN(CD_File); name = cd_pc_name(pnt); strcpy(cd_file->name, name + 1); addtail(&cd_dir->filelist, cd_file); // sprintf(gurustr, " adding %s to %s\n", cd_file->name, cd_dir->name); // guru(gurustr); // get data strcpy(tmpname, cd_dir->name); strcat(tmpname, cd_file->name); if (is_cd == org_cd) { if (CdSearchFile(cdfile, tmpname) == 0) { guru(tmpname); remlink(&cd_dir->filelist, cd_file); freeN(cd_file); } else { cd_file->start = CdPosToInt(&cdfile->pos); cd_file->bytesize = cdfile->size; } } } } pnt += len; size -= len; } is_cd = org_cd; } else guru("Error reading auto.list / file.list"); freeN(buf); } close(fd); if (is_cd == 0) freeN(stream); return(0); } long cd_exit() { ListBase * file_list; CD_Dir * cd_dir; CD_File * cd_file; if (is_cd == 0) return(-1); while (cd_dir = dir_list->first) { remlink(dir_list, cd_dir); file_list = & cd_dir->filelist; while (cd_file = file_list->first) { remlink(file_list, cd_file); freeN(cd_file); } freeN(cd_dir); } CdControl(CdlStop, 0, 0); return(0); }