Index: src/Cube.mm ================================================================== --- src/Cube.mm +++ src/Cube.mm @@ -7,10 +7,11 @@ VARF(gamespeed, 10, 100, 1000, if (multiplayer()) gamespeed = 100); VARP(minmillis, 0, 5, 1000); @implementation Cube { int _width, _height; + OFIRI *_userDataIRI; } + (Cube *)sharedInstance { return (Cube *)OFApplication.sharedApplication.delegate; @@ -114,20 +115,47 @@ log("gl"); gl_init(_width, _height); log("basetex"); + _gameDataIRI = [OFFileManager.defaultManager currentDirectoryIRI]; + _userDataIRI = [OFFileManager.defaultManager currentDirectoryIRI]; int xs, ys; - if (!installtex(2, path(newstring("data/newchars.png")), xs, ys) || - !installtex(3, path(newstring("data/martin/base.png")), xs, ys) || - !installtex(6, path(newstring("data/martin/ball1.png")), xs, ys) || - !installtex(7, path(newstring("data/martin/smoke.png")), xs, ys) || - !installtex(8, path(newstring("data/martin/ball2.png")), xs, ys) || - !installtex(9, path(newstring("data/martin/ball3.png")), xs, ys) || - !installtex(4, path(newstring("data/explosion.jpg")), xs, ys) || - !installtex(5, path(newstring("data/items.png")), xs, ys) || - !installtex(1, path(newstring("data/crosshair.png")), xs, ys)) + if (!installtex(2, + [_userDataIRI IRIByAppendingPathComponent:@"data/newchars.png"], + &xs, &ys, false) || + !installtex(3, + [_userDataIRI + IRIByAppendingPathComponent:@"data/martin/base.png"], + &xs, &ys, false) || + !installtex(6, + [_userDataIRI + IRIByAppendingPathComponent:@"data/martin/ball1.png"], + &xs, &ys, false) || + !installtex(7, + [_userDataIRI + IRIByAppendingPathComponent:@"data/martin/smoke.png"], + &xs, &ys, false) || + !installtex(8, + [_userDataIRI + IRIByAppendingPathComponent:@"data/martin/ball2.png"], + &xs, &ys, false) || + !installtex(9, + [_userDataIRI + IRIByAppendingPathComponent:@"data/martin/ball3.png"], + &xs, &ys, false) || + !installtex(4, + [_userDataIRI + IRIByAppendingPathComponent:@"data/explosion.jpg"], + &xs, &ys, false) || + !installtex(5, + [_userDataIRI IRIByAppendingPathComponent:@"data/items.png"], + &xs, &ys, false) || + !installtex(1, + [_userDataIRI + IRIByAppendingPathComponent:@"data/crosshair.png"], + &xs, &ys, false)) fatal(@"could not find core textures (hint: run cube from the " @"parent of the bin directory)"); log("sound"); initsound(); @@ -267,13 +295,20 @@ 3 * _width * (_height - 1 - idx), 3 * _width); endianswap(dest, 3, _width); } - sprintf_sd(buf)( - "screenshots/screenshot_%d.bmp", lastmillis); - SDL_SaveBMP(temp, path(buf)); + @autoreleasepool { + OFString *path = [OFString + stringWithFormat: + @"screenshots/screenshot_%d.bmp", + lastmillis]; + SDL_SaveBMP(temp, + [_userDataIRI + IRIByAppendingPathComponent:path] + .fileSystemRepresentation.UTF8String); + } SDL_FreeSurface(temp); } SDL_FreeSurface(image); } Index: src/clientextras.mm ================================================================== --- src/clientextras.mm +++ src/clientextras.mm @@ -167,30 +167,28 @@ if (mapname.length > 0) save_world(mapname); changemap(mapname); mapname = getclientmap(); int mapsize; - uchar *mapdata = readmap(mapname.UTF8String, &mapsize); - if (!mapdata) + OFData *mapdata = readmap(mapname); + if (mapdata == nil) return; ENetPacket *packet = enet_packet_create( NULL, MAXTRANS + mapsize, ENET_PACKET_FLAG_RELIABLE); uchar *start = packet->data; uchar *p = start + 2; putint(p, SV_SENDMAP); sendstring(mapname.UTF8String, p); putint(p, mapsize); - if (65535 - (p - start) < mapsize) { + if (65535 - (p - start) < mapdata.count) { conoutf( @"map %s is too large to send", mapname.UTF8String); - free(mapdata); enet_packet_destroy(packet); return; - }; - memcpy(p, mapdata, mapsize); + } + memcpy(p, mapdata.items, mapdata.count); p += mapsize; - free(mapdata); *(ushort *)start = ENET_HOST_TO_NET_16(p - start); enet_packet_resize(packet, p - start); sendpackettoserv(packet); conoutf(@"sending map %s to server...", mapname.UTF8String); sprintf_sd(msg)( Index: src/command.mm ================================================================== --- src/command.mm +++ src/command.mm @@ -555,17 +555,21 @@ bool execfile(OFString *cfgfile) { @autoreleasepool { - string s; - strcpy_s(s, cfgfile.UTF8String); - char *buf = loadfile(path(s), NULL); - if (!buf) + OFMutableData *data; + @try { + data = [OFMutableData dataWithContentsOfFile:cfgfile]; + } @catch (id e) { return false; - execute(buf); - free(buf); + } + + // Ensure \0 termination. + [data addItem:""]; + + execute((char *)data.mutableItems); return true; } } void Index: src/cube.h ================================================================== --- src/cube.h +++ src/cube.h @@ -9,10 +9,11 @@ #include "tools.h" @interface Cube : OFObject @property (class, readonly, nonatomic) Cube *sharedInstance; @property (readonly, nonatomic) SDL_Window *window; +@property (readonly, nonatomic) OFIRI *gameDataIRI; @property (nonatomic) bool repeatsKeys; @property (nonatomic) int framesInMap; @end enum // block types, order matters! Index: src/protos.h ================================================================== --- src/protos.h +++ src/protos.h @@ -42,16 +42,15 @@ // rendergl extern void gl_init(int w, int h); extern void cleangl(); extern void gl_drawframe(int w, int h, float curfps); -extern bool installtex( - int tnum, char *texname, int &xs, int &ys, bool clamp = false); +extern bool installtex(int tnum, OFIRI *IRI, int *xs, int *ys, bool clamp); extern void mipstats(int a, int b, int c); extern void vertf(float v1, float v2, float v3, sqr *ls, float t1, float t2); extern void addstrip(int tex, int start, int n); -extern int lookuptexture(int tex, int &xs, int &ys); +extern int lookuptexture(int tex, int *xs, int *ys); // rendercubes extern void resetcubes(); extern void render_flat(int tex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil); @@ -183,11 +182,11 @@ // worldio extern void save_world(OFString *fname); extern void load_world(char *mname); extern void writemap(char *mname, int msize, uchar *mdata); -extern uchar *readmap(const char *mname, int *msize); +extern OFData *readmap(OFString *mname); extern void loadgamerest(); extern void incomingdemodata(uchar *buf, int len, bool extras = false); extern void demoplaybackstep(); extern void stop(); extern void stopifrecording(); Index: src/rendercubes.mm ================================================================== --- src/rendercubes.mm +++ src/rendercubes.mm @@ -101,11 +101,11 @@ l3 = l1 = &sbright; l4 = l2 = &sdark; }; int sx, sy; - int gltex = lookuptexture(wtex, sx, sy); + int gltex = lookuptexture(wtex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; float xs = size * xf; float ys = size * yf; float xo = xf * x; @@ -182,11 +182,11 @@ l3 = l1 = &sbright; l4 = l2 = &sdark; }; int sx, sy; - int gltex = lookuptexture(wtex, sx, sy); + int gltex = lookuptexture(wtex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; float xs = size * xf; float ys = size * yf; float xo = xf * x; @@ -236,20 +236,20 @@ { stripend(); vertcheck(); int sx, sy; - int gltex = lookuptexture(h->ftex, sx, sy); + int gltex = lookuptexture(h->ftex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; vertf((float)x1, h->floor, (float)y1, l1, xf * x1, yf * y1); vertf((float)x2, h->floor, (float)y2, l2, xf * x2, yf * y2); vertf((float)x3, h->floor, (float)y3, l3, xf * x3, yf * y3); addstrip(gltex, curvert - 3, 3); - gltex = lookuptexture(h->ctex, sx, sy); + gltex = lookuptexture(h->ctex, &sx, &sy); xf = TEXTURESCALE / sx; yf = TEXTURESCALE / sy; vertf((float)x3, h->ceil, (float)y3, l3, xf * x3, yf * y3); vertf((float)x2, h->ceil, (float)y2, l2, xf * x2, yf * y2); @@ -290,11 +290,11 @@ l1 = &sbright; l2 = &sdark; }; int sx, sy; - int gltex = lookuptexture(wtex, sx, sy); + int gltex = lookuptexture(wtex, &sx, &sy); float xf = TEXTURESCALE / sx; float yf = TEXTURESCALE / sy; float xs = size * xf; float xo = xf * (x1 == x2 ? min(y1, y2) : min(x1, x2)); @@ -350,11 +350,11 @@ glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_SRC_COLOR); int sx, sy; - glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, sx, sy)); + glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, &sx, &sy)); wx1 &= ~(watersubdiv - 1); wy1 &= ~(watersubdiv - 1); float xf = TEXTURESCALE / sx; Index: src/renderextras.mm ================================================================== --- src/renderextras.mm +++ src/renderextras.mm @@ -204,22 +204,31 @@ void loadsky(OFString *basename) { @autoreleasepool { static OFString *lastsky = @""; + if ([lastsky isEqual:basename]) return; - char *side[] = {"ft", "bk", "lf", "rt", "dn", "up"}; + + static const OFString *side[] = { + @"ft", @"bk", @"lf", @"rt", @"dn", @"up"}; int texnum = 14; loopi(6) { - sprintf_sd(name)( - "packages/%s_%s.jpg", basename.UTF8String, side[i]); + OFString *path = + [OFString stringWithFormat:@"packages/%@_%@.jpg", + basename, side[i]]; + int xs, ys; - if (!installtex(texnum + i, path(name), xs, ys, true)) + if (!installtex(texnum + i, + [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path], + &xs, &ys, true)) conoutf(@"could not load sky textures"); } + lastsky = basename; } } COMMAND(loadsky, ARG_1STR) Index: src/rendergl.mm ================================================================== --- src/rendergl.mm +++ src/rendergl.mm @@ -71,83 +71,91 @@ if (qsphere) gluDeleteQuadric(qsphere); } bool -installtex(int tnum, char *texname, int &xs, int &ys, bool clamp) -{ - SDL_Surface *s = IMG_Load(texname); - if (s == NULL) { - conoutf(@"couldn't load texture %s", texname); - return false; - } - - if (s->format->BitsPerPixel != 24) { - SDL_PixelFormat *format = - SDL_AllocFormat(SDL_PIXELFORMAT_RGB24); - if (format == NULL) { - conoutf(@"texture cannot be converted to 24bpp: %s", - texname); - return false; - } - - @try { - SDL_Surface *converted = - SDL_ConvertSurface(s, format, 0); - if (converted == NULL) { - conoutf( - @"texture cannot be converted to 24bpp: %s", - texname); - return false; - } - - SDL_FreeSurface(s); - s = converted; - } @finally { - SDL_FreeFormat(format); - } - } - - // loopi(s->w*s->h*3) { uchar *p = (uchar *)s->pixels+i; *p = 255-*p; }; - glBindTexture(GL_TEXTURE_2D, tnum); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_LINEAR_MIPMAP_LINEAR); // NEAREST); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - xs = s->w; - ys = s->h; - while (xs > glmaxtexsize || ys > glmaxtexsize) { - xs /= 2; - ys /= 2; - } - - void *scaledimg = s->pixels; - - if (xs != s->w) { - conoutf(@"warning: quality loss: scaling %s", - texname); // for voodoo cards under linux - scaledimg = alloc(xs * ys * 3); - gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, s->pixels, - xs, ys, GL_UNSIGNED_BYTE, scaledimg); - } - - if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, xs, ys, GL_RGB, - GL_UNSIGNED_BYTE, scaledimg)) - fatal(@"could not build mipmaps"); - - if (xs != s->w) - free(scaledimg); - - SDL_FreeSurface(s); - - return true; +installtex(int tnum, OFIRI *IRI, int *xs, int *ys, bool clamp) +{ + @autoreleasepool { + SDL_Surface *s = + IMG_Load(IRI.fileSystemRepresentation.UTF8String); + if (s == NULL) { + conoutf( + @"couldn't load texture %s", IRI.string.UTF8String); + return false; + } + + if (s->format->BitsPerPixel != 24) { + SDL_PixelFormat *format = + SDL_AllocFormat(SDL_PIXELFORMAT_RGB24); + if (format == NULL) { + conoutf( + @"texture cannot be converted to 24bpp: %s", + IRI.string.UTF8String); + return false; + } + + @try { + SDL_Surface *converted = + SDL_ConvertSurface(s, format, 0); + if (converted == NULL) { + conoutf(@"texture cannot be converted " + @"to 24bpp: %s", + IRI.string.UTF8String); + return false; + } + + SDL_FreeSurface(s); + s = converted; + } @finally { + SDL_FreeFormat(format); + } + } + + // loopi(s->w*s->h*3) { uchar *p = (uchar *)s->pixels+i; *p = + // 255-*p; }; + glBindTexture(GL_TEXTURE_2D, tnum); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); // NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + *xs = s->w; + *ys = s->h; + while (*xs > glmaxtexsize || *ys > glmaxtexsize) { + *xs /= 2; + *ys /= 2; + } + + void *scaledimg = s->pixels; + + if (*xs != s->w) { + conoutf(@"warning: quality loss: scaling %s", + IRI.string + .UTF8String); // for voodoo cards under linux + scaledimg = alloc(*xs * *ys * 3); + gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, + s->pixels, *xs, *ys, GL_UNSIGNED_BYTE, scaledimg); + } + + if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, *xs, *ys, GL_RGB, + GL_UNSIGNED_BYTE, scaledimg)) + fatal(@"could not build mipmaps"); + + if (*xs != s->w) + free(scaledimg); + + SDL_FreeSurface(s); + + return true; + } } // management of texture slots // each texture slot can have multople texture frames, of which currently only // the first is used additional frames can be used for various shaders @@ -187,59 +195,64 @@ if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES) return; mapping[num][frame] = 1; char *n = mapname[num][frame]; strcpy_s(n, name.UTF8String); - path(n); } } COMMAND(texture, ARG_2STR) int -lookuptexture(int tex, int &xs, int &ys) +lookuptexture(int tex, int *xs, int *ys) { int frame = 0; // other frames? int tid = mapping[tex][frame]; if (tid >= FIRSTTEX) { - xs = texx[tid - FIRSTTEX]; - ys = texy[tid - FIRSTTEX]; + *xs = texx[tid - FIRSTTEX]; + *ys = texy[tid - FIRSTTEX]; return tid; - }; + } - xs = ys = 16; - if (!tid) + *xs = *ys = 16; + if (tid == 0) return 1; // crosshair :) loopi(curtex) // lazily happens once per "texture" command, basically { if (strcmp(mapname[tex][frame], texname[i]) == 0) { mapping[tex][frame] = tid = i + FIRSTTEX; - xs = texx[i]; - ys = texy[i]; + *xs = texx[i]; + *ys = texy[i]; return tid; - }; - }; + } + } if (curtex == MAXTEX) fatal(@"loaded too many textures"); int tnum = curtex + FIRSTTEX; strcpy_s(texname[curtex], mapname[tex][frame]); - sprintf_sd(name)("packages%c%s", PATHDIV, texname[curtex]); - - if (installtex(tnum, name, xs, ys)) { - mapping[tex][frame] = tnum; - texx[curtex] = xs; - texy[curtex] = ys; - curtex++; - return tnum; - } else { - return mapping[tex][frame] = FIRSTTEX; // temp fix - }; -}; + @autoreleasepool { + OFString *path = + [OFString stringWithFormat:@"packages/%s", texname[curtex]]; + + if (installtex(tnum, + [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path], + xs, ys, false)) { + mapping[tex][frame] = tnum; + texx[curtex] = *xs; + texy[curtex] = *ys; + curtex++; + return tnum; + } else { + return mapping[tex][frame] = FIRSTTEX; // temp fix + } + } +} void setupworld() { glEnableClientState(GL_VERTEX_ARRAY); @@ -416,11 +429,11 @@ transplayer(); glEnable(GL_TEXTURE_2D); int xs, ys; - skyoglid = lookuptexture(DEFAULT_SKY, xs, ys); + skyoglid = lookuptexture(DEFAULT_SKY, &xs, &ys); resetcubes(); curvert = 0; strips.setsize(0); Index: src/rendermd2.mm ================================================================== --- src/rendermd2.mm +++ src/rendermd2.mm @@ -40,11 +40,11 @@ @property (nonatomic) MapModelInfo *mmi; @property (copy, nonatomic) OFString *loadname; @property (nonatomic) int mdlnum; @property (nonatomic) bool loaded; -- (bool)loadWithPath:(char *)filename; +- (bool)loadWithIRI:(OFIRI *)IRI; - (void)renderWithLight:(OFVector3D &)light frame:(int)frame range:(int)range x:(float)x y:(float)y @@ -77,55 +77,66 @@ delete[] _glCommands; if (_frames) delete[] _frames; } -- (bool)loadWithPath:(char *)filename -{ - FILE *file; - md2_header header; - - if ((file = fopen(filename, "rb")) == NULL) - return false; - - fread(&header, sizeof(md2_header), 1, file); - endianswap(&header, sizeof(int), sizeof(md2_header) / sizeof(int)); - - if (header.magic != 844121161 || header.version != 8) - return false; - - _frames = new char[header.frameSize * header.numFrames]; - if (_frames == NULL) - return false; - - fseek(file, header.offsetFrames, SEEK_SET); - fread(_frames, header.frameSize * header.numFrames, 1, file); - - for (int i = 0; i < header.numFrames; ++i) - endianswap(_frames + i * header.frameSize, sizeof(float), 6); - - _glCommands = new int[header.numGlCommands]; - if (_glCommands == NULL) - return false; - - fseek(file, header.offsetGlCommands, SEEK_SET); - fread(_glCommands, header.numGlCommands * sizeof(int), 1, file); - - endianswap(_glCommands, sizeof(int), header.numGlCommands); - - _numFrames = header.numFrames; - _numGlCommands = header.numGlCommands; - _frameSize = header.frameSize; - _numTriangles = header.numTriangles; - _numVerts = header.numVertices; - - fclose(file); - - _mverts = new OFVector3D *[_numFrames]; - loopj(_numFrames) _mverts[j] = NULL; - - return true; +- (bool)loadWithIRI:(OFIRI *)IRI +{ + @autoreleasepool { + OFSeekableStream *stream; + @try { + stream = (OFSeekableStream *)[[OFIRIHandler + handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"]; + } @catch (id e) { + return false; + } + + if (![stream isKindOfClass:[OFSeekableStream class]]) + return false; + + md2_header header; + [stream readIntoBuffer:&header exactLength:sizeof(md2_header)]; + endianswap( + &header, sizeof(int), sizeof(md2_header) / sizeof(int)); + + if (header.magic != 844121161 || header.version != 8) + return false; + + _frames = new char[header.frameSize * header.numFrames]; + if (_frames == NULL) + return false; + + [stream seekToOffset:header.offsetFrames whence:OFSeekSet]; + [stream readIntoBuffer:_frames + exactLength:header.frameSize * header.numFrames]; + + for (int i = 0; i < header.numFrames; ++i) + endianswap( + _frames + i * header.frameSize, sizeof(float), 6); + + _glCommands = new int[header.numGlCommands]; + if (_glCommands == NULL) + return false; + + [stream seekToOffset:header.offsetGlCommands whence:OFSeekSet]; + [stream readIntoBuffer:_glCommands + exactLength:header.numGlCommands * sizeof(int)]; + endianswap(_glCommands, sizeof(int), header.numGlCommands); + + _numFrames = header.numFrames; + _numGlCommands = header.numGlCommands; + _frameSize = header.frameSize; + _numTriangles = header.numTriangles; + _numVerts = header.numVertices; + + [stream close]; + + _mverts = new OFVector3D *[_numFrames]; + loopj(_numFrames) _mverts[j] = NULL; + + return true; + } } float snap(int sn, float f) { @@ -233,18 +244,24 @@ void delayedload(MD2 *m) { if (!m.loaded) { @autoreleasepool { - sprintf_sd(name1)("packages/models/%s/tris.md2", - m.loadname.UTF8String); - if (![m loadWithPath:path(name1)]) - fatal(@"loadmodel: ", @(name1)); - sprintf_sd(name2)("packages/models/%s/skin.jpg", - m.loadname.UTF8String); + OFString *path = [OFString + stringWithFormat:@"packages/models/%@", m.loadname]; + OFIRI *baseIRI = [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path]; + + OFIRI *IRI1 = + [baseIRI IRIByAppendingPathComponent:@"tris.md2"]; + if (![m loadWithIRI:IRI1]) + fatal(@"loadmodel: ", IRI1.string); + + OFIRI *IRI2 = + [baseIRI IRIByAppendingPathComponent:@"skin.jpg"]; int xs, ys; - installtex(FIRSTMDL + m.mdlnum, path(name2), xs, ys); + installtex(FIRSTMDL + m.mdlnum, IRI2, &xs, &ys, false); m.loaded = true; } } } @@ -312,11 +329,11 @@ delayedload(m); int xs, ys; glBindTexture(GL_TEXTURE_2D, - tex ? lookuptexture(tex, xs, ys) : FIRSTMDL + m.mdlnum); + tex ? lookuptexture(tex, &xs, &ys) : FIRSTMDL + m.mdlnum); int ix = (int)x; int iy = (int)z; OFVector3D light = OFMakeVector3D(1, 1, 1); Index: src/sound.mm ================================================================== --- src/sound.mm +++ src/sound.mm @@ -84,24 +84,29 @@ if (nosound) return; stopsound(); if (soundvol && musicvol) { @autoreleasepool { - string sn; - strcpy_s(sn, "packages/"); - strcat_s(sn, name.UTF8String); + OFString *path = + [OFString stringWithFormat:@"packages/%@", name]; + OFIRI *IRI = [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path]; + #ifdef USE_MIXER - if (mod = Mix_LoadMUS(path(sn))) { + if (mod = Mix_LoadMUS( + IRI.fileSystemRepresentation.UTF8String)) { Mix_PlayMusic(mod, -1); Mix_VolumeMusic((musicvol * MAXVOL) / 255); } #else - if (mod = FMUSIC_LoadSong(path(sn))) { + if (mod = FMUSIC_LoadSong( + IRI.fileSystemRepresentation.UTF8String)) { FMUSIC_PlaySong(mod); FMUSIC_SetMasterVolume(mod, musicvol); } else if (stream = FSOUND_Stream_Open( - path(sn), FSOUND_LOOP_NORMAL, 0, 0)) { + IRI.fileSystemRepresentation.UTF8String, + FSOUND_LOOP_NORMAL, 0, 0)) { int chan = FSOUND_Stream_Play(FSOUND_FREE, stream); if (chan >= 0) { FSOUND_SetVolume( chan, (musicvol * MAXVOL) / 255); @@ -228,27 +233,33 @@ return; // avoid bursts of sounds with heavy packetloss // and in sp if (n < 0 || n >= samples.length()) { conoutf(@"unregistered sound: %d", n); return; - }; + } if (!samples[n]) { - sprintf_sd(buf)("packages/sounds/%s.wav", snames[n]); + OFString *path = [OFString + stringWithFormat:@"packages/sounds/%s.wav", snames[n]]; + OFIRI *IRI = [Cube.sharedInstance.gameDataIRI + IRIByAppendingPathComponent:path]; #ifdef USE_MIXER - samples[n] = Mix_LoadWAV(path(buf)); + samples[n] = + Mix_LoadWAV(IRI.fileSystemRepresentation.UTF8String); #else - samples[n] = - FSOUND_Sample_Load(n, path(buf), FSOUND_LOOP_OFF, 0, 0); + samples[n] = FSOUND_Sample_Load(n, + IRI.fileSystemRepresentation.UTF8String, FSOUND_LOOP_OFF, 0, + 0); #endif if (!samples[n]) { - conoutf(@"failed to load sample: %s", buf); + conoutf(@"failed to load sample: %s", + IRI.string.UTF8String); return; - }; - }; + } + } #ifdef USE_MIXER int chan = Mix_PlayChannel(-1, samples[n], 0); #else int chan = FSOUND_PlaySoundEx(FSOUND_FREE, samples[n], NULL, true); @@ -259,13 +270,13 @@ newsoundloc(chan, loc); updatechanvol(chan, loc); #ifndef USE_MIXER FSOUND_SetPaused(chan, false); #endif -}; +} void sound(int n) { playsound(n, NULL); } COMMAND(sound, ARG_1INT) Index: src/tools.h ================================================================== --- src/tools.h +++ src/tools.h @@ -120,12 +120,10 @@ } #define sprintf_sdv(d, fmt) sprintf_sdlv(d, fmt, fmt) #define fast_f2nat(val) ((int)(val)) -extern char *path(char *s); -extern char *loadfile(char *fn, int *size); extern void endianswap(void *, int, int); // memory pool that uses buckets and linear allocation for small objects // VERY fast, and reasonably good memory reuse Index: src/tools.mm ================================================================== --- src/tools.mm +++ src/tools.mm @@ -98,42 +98,10 @@ return p ? p : (p = new pool()); }; ///////////////////////// misc tools /////////////////////// -char * -path(char *s) -{ - for (char *t = s; t = strpbrk(t, "/\\"); *t++ = PATHDIV) - ; - return s; -}; - -char * -loadfile(char *fn, int *size) -{ - FILE *f = fopen(fn, "rb"); - if (!f) - return NULL; - fseek(f, 0, SEEK_END); - int len = ftell(f); - fseek(f, 0, SEEK_SET); - char *buf = (char *)malloc(len + 1); - if (!buf) - return NULL; - buf[len] = 0; - size_t rlen = fread(buf, 1, len, f); - fclose(f); - if (len != rlen || len <= 0) { - free(buf); - return NULL; - }; - if (size != NULL) - *size = len; - return buf; -}; - void endianswap( void *memory, int stride, int length) // little indians as storage format { if (*((char *)&stride)) Index: src/weapon.mm ================================================================== --- src/weapon.mm +++ src/weapon.mm @@ -5,16 +5,16 @@ struct guninfo { short sound, attackdelay, damage, projspeed, part, kickamount; OFString *name; }; -const int MONSTERDAMAGEFACTOR = 4; -const int SGRAYS = 20; -const float SGSPREAD = 2; -OFVector3D sg[SGRAYS]; +static const int MONSTERDAMAGEFACTOR = 4; +static const int SGRAYS = 20; +static const float SGSPREAD = 2; +static OFVector3D sg[SGRAYS]; -guninfo guns[NUMGUNS] = { +static const guninfo guns[NUMGUNS] = { {S_PUNCH1, 250, 50, 0, 0, 1, @"fist"}, {S_SG, 1400, 10, 0, 0, 20, @"shotgun"}, // *SGRAYS {S_CG, 100, 30, 0, 0, 7, @"chaingun"}, {S_RLFIRE, 800, 120, 80, 0, 10, @"rocketlauncher"}, {S_RIFLE, 1500, 100, 0, 0, 30, @"rifle"}, Index: src/worldio.mm ================================================================== --- src/worldio.mm +++ src/worldio.mm @@ -26,13 +26,10 @@ sprintf_s(cgzname)("packages/%s/%s.cgz", pakname, mapname); sprintf_s(bakname)( "packages/%s/%s_%d.BAK", pakname, mapname, lastmillis); sprintf_s(pcfname)("packages/%s/package.cfg", pakname); sprintf_s(mcfname)("packages/%s/%s.cfg", pakname, mapname); - - path(cgzname); - path(bakname); } // the optimize routines below are here to reduce the detrimental effects of // messy mapping by setting certain properties (vdeltas and textures) to // neighbouring values wherever there is no visible difference. This allows the @@ -135,20 +132,17 @@ fwrite(mdata, 1, msize, f); fclose(f); conoutf(@"wrote map %s as file %s", mname, cgzname); } -uchar * -readmap(const char *mname, int *msize) -{ - setnames(mname); - uchar *mdata = (uchar *)loadfile(cgzname, msize); - if (!mdata) { - conoutf(@"could not read map %s", cgzname); - return NULL; - } - return mdata; +OFData * +readmap(OFString *mname) +{ + @autoreleasepool { + setnames(mname.UTF8String); + } + return [OFData dataWithContentsOfFile:mname]; } // save map as .cgz file. uses 2 layers of compression: first does simple // run-length encoding and leaves out data for certain kinds of cubes, then zlib // removes the last bits of redundancy. Both passes contribute greatly to the @@ -360,11 +354,11 @@ } gzclose(f); calclight(); settagareas(); int xs, ys; - loopi(256) if (texuse) lookuptexture(i, xs, ys); + loopi(256) if (texuse) lookuptexture(i, &xs, &ys); conoutf(@"read map %s (%d milliseconds)", cgzname, SDL_GetTicks() - lastmillis); conoutf(@"%s", hdr.maptitle); startmap(mname); loopl(256)