Clean up file handling

FossilOrigin-Name: 3d55e077f74fc1c036e856cc4fdf0ae3c308c58f7d37eb9392f1a15f10cc237d
This commit is contained in:
Jonathan Schleifer 2025-03-05 21:29:54 +00:00
parent c6eebefd77
commit ab582d3745
14 changed files with 278 additions and 231 deletions

View file

@ -9,6 +9,7 @@ VARP(minmillis, 0, 5, 1000);
@implementation Cube { @implementation Cube {
int _width, _height; int _width, _height;
OFIRI *_userDataIRI;
} }
+ (Cube *)sharedInstance + (Cube *)sharedInstance
@ -116,16 +117,43 @@ VARP(minmillis, 0, 5, 1000);
gl_init(_width, _height); gl_init(_width, _height);
log("basetex"); log("basetex");
_gameDataIRI = [OFFileManager.defaultManager currentDirectoryIRI];
_userDataIRI = [OFFileManager.defaultManager currentDirectoryIRI];
int xs, ys; int xs, ys;
if (!installtex(2, path(newstring("data/newchars.png")), xs, ys) || if (!installtex(2,
!installtex(3, path(newstring("data/martin/base.png")), xs, ys) || [_userDataIRI IRIByAppendingPathComponent:@"data/newchars.png"],
!installtex(6, path(newstring("data/martin/ball1.png")), xs, ys) || &xs, &ys, false) ||
!installtex(7, path(newstring("data/martin/smoke.png")), xs, ys) || !installtex(3,
!installtex(8, path(newstring("data/martin/ball2.png")), xs, ys) || [_userDataIRI
!installtex(9, path(newstring("data/martin/ball3.png")), xs, ys) || IRIByAppendingPathComponent:@"data/martin/base.png"],
!installtex(4, path(newstring("data/explosion.jpg")), xs, ys) || &xs, &ys, false) ||
!installtex(5, path(newstring("data/items.png")), xs, ys) || !installtex(6,
!installtex(1, path(newstring("data/crosshair.png")), xs, ys)) [_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 " fatal(@"could not find core textures (hint: run cube from the "
@"parent of the bin directory)"); @"parent of the bin directory)");
@ -269,9 +297,16 @@ VARP(minmillis, 0, 5, 1000);
endianswap(dest, 3, _width); endianswap(dest, 3, _width);
} }
sprintf_sd(buf)( @autoreleasepool {
"screenshots/screenshot_%d.bmp", lastmillis); OFString *path = [OFString
SDL_SaveBMP(temp, path(buf)); stringWithFormat:
@"screenshots/screenshot_%d.bmp",
lastmillis];
SDL_SaveBMP(temp,
[_userDataIRI
IRIByAppendingPathComponent:path]
.fileSystemRepresentation.UTF8String);
}
SDL_FreeSurface(temp); SDL_FreeSurface(temp);
} }

View file

@ -169,8 +169,8 @@ sendmap(OFString *mapname)
changemap(mapname); changemap(mapname);
mapname = getclientmap(); mapname = getclientmap();
int mapsize; int mapsize;
uchar *mapdata = readmap(mapname.UTF8String, &mapsize); OFData *mapdata = readmap(mapname);
if (!mapdata) if (mapdata == nil)
return; return;
ENetPacket *packet = enet_packet_create( ENetPacket *packet = enet_packet_create(
NULL, MAXTRANS + mapsize, ENET_PACKET_FLAG_RELIABLE); NULL, MAXTRANS + mapsize, ENET_PACKET_FLAG_RELIABLE);
@ -179,16 +179,14 @@ sendmap(OFString *mapname)
putint(p, SV_SENDMAP); putint(p, SV_SENDMAP);
sendstring(mapname.UTF8String, p); sendstring(mapname.UTF8String, p);
putint(p, mapsize); putint(p, mapsize);
if (65535 - (p - start) < mapsize) { if (65535 - (p - start) < mapdata.count) {
conoutf( conoutf(
@"map %s is too large to send", mapname.UTF8String); @"map %s is too large to send", mapname.UTF8String);
free(mapdata);
enet_packet_destroy(packet); enet_packet_destroy(packet);
return; return;
}; }
memcpy(p, mapdata, mapsize); memcpy(p, mapdata.items, mapdata.count);
p += mapsize; p += mapsize;
free(mapdata);
*(ushort *)start = ENET_HOST_TO_NET_16(p - start); *(ushort *)start = ENET_HOST_TO_NET_16(p - start);
enet_packet_resize(packet, p - start); enet_packet_resize(packet, p - start);
sendpackettoserv(packet); sendpackettoserv(packet);

View file

@ -557,13 +557,17 @@ bool
execfile(OFString *cfgfile) execfile(OFString *cfgfile)
{ {
@autoreleasepool { @autoreleasepool {
string s; OFMutableData *data;
strcpy_s(s, cfgfile.UTF8String); @try {
char *buf = loadfile(path(s), NULL); data = [OFMutableData dataWithContentsOfFile:cfgfile];
if (!buf) } @catch (id e) {
return false; return false;
execute(buf); }
free(buf);
// Ensure \0 termination.
[data addItem:""];
execute((char *)data.mutableItems);
return true; return true;
} }
} }

View file

@ -11,6 +11,7 @@
@interface Cube : OFObject <OFApplicationDelegate> @interface Cube : OFObject <OFApplicationDelegate>
@property (class, readonly, nonatomic) Cube *sharedInstance; @property (class, readonly, nonatomic) Cube *sharedInstance;
@property (readonly, nonatomic) SDL_Window *window; @property (readonly, nonatomic) SDL_Window *window;
@property (readonly, nonatomic) OFIRI *gameDataIRI;
@property (nonatomic) bool repeatsKeys; @property (nonatomic) bool repeatsKeys;
@property (nonatomic) int framesInMap; @property (nonatomic) int framesInMap;
@end @end

View file

@ -44,12 +44,11 @@ extern void writeservercfg();
extern void gl_init(int w, int h); extern void gl_init(int w, int h);
extern void cleangl(); extern void cleangl();
extern void gl_drawframe(int w, int h, float curfps); extern void gl_drawframe(int w, int h, float curfps);
extern bool installtex( extern bool installtex(int tnum, OFIRI *IRI, int *xs, int *ys, bool clamp);
int tnum, char *texname, int &xs, int &ys, bool clamp = false);
extern void mipstats(int a, int b, int c); 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 vertf(float v1, float v2, float v3, sqr *ls, float t1, float t2);
extern void addstrip(int tex, int start, int n); 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 // rendercubes
extern void resetcubes(); extern void resetcubes();
@ -185,7 +184,7 @@ extern void render_particles(int time);
extern void save_world(OFString *fname); extern void save_world(OFString *fname);
extern void load_world(char *mname); extern void load_world(char *mname);
extern void writemap(char *mname, int msize, uchar *mdata); 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 loadgamerest();
extern void incomingdemodata(uchar *buf, int len, bool extras = false); extern void incomingdemodata(uchar *buf, int len, bool extras = false);
extern void demoplaybackstep(); extern void demoplaybackstep();

View file

@ -103,7 +103,7 @@ render_flat(int wtex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3,
}; };
int sx, sy; int sx, sy;
int gltex = lookuptexture(wtex, sx, sy); int gltex = lookuptexture(wtex, &sx, &sy);
float xf = TEXTURESCALE / sx; float xf = TEXTURESCALE / sx;
float yf = TEXTURESCALE / sy; float yf = TEXTURESCALE / sy;
float xs = size * xf; float xs = size * xf;
@ -184,7 +184,7 @@ render_flatdelta(int wtex, int x, int y, int size, float h1, float h2, float h3,
}; };
int sx, sy; int sx, sy;
int gltex = lookuptexture(wtex, sx, sy); int gltex = lookuptexture(wtex, &sx, &sy);
float xf = TEXTURESCALE / sx; float xf = TEXTURESCALE / sx;
float yf = TEXTURESCALE / sy; float yf = TEXTURESCALE / sy;
float xs = size * xf; float xs = size * xf;
@ -238,7 +238,7 @@ render_2tris(sqr *h, sqr *s, int x1, int y1, int x2, int y2, int x3, int y3,
vertcheck(); vertcheck();
int sx, sy; int sx, sy;
int gltex = lookuptexture(h->ftex, sx, sy); int gltex = lookuptexture(h->ftex, &sx, &sy);
float xf = TEXTURESCALE / sx; float xf = TEXTURESCALE / sx;
float yf = TEXTURESCALE / sy; float yf = TEXTURESCALE / sy;
@ -247,7 +247,7 @@ render_2tris(sqr *h, sqr *s, int x1, int y1, int x2, int y2, int x3, int y3,
vertf((float)x3, h->floor, (float)y3, l3, xf * x3, yf * y3); vertf((float)x3, h->floor, (float)y3, l3, xf * x3, yf * y3);
addstrip(gltex, curvert - 3, 3); addstrip(gltex, curvert - 3, 3);
gltex = lookuptexture(h->ctex, sx, sy); gltex = lookuptexture(h->ctex, &sx, &sy);
xf = TEXTURESCALE / sx; xf = TEXTURESCALE / sx;
yf = TEXTURESCALE / sy; yf = TEXTURESCALE / sy;
@ -292,7 +292,7 @@ render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2,
}; };
int sx, sy; int sx, sy;
int gltex = lookuptexture(wtex, sx, sy); int gltex = lookuptexture(wtex, &sx, &sy);
float xf = TEXTURESCALE / sx; float xf = TEXTURESCALE / sx;
float yf = TEXTURESCALE / sy; float yf = TEXTURESCALE / sy;
float xs = size * xf; float xs = size * xf;
@ -352,7 +352,7 @@ renderwater(float hf)
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR); glBlendFunc(GL_ONE, GL_SRC_COLOR);
int sx, sy; int sx, sy;
glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, sx, sy)); glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, &sx, &sy));
wx1 &= ~(watersubdiv - 1); wx1 &= ~(watersubdiv - 1);
wy1 &= ~(watersubdiv - 1); wy1 &= ~(watersubdiv - 1);

View file

@ -206,18 +206,27 @@ loadsky(OFString *basename)
{ {
@autoreleasepool { @autoreleasepool {
static OFString *lastsky = @""; static OFString *lastsky = @"";
if ([lastsky isEqual:basename]) if ([lastsky isEqual:basename])
return; return;
char *side[] = {"ft", "bk", "lf", "rt", "dn", "up"};
static const OFString *side[] = {
@"ft", @"bk", @"lf", @"rt", @"dn", @"up"};
int texnum = 14; int texnum = 14;
loopi(6) loopi(6)
{ {
sprintf_sd(name)( OFString *path =
"packages/%s_%s.jpg", basename.UTF8String, side[i]); [OFString stringWithFormat:@"packages/%@_%@.jpg",
basename, side[i]];
int xs, ys; 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"); conoutf(@"could not load sky textures");
} }
lastsky = basename; lastsky = basename;
} }
} }

View file

@ -73,11 +73,14 @@ cleangl()
} }
bool bool
installtex(int tnum, char *texname, int &xs, int &ys, bool clamp) installtex(int tnum, OFIRI *IRI, int *xs, int *ys, bool clamp)
{ {
SDL_Surface *s = IMG_Load(texname); @autoreleasepool {
SDL_Surface *s =
IMG_Load(IRI.fileSystemRepresentation.UTF8String);
if (s == NULL) { if (s == NULL) {
conoutf(@"couldn't load texture %s", texname); conoutf(
@"couldn't load texture %s", IRI.string.UTF8String);
return false; return false;
} }
@ -85,8 +88,9 @@ installtex(int tnum, char *texname, int &xs, int &ys, bool clamp)
SDL_PixelFormat *format = SDL_PixelFormat *format =
SDL_AllocFormat(SDL_PIXELFORMAT_RGB24); SDL_AllocFormat(SDL_PIXELFORMAT_RGB24);
if (format == NULL) { if (format == NULL) {
conoutf(@"texture cannot be converted to 24bpp: %s", conoutf(
texname); @"texture cannot be converted to 24bpp: %s",
IRI.string.UTF8String);
return false; return false;
} }
@ -94,9 +98,9 @@ installtex(int tnum, char *texname, int &xs, int &ys, bool clamp)
SDL_Surface *converted = SDL_Surface *converted =
SDL_ConvertSurface(s, format, 0); SDL_ConvertSurface(s, format, 0);
if (converted == NULL) { if (converted == NULL) {
conoutf( conoutf(@"texture cannot be converted "
@"texture cannot be converted to 24bpp: %s", @"to 24bpp: %s",
texname); IRI.string.UTF8String);
return false; return false;
} }
@ -107,46 +111,50 @@ installtex(int tnum, char *texname, int &xs, int &ys, bool clamp)
} }
} }
// loopi(s->w*s->h*3) { uchar *p = (uchar *)s->pixels+i; *p = 255-*p; }; // loopi(s->w*s->h*3) { uchar *p = (uchar *)s->pixels+i; *p =
// 255-*p; };
glBindTexture(GL_TEXTURE_2D, tnum); glBindTexture(GL_TEXTURE_2D, tnum);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR); // NEAREST); GL_LINEAR_MIPMAP_LINEAR); // NEAREST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
xs = s->w; *xs = s->w;
ys = s->h; *ys = s->h;
while (xs > glmaxtexsize || ys > glmaxtexsize) { while (*xs > glmaxtexsize || *ys > glmaxtexsize) {
xs /= 2; *xs /= 2;
ys /= 2; *ys /= 2;
} }
void *scaledimg = s->pixels; void *scaledimg = s->pixels;
if (xs != s->w) { if (*xs != s->w) {
conoutf(@"warning: quality loss: scaling %s", conoutf(@"warning: quality loss: scaling %s",
texname); // for voodoo cards under linux IRI.string
scaledimg = alloc(xs * ys * 3); .UTF8String); // for voodoo cards under linux
gluScaleImage(GL_RGB, s->w, s->h, GL_UNSIGNED_BYTE, s->pixels, scaledimg = alloc(*xs * *ys * 3);
xs, ys, GL_UNSIGNED_BYTE, scaledimg); 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, if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, *xs, *ys, GL_RGB,
GL_UNSIGNED_BYTE, scaledimg)) GL_UNSIGNED_BYTE, scaledimg))
fatal(@"could not build mipmaps"); fatal(@"could not build mipmaps");
if (xs != s->w) if (*xs != s->w)
free(scaledimg); free(scaledimg);
SDL_FreeSurface(s); SDL_FreeSurface(s);
return true; return true;
} }
}
// management of texture slots // management of texture slots
// each texture slot can have multople texture frames, of which currently only // each texture slot can have multople texture frames, of which currently only
@ -189,36 +197,35 @@ texture(OFString *aframe, OFString *name)
mapping[num][frame] = 1; mapping[num][frame] = 1;
char *n = mapname[num][frame]; char *n = mapname[num][frame];
strcpy_s(n, name.UTF8String); strcpy_s(n, name.UTF8String);
path(n);
} }
} }
COMMAND(texture, ARG_2STR) COMMAND(texture, ARG_2STR)
int int
lookuptexture(int tex, int &xs, int &ys) lookuptexture(int tex, int *xs, int *ys)
{ {
int frame = 0; // other frames? int frame = 0; // other frames?
int tid = mapping[tex][frame]; int tid = mapping[tex][frame];
if (tid >= FIRSTTEX) { if (tid >= FIRSTTEX) {
xs = texx[tid - FIRSTTEX]; *xs = texx[tid - FIRSTTEX];
ys = texy[tid - FIRSTTEX]; *ys = texy[tid - FIRSTTEX];
return tid; return tid;
}; }
xs = ys = 16; *xs = *ys = 16;
if (!tid) if (tid == 0)
return 1; // crosshair :) return 1; // crosshair :)
loopi(curtex) // lazily happens once per "texture" command, basically loopi(curtex) // lazily happens once per "texture" command, basically
{ {
if (strcmp(mapname[tex][frame], texname[i]) == 0) { if (strcmp(mapname[tex][frame], texname[i]) == 0) {
mapping[tex][frame] = tid = i + FIRSTTEX; mapping[tex][frame] = tid = i + FIRSTTEX;
xs = texx[i]; *xs = texx[i];
ys = texy[i]; *ys = texy[i];
return tid; return tid;
}; }
}; }
if (curtex == MAXTEX) if (curtex == MAXTEX)
fatal(@"loaded too many textures"); fatal(@"loaded too many textures");
@ -226,18 +233,24 @@ lookuptexture(int tex, int &xs, int &ys)
int tnum = curtex + FIRSTTEX; int tnum = curtex + FIRSTTEX;
strcpy_s(texname[curtex], mapname[tex][frame]); strcpy_s(texname[curtex], mapname[tex][frame]);
sprintf_sd(name)("packages%c%s", PATHDIV, texname[curtex]); @autoreleasepool {
OFString *path =
[OFString stringWithFormat:@"packages/%s", texname[curtex]];
if (installtex(tnum, name, xs, ys)) { if (installtex(tnum,
[Cube.sharedInstance.gameDataIRI
IRIByAppendingPathComponent:path],
xs, ys, false)) {
mapping[tex][frame] = tnum; mapping[tex][frame] = tnum;
texx[curtex] = xs; texx[curtex] = *xs;
texy[curtex] = ys; texy[curtex] = *ys;
curtex++; curtex++;
return tnum; return tnum;
} else { } else {
return mapping[tex][frame] = FIRSTTEX; // temp fix return mapping[tex][frame] = FIRSTTEX; // temp fix
}; }
}; }
}
void void
setupworld() setupworld()
@ -418,7 +431,7 @@ gl_drawframe(int w, int h, float curfps)
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
int xs, ys; int xs, ys;
skyoglid = lookuptexture(DEFAULT_SKY, xs, ys); skyoglid = lookuptexture(DEFAULT_SKY, &xs, &ys);
resetcubes(); resetcubes();

View file

@ -42,7 +42,7 @@ struct md2_frame {
@property (nonatomic) int mdlnum; @property (nonatomic) int mdlnum;
@property (nonatomic) bool loaded; @property (nonatomic) bool loaded;
- (bool)loadWithPath:(char *)filename; - (bool)loadWithIRI:(OFIRI *)IRI;
- (void)renderWithLight:(OFVector3D &)light - (void)renderWithLight:(OFVector3D &)light
frame:(int)frame frame:(int)frame
range:(int)range range:(int)range
@ -79,16 +79,24 @@ static OFMutableArray<MD2 *> *mapmodels = nil;
delete[] _frames; delete[] _frames;
} }
- (bool)loadWithPath:(char *)filename - (bool)loadWithIRI:(OFIRI *)IRI
{ {
FILE *file; @autoreleasepool {
md2_header header; OFSeekableStream *stream;
@try {
stream = (OFSeekableStream *)[[OFIRIHandler
handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"];
} @catch (id e) {
return false;
}
if ((file = fopen(filename, "rb")) == NULL) if (![stream isKindOfClass:[OFSeekableStream class]])
return false; return false;
fread(&header, sizeof(md2_header), 1, file); md2_header header;
endianswap(&header, sizeof(int), sizeof(md2_header) / sizeof(int)); [stream readIntoBuffer:&header exactLength:sizeof(md2_header)];
endianswap(
&header, sizeof(int), sizeof(md2_header) / sizeof(int));
if (header.magic != 844121161 || header.version != 8) if (header.magic != 844121161 || header.version != 8)
return false; return false;
@ -97,19 +105,21 @@ static OFMutableArray<MD2 *> *mapmodels = nil;
if (_frames == NULL) if (_frames == NULL)
return false; return false;
fseek(file, header.offsetFrames, SEEK_SET); [stream seekToOffset:header.offsetFrames whence:OFSeekSet];
fread(_frames, header.frameSize * header.numFrames, 1, file); [stream readIntoBuffer:_frames
exactLength:header.frameSize * header.numFrames];
for (int i = 0; i < header.numFrames; ++i) for (int i = 0; i < header.numFrames; ++i)
endianswap(_frames + i * header.frameSize, sizeof(float), 6); endianswap(
_frames + i * header.frameSize, sizeof(float), 6);
_glCommands = new int[header.numGlCommands]; _glCommands = new int[header.numGlCommands];
if (_glCommands == NULL) if (_glCommands == NULL)
return false; return false;
fseek(file, header.offsetGlCommands, SEEK_SET); [stream seekToOffset:header.offsetGlCommands whence:OFSeekSet];
fread(_glCommands, header.numGlCommands * sizeof(int), 1, file); [stream readIntoBuffer:_glCommands
exactLength:header.numGlCommands * sizeof(int)];
endianswap(_glCommands, sizeof(int), header.numGlCommands); endianswap(_glCommands, sizeof(int), header.numGlCommands);
_numFrames = header.numFrames; _numFrames = header.numFrames;
@ -118,13 +128,14 @@ static OFMutableArray<MD2 *> *mapmodels = nil;
_numTriangles = header.numTriangles; _numTriangles = header.numTriangles;
_numVerts = header.numVertices; _numVerts = header.numVertices;
fclose(file); [stream close];
_mverts = new OFVector3D *[_numFrames]; _mverts = new OFVector3D *[_numFrames];
loopj(_numFrames) _mverts[j] = NULL; loopj(_numFrames) _mverts[j] = NULL;
return true; return true;
} }
}
float float
snap(int sn, float f) snap(int sn, float f)
@ -235,14 +246,20 @@ delayedload(MD2 *m)
{ {
if (!m.loaded) { if (!m.loaded) {
@autoreleasepool { @autoreleasepool {
sprintf_sd(name1)("packages/models/%s/tris.md2", OFString *path = [OFString
m.loadname.UTF8String); stringWithFormat:@"packages/models/%@", m.loadname];
if (![m loadWithPath:path(name1)]) OFIRI *baseIRI = [Cube.sharedInstance.gameDataIRI
fatal(@"loadmodel: ", @(name1)); IRIByAppendingPathComponent:path];
sprintf_sd(name2)("packages/models/%s/skin.jpg",
m.loadname.UTF8String); OFIRI *IRI1 =
[baseIRI IRIByAppendingPathComponent:@"tris.md2"];
if (![m loadWithIRI:IRI1])
fatal(@"loadmodel: ", IRI1.string);
OFIRI *IRI2 =
[baseIRI IRIByAppendingPathComponent:@"skin.jpg"];
int xs, ys; int xs, ys;
installtex(FIRSTMDL + m.mdlnum, path(name2), xs, ys); installtex(FIRSTMDL + m.mdlnum, IRI2, &xs, &ys, false);
m.loaded = true; m.loaded = true;
} }
} }
@ -314,7 +331,7 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad, float x,
int xs, ys; int xs, ys;
glBindTexture(GL_TEXTURE_2D, 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 ix = (int)x;
int iy = (int)z; int iy = (int)z;

View file

@ -86,20 +86,25 @@ music(OFString *name)
stopsound(); stopsound();
if (soundvol && musicvol) { if (soundvol && musicvol) {
@autoreleasepool { @autoreleasepool {
string sn; OFString *path =
strcpy_s(sn, "packages/"); [OFString stringWithFormat:@"packages/%@", name];
strcat_s(sn, name.UTF8String); OFIRI *IRI = [Cube.sharedInstance.gameDataIRI
IRIByAppendingPathComponent:path];
#ifdef USE_MIXER #ifdef USE_MIXER
if (mod = Mix_LoadMUS(path(sn))) { if (mod = Mix_LoadMUS(
IRI.fileSystemRepresentation.UTF8String)) {
Mix_PlayMusic(mod, -1); Mix_PlayMusic(mod, -1);
Mix_VolumeMusic((musicvol * MAXVOL) / 255); Mix_VolumeMusic((musicvol * MAXVOL) / 255);
} }
#else #else
if (mod = FMUSIC_LoadSong(path(sn))) { if (mod = FMUSIC_LoadSong(
IRI.fileSystemRepresentation.UTF8String)) {
FMUSIC_PlaySong(mod); FMUSIC_PlaySong(mod);
FMUSIC_SetMasterVolume(mod, musicvol); FMUSIC_SetMasterVolume(mod, musicvol);
} else if (stream = FSOUND_Stream_Open( } else if (stream = FSOUND_Stream_Open(
path(sn), FSOUND_LOOP_NORMAL, 0, 0)) { IRI.fileSystemRepresentation.UTF8String,
FSOUND_LOOP_NORMAL, 0, 0)) {
int chan = int chan =
FSOUND_Stream_Play(FSOUND_FREE, stream); FSOUND_Stream_Play(FSOUND_FREE, stream);
if (chan >= 0) { if (chan >= 0) {
@ -230,23 +235,29 @@ playsound(int n, OFVector3D *loc)
if (n < 0 || n >= samples.length()) { if (n < 0 || n >= samples.length()) {
conoutf(@"unregistered sound: %d", n); conoutf(@"unregistered sound: %d", n);
return; return;
}; }
if (!samples[n]) { 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 #ifdef USE_MIXER
samples[n] = Mix_LoadWAV(path(buf));
#else
samples[n] = samples[n] =
FSOUND_Sample_Load(n, path(buf), FSOUND_LOOP_OFF, 0, 0); Mix_LoadWAV(IRI.fileSystemRepresentation.UTF8String);
#else
samples[n] = FSOUND_Sample_Load(n,
IRI.fileSystemRepresentation.UTF8String, FSOUND_LOOP_OFF, 0,
0);
#endif #endif
if (!samples[n]) { if (!samples[n]) {
conoutf(@"failed to load sample: %s", buf); conoutf(@"failed to load sample: %s",
IRI.string.UTF8String);
return; return;
}; }
}; }
#ifdef USE_MIXER #ifdef USE_MIXER
int chan = Mix_PlayChannel(-1, samples[n], 0); int chan = Mix_PlayChannel(-1, samples[n], 0);
@ -261,7 +272,7 @@ playsound(int n, OFVector3D *loc)
#ifndef USE_MIXER #ifndef USE_MIXER
FSOUND_SetPaused(chan, false); FSOUND_SetPaused(chan, false);
#endif #endif
}; }
void void
sound(int n) sound(int n)

View file

@ -122,8 +122,6 @@ struct sprintf_s_f {
#define fast_f2nat(val) ((int)(val)) #define fast_f2nat(val) ((int)(val))
extern char *path(char *s);
extern char *loadfile(char *fn, int *size);
extern void endianswap(void *, int, int); extern void endianswap(void *, int, int);
// memory pool that uses buckets and linear allocation for small objects // memory pool that uses buckets and linear allocation for small objects

View file

@ -100,38 +100,6 @@ gp() // useful for global buffers that need to be initialisation order
///////////////////////// misc tools /////////////////////// ///////////////////////// 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 void
endianswap( endianswap(
void *memory, int stride, int length) // little indians as storage format void *memory, int stride, int length) // little indians as storage format

View file

@ -7,12 +7,12 @@ struct guninfo {
OFString *name; OFString *name;
}; };
const int MONSTERDAMAGEFACTOR = 4; static const int MONSTERDAMAGEFACTOR = 4;
const int SGRAYS = 20; static const int SGRAYS = 20;
const float SGSPREAD = 2; static const float SGSPREAD = 2;
OFVector3D sg[SGRAYS]; static OFVector3D sg[SGRAYS];
guninfo guns[NUMGUNS] = { static const guninfo guns[NUMGUNS] = {
{S_PUNCH1, 250, 50, 0, 0, 1, @"fist"}, {S_PUNCH1, 250, 50, 0, 0, 1, @"fist"},
{S_SG, 1400, 10, 0, 0, 20, @"shotgun"}, // *SGRAYS {S_SG, 1400, 10, 0, 0, 20, @"shotgun"}, // *SGRAYS
{S_CG, 100, 30, 0, 0, 7, @"chaingun"}, {S_CG, 100, 30, 0, 0, 7, @"chaingun"},

View file

@ -28,9 +28,6 @@ setnames(const char *name)
"packages/%s/%s_%d.BAK", pakname, mapname, lastmillis); "packages/%s/%s_%d.BAK", pakname, mapname, lastmillis);
sprintf_s(pcfname)("packages/%s/package.cfg", pakname); sprintf_s(pcfname)("packages/%s/package.cfg", pakname);
sprintf_s(mcfname)("packages/%s/%s.cfg", pakname, mapname); 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 // the optimize routines below are here to reduce the detrimental effects of
@ -137,16 +134,13 @@ writemap(char *mname, int msize, uchar *mdata)
conoutf(@"wrote map %s as file %s", mname, cgzname); conoutf(@"wrote map %s as file %s", mname, cgzname);
} }
uchar * OFData *
readmap(const char *mname, int *msize) readmap(OFString *mname)
{ {
setnames(mname); @autoreleasepool {
uchar *mdata = (uchar *)loadfile(cgzname, msize); setnames(mname.UTF8String);
if (!mdata) {
conoutf(@"could not read map %s", cgzname);
return NULL;
} }
return mdata; return [OFData dataWithContentsOfFile:mname];
} }
// save map as .cgz file. uses 2 layers of compression: first does simple // save map as .cgz file. uses 2 layers of compression: first does simple
@ -362,7 +356,7 @@ load_world(char *mname) // still supports all map formats that have existed
calclight(); calclight();
settagareas(); settagareas();
int xs, ys; 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, conoutf(@"read map %s (%d milliseconds)", cgzname,
SDL_GetTicks() - lastmillis); SDL_GetTicks() - lastmillis);
conoutf(@"%s", hdr.maptitle); conoutf(@"%s", hdr.maptitle);