Index: src/editing.mm ================================================================== --- src/editing.mm +++ src/editing.mm @@ -237,41 +237,50 @@ linestyle(GRIDS, 0xFF, 0x40, 0x40); box(sel, (float)selh, (float)selh, (float)selh, (float)selh); } } -vector undos; // unlimited undo -VARP(undomegs, 0, 1, 10); // bounded by n megs +static OFMutableData *undos; // unlimited undo +VARP(undomegs, 0, 1, 10); // bounded by n megs void pruneundos(int maxremain) // bound memory { int t = 0; - loopvrev(undos) - { - t += undos[i]->xs * undos[i]->ys * sizeof(sqr); - if (t > maxremain) - OFFreeMemory(undos.remove(i)); + for (ssize_t i = (ssize_t)undos.count - 1; i >= 0; i--) { + block *undo = *(block **)[undos itemAtIndex:i]; + + t += undo->xs * undo->ys * sizeof(sqr); + if (t > maxremain) { + OFFreeMemory(undo); + [undos removeItemAtIndex:i]; + } } } void makeundo() { - undos.add(blockcopy(sel)); + if (undos == nil) + undos = + [[OFMutableData alloc] initWithItemSize:sizeof(block *)]; + + block *copy = blockcopy(sel); + [undos addItem:©]; pruneundos(undomegs << 20); } void editundo() { EDITMP; - if (undos.empty()) { + if (undos.count == 0) { conoutf(@"nothing more to undo"); return; } - block *p = undos.pop(); + block *p = *(block **)undos.lastItem; + [undos removeLastItem]; blockpaste(*p); OFFreeMemory(p); } block *copybuf = NULL; Index: src/protos.h ================================================================== --- src/protos.h +++ src/protos.h @@ -113,11 +113,11 @@ // world extern void setupworld(int factor); extern void empty_world(int factor, bool force); extern void remip(block &b, int level = 0); -extern void remipmore(block &b, int level = 0); +extern void remipmore(const block &b, int level = 0); extern int closestent(); extern int findentity(int type, int index = 0); extern void trigger(int tag, int type, bool savegame); extern void resettagareas(); extern void settagareas(); @@ -128,11 +128,11 @@ extern void calclight(); extern void dodynlight(const OFVector3D &vold, const OFVector3D &v, int reach, int strength, DynamicEntity *owner); extern void cleardlights(); extern block *blockcopy(block &b); -extern void blockpaste(block &b); +extern void blockpaste(const block &b); // worldrender extern void render_world(float vx, float vy, float vh, int yaw, int pitch, float widef, int w, int h); Index: src/rendergl.mm ================================================================== --- src/rendergl.mm +++ src/rendergl.mm @@ -272,31 +272,41 @@ int skyoglid; struct strip { int tex, start, num; }; -vector strips; +static OFMutableData *strips; void renderstripssky() { glBindTexture(GL_TEXTURE_2D, skyoglid); - loopv(strips) if (strips[i].tex == skyoglid) - glDrawArrays(GL_TRIANGLE_STRIP, strips[i].start, strips[i].num); + + const strip *items = (const strip *)strips.items; + size_t count = strips.count; + for (size_t i = 0; i < count; i++) + if (items[i].tex == skyoglid) + glDrawArrays( + GL_TRIANGLE_STRIP, items[i].start, items[i].num); } void renderstrips() { int lasttex = -1; - loopv(strips) if (strips[i].tex != skyoglid) - { - if (strips[i].tex != lasttex) { - glBindTexture(GL_TEXTURE_2D, strips[i].tex); - lasttex = strips[i].tex; + const strip *items = (const strip *)strips.items; + size_t count = strips.count; + for (size_t i = 0; i < count; i++) { + if (items[i].tex == skyoglid) + continue; + + if (items[i].tex != lasttex) { + glBindTexture(GL_TEXTURE_2D, items[i].tex); + lasttex = items[i].tex; } - glDrawArrays(GL_TRIANGLE_STRIP, strips[i].start, strips[i].num); + + glDrawArrays(GL_TRIANGLE_STRIP, items[i].start, items[i].num); } } void overbright(float amount) @@ -306,14 +316,15 @@ } void addstrip(int tex, int start, int n) { - strip &s = strips.add(); - s.tex = tex; - s.start = start; - s.num = n; + if (strips == nil) + strips = [[OFMutableData alloc] initWithItemSize:sizeof(strip)]; + + strip s = { .tex = tex, .start = start, .num = n }; + [strips addItem:&s]; } VARFP(gamma, 30, 100, 300, { float f = gamma / 100.0f; Uint16 ramp[256]; @@ -432,11 +443,11 @@ skyoglid = lookuptexture(DEFAULT_SKY, &xs, &ys); resetcubes(); curvert = 0; - strips.setsize(0); + [strips removeAllItems]; render_world(player1.o.x, player1.o.y, player1.o.z, (int)player1.yaw, (int)player1.pitch, (float)fov, w, h); finishstrips(); Index: src/sound.mm ================================================================== --- src/sound.mm +++ src/sound.mm @@ -1,38 +1,37 @@ #include "cube.h" #import "DynamicEntity.h" + +#include VARP(soundvol, 0, 255, 255); VARP(musicvol, 0, 128, 255); bool nosound = false; #define MAXCHAN 32 #define SOUNDFREQ 22050 +#define MAXVOL MIX_MAX_VOLUME struct soundloc { OFVector3D loc; bool inuse; } soundlocs[MAXCHAN]; -#include -#define MAXVOL MIX_MAX_VOLUME -Mix_Music *mod = NULL; -void *stream = NULL; +static Mix_Music *mod = NULL; void stopsound() { if (nosound) return; - if (mod) { + + if (mod != NULL) { Mix_HaltMusic(); Mix_FreeMusic(mod); mod = NULL; } - if (stream != NULL) - stream = NULL; } VAR(soundbufferlen, 128, 1024, 4096); void @@ -51,11 +50,13 @@ void music(OFString *name) { if (nosound) return; + stopsound(); + if (soundvol && musicvol) { name = [name stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; OFString *path = [OFString stringWithFormat:@"packages/%@", name]; @@ -69,12 +70,11 @@ } } } COMMAND(music, ARG_1STR) -vector samples; - +static OFMutableData *samples; static OFMutableArray *snames; int registersound(OFString *name) { @@ -86,16 +86,20 @@ i++; } if (snames == nil) snames = [[OFMutableArray alloc] init]; + if (samples == nil) + samples = [[OFMutableData alloc] + initWithItemSize:sizeof(Mix_Chunk *)]; [snames addObject:[name stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]]; - samples.add(NULL); + Mix_Chunk *sample = NULL; + [samples addItem:&sample]; - return samples.length() - 1; + return samples.count - 1; } COMMAND(registersound, ARG_1EST) void cleansound() @@ -163,49 +167,56 @@ void playsound(int n, const OFVector3D *loc) { if (nosound) return; + if (!soundvol) return; + if (lastmillis == lastsoundmillis) soundsatonce++; else soundsatonce = 1; + lastsoundmillis = lastmillis; + if (soundsatonce > 5) - return; // avoid bursts of sounds with heavy packetloss - // and in sp - if (n < 0 || n >= samples.length()) { + // avoid bursts of sounds with heavy packetloss and in sp + return; + + if (n < 0 || n >= samples.count) { conoutf(@"unregistered sound: %d", n); return; } - if (!samples[n]) { + Mix_Chunk **sample = (Mix_Chunk **)[samples mutableItemAtIndex:n]; + if (*sample == NULL) { OFString *path = [OFString stringWithFormat:@"packages/sounds/%@.wav", snames[n]]; OFIRI *IRI = [Cube.sharedInstance.gameDataIRI IRIByAppendingPathComponent:path]; - samples[n] = - Mix_LoadWAV(IRI.fileSystemRepresentation.UTF8String); + *sample = Mix_LoadWAV(IRI.fileSystemRepresentation.UTF8String); - if (!samples[n]) { + if (*sample == NULL) { conoutf(@"failed to load sample: %@", IRI.string); return; } } - int chan = Mix_PlayChannel(-1, samples[n], 0); + int chan = Mix_PlayChannel(-1, *sample, 0); if (chan < 0) return; + if (loc) newsoundloc(chan, loc); + updatechanvol(chan, loc); } void sound(int n) { playsound(n, NULL); } COMMAND(sound, ARG_1INT) Index: src/tools.h ================================================================== --- src/tools.h +++ src/tools.h @@ -17,23 +17,13 @@ #include #include #include #include #include -#ifdef __GNUC__ -# include -#else -# include -#endif #import -#ifdef NULL -# undef NULL -#endif -#define NULL 0 - typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; #define max(a, b) (((a) > (b)) ? (a) : (b)) @@ -50,139 +40,12 @@ #define loopk(m) loop(k, m) #define loopl(m) loop(l, m) #ifndef OF_WINDOWS # define __cdecl -# define _vsnprintf vsnprintf #endif #define fast_f2nat(val) ((int)(val)) extern void endianswap(void *, int, int); -template struct vector { - T *buf; - int alen; - int ulen; - - vector() - { - alen = 8; - buf = (T *)OFAllocMemory(alen, sizeof(T)); - ulen = 0; - } - - ~vector() - { - setsize(0); - free(buf); - } - - vector(vector &v); - void operator=(vector &v); - - T & - add(const T &x) - { - if (ulen == alen) - realloc(); - new (&buf[ulen]) T(x); - return buf[ulen++]; - } - - T & - add() - { - if (ulen == alen) - realloc(); - new (&buf[ulen]) T; - return buf[ulen++]; - } - - T & - pop() - { - return buf[--ulen]; - } - - T & - last() - { - return buf[ulen - 1]; - } - - bool - empty() - { - return ulen == 0; - } - - int - length() - { - return ulen; - } - - T & - operator[](int i) - { - assert(i >= 0 && i < ulen); - return buf[i]; - } - - void - setsize(int i) - { - for (; ulen > i; ulen--) - buf[ulen - 1].~T(); - } - - T * - getbuf() - { - return buf; - } - - void - sort(void *cf) - { - qsort(buf, ulen, sizeof(T), - (int(__cdecl *)(const void *, const void *))cf); - } - - void - realloc() - { - buf = (T *)OFResizeMemory(buf, (alen *= 2), sizeof(T)); - } - - T - remove(int i) - { - T e = buf[i]; - for (int p = i + 1; p < ulen; p++) - buf[p - 1] = buf[p]; - ulen--; - return e; - } - - T & - insert(int i, const T &e) - { - add(T()); - for (int p = ulen - 1; p > i; p--) - buf[p] = buf[p - 1]; - buf[i] = e; - return buf[i]; - } -}; - -#define loopv(v) \ - if (false) { \ - } else \ - for (int i = 0; i < (v).length(); i++) -#define loopvrev(v) \ - if (false) { \ - } else \ - for (int i = (v).length() - 1; i >= 0; i--) - #endif Index: src/world.mm ================================================================== --- src/world.mm +++ src/world.mm @@ -240,11 +240,11 @@ s.ys /= 2; remip(s, level + 1); } void -remipmore(block &b, int level) +remipmore(const block &b, int level) { block bb = b; if (bb.x > 1) bb.x--; if (bb.y > 1) Index: src/worldlight.mm ================================================================== --- src/worldlight.mm +++ src/worldlight.mm @@ -260,11 +260,11 @@ *q++ = *S(x, y); return b; } void -blockpaste(block &b) +blockpaste(const block &b) { sqr *q = (sqr *)((&b) + 1); for (int x = b.x; x < b.xs + b.x; x++) for (int y = b.y; y < b.ys + b.y; y++) *S(x, y) = *q++;