diff --git a/source/enet/enet_dll.cbp b/source/enet/enet_dll.cbp
index 961274c7..7d8f8c9d 100644
--- a/source/enet/enet_dll.cbp
+++ b/source/enet/enet_dll.cbp
@@ -31,10 +31,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/source/lib/enet.lib b/source/lib/enet.lib
index 0af1d82c..5bc04977 100644
Binary files a/source/lib/enet.lib and b/source/lib/enet.lib differ
diff --git a/source/src/jpegenc.h b/source/src/jpegenc.h
index 7ed4de9a..a3a46750 100644
--- a/source/src/jpegenc.h
+++ b/source/src/jpegenc.h
@@ -51,6 +51,22 @@ struct APP0infotype
};
};
+struct APP1infotype
+{
+ WORD marker;
+ WORD length;
+ const char *sig1, *sig2;
+ APP1infotype()
+ {
+ marker = 0xFFE1;
+ length = 46;
+ sig1 = "Exif\0\0MM";
+ sig2 = "\0\x2a\0\0\0\10\0\1\1\x31\0\2\0\0\0\14"
+ "\0\0\0\x1a\0\0\0\0\101\x73\x73\141\165"
+ "\154\164\103\165\142\145";
+ };
+};
+
struct SOF0infotype
{
WORD marker;
@@ -189,6 +205,7 @@ class jpegenc
static WORD mask[];
APP0infotype APP0info;
+ APP1infotype APP1info;
SOF0infotype SOF0info;
DQTinfotype DQTinfo;
SOSinfotype SOSinfo;
@@ -198,6 +215,7 @@ class jpegenc
SBYTE bytepos;
void write_APP0info(void);
+ void write_APP1info(void);
void write_SOF0info(void);
void write_DQTinfo(void);
void set_quant_table(BYTE *basic_table, BYTE scale_factor, BYTE *newtable);
@@ -205,7 +223,7 @@ class jpegenc
void write_DHTinfo(void);
void set_DHTinfo(void);
void write_SOSinfo(void);
- void write_comment(BYTE *comment);
+ void write_comment(const char *comment);
void writebits(bitstring bs);
void compute_Huffman_table(BYTE *nrcodes, BYTE *std_table, bitstring *HT);
void init_Huffman_tables(void);
@@ -255,7 +273,7 @@ class jpegenc
stream *fp_jpeg_stream;
- int encode(const char *filename, SDL_Surface *image, int jpegquality);
+ int encode(const char *filename, SDL_Surface *image, int jpegquality, const char *comment);
};
BYTE jpegenc::zigzag[64] = {
@@ -347,11 +365,6 @@ BYTE jpegenc::std_ac_chrominance_values[162] = {
WORD jpegenc::mask[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
-
-//******************************************************************************
-//******************************************************************************
-// Toca: TODO: the following goes into jpegenc.cpp or some other .cpp file
-
void jpegenc::write_APP0info() //Nothing to overwrite for APP0info
{
writeword(APP0info.marker);
@@ -370,6 +383,14 @@ void jpegenc::write_APP0info() //Nothing to overwrite for APP0info
writebyte(APP0info.thumbnheight);
}
+void jpegenc::write_APP1info()
+{
+ writeword(APP1info.marker);
+ writeword(APP1info.length);
+ loopi(8) writebyte(APP1info.sig1[i]);
+ loopi(APP1info.length - 10) writebyte(APP1info.sig2[i]);
+}
+
void jpegenc::write_SOF0info()
{
writeword(SOF0info.marker);
@@ -500,7 +521,7 @@ void jpegenc::write_SOSinfo() //Nothing to overwrite for SOSinfo
writebyte(SOSinfo.Bf);
}
-void jpegenc::write_comment(BYTE *comment)
+void jpegenc::write_comment(const char *comment)
{
WORD i, length;
writeword(0xFFFE);
@@ -811,7 +832,7 @@ void jpegenc::main_encoder()
}
}
-int jpegenc::encode(const char *filename, SDL_Surface *image, int jpegquality)
+int jpegenc::encode(const char *filename, SDL_Surface *image, int jpegquality, const char *comment)
{
RGB_buffer = (BYTE *)image->pixels;
width = image->w;
@@ -842,7 +863,8 @@ int jpegenc::encode(const char *filename, SDL_Surface *image, int jpegquality)
writeword(0xFFD8);
write_APP0info();
- // write_comment("Cris made this JPEG with his own encoder");
+ write_APP1info();
+ if(comment) write_comment(comment);
write_DQTinfo();
write_SOF0info();
write_DHTinfo();
diff --git a/source/src/main.cpp b/source/src/main.cpp
index 6331e59d..f238473c 100644
--- a/source/src/main.cpp
+++ b/source/src/main.cpp
@@ -175,16 +175,16 @@ void setprocesspriority(bool high)
VARP(pngcompress, 0, 9, 9);
-void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0)
+void writepngchunk(stream *f, const char *type, const void *data = NULL, uint len = 0)
{
f->putbig(len);
f->write(type, 4);
- f->write(data, len);
+ if(data) f->write(data, len);
uint crc = crc32(0, Z_NULL, 0);
- crc = crc32(crc, (const Bytef *)type, 4);
- if(data) crc = crc32(crc, data, len);
- f->putbig(crc);
+ crc = ~crc32(crc, (const Bytef *)type, 4);
+ if(data) loopi(len) enet_crc32_inc(&crc, ((const uchar *)data)[i]);
+ f->putbig(~crc);
}
int save_png(const char *filename, SDL_Surface *image)
@@ -194,6 +194,7 @@ int save_png(const char *filename, SDL_Surface *image)
stream *f = openfile(filename, "wb");
if(!f) { conoutf("could not write to %s", filename); return -1; }
+ const char *scores = asciiscores(true);
uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
f->write(signature, sizeof(signature));
@@ -261,6 +262,8 @@ int save_png(const char *filename, SDL_Surface *image)
f->seek(0, SEEK_END);
f->putbig(crc);
+ writepngchunk(f, "tEXt", "\123o\165rc\145\0\101ss\141" "\165\154\164\103\165\142\145", 18);
+ writepngchunk(f, "tEXt", scores - 8, strlen(scores) + 8);
writepngchunk(f, "IEND");
delete f;
@@ -367,7 +370,7 @@ void mapscreenshot(const char *imagepath, bool mapshot, int fileformat, float sc
case 1: // jpeg
{
jpegenc jpegencoder;
- jpegencoder.encode(imagepath, image, quality);
+ jpegencoder.encode(imagepath, image, quality, asciiscores(true));
break;
}
case 2: // png
diff --git a/source/src/scoreboard.cpp b/source/src/scoreboard.cpp
index bf5f0fa8..b6aa43c7 100644
--- a/source/src/scoreboard.cpp
+++ b/source/src/scoreboard.cpp
@@ -439,7 +439,7 @@ void renderscores(void *menu, bool init)
#define MAXJPGCOM 65533 // maximum JPEG comment length
-void addstr(char *dest, const char *src) { if(strlen(dest) + strlen(src) < MAXJPGCOM) strcat(dest, src); }
+static void addstr(char *&dest, const char *end, const char *src) { size_t l = strlen(src); if(dest + l < end) copystring(dest, src, l + 1), dest += l; }
const char *asciiscores(bool destjpg)
{
@@ -455,16 +455,17 @@ const char *asciiscores(bool destjpg)
loopv(players) if(players[i]) scores.add(players[i]);
scores.sort(scorecmp);
- buf[0] = '\0';
+ copystring(buf, "Comment", MAXJPGCOM); // include PNG keyword and skip it (which looks like a hack because it is one)
+ char *t = buf + 8, *e = buf + MAXJPGCOM;
if(destjpg)
{
formatstring(text)("AssaultCube Screenshot (%s)\n", asctimestr());
- addstr(buf, text);
+ addstr(t, e, text);
}
if(getclientmap()[0])
{
formatstring(text)("\n\"%s\" on map %s", modestr(gamemode, 0), getclientmap());
- addstr(buf, text);
+ addstr(t, e, text);
}
if(multiplayer(NULL))
{
@@ -474,15 +475,15 @@ const char *asciiscores(bool destjpg)
string sdesc;
filtertext(sdesc, s->sdesc, FTXT__SERVDESC | FTXT_NOCOLOR);
formatstring(text)(", %s:%d %s", s->name, s->port, sdesc);
- addstr(buf, text);
+ addstr(t, e, text);
}
}
if(destjpg)
- addstr(buf, "\n");
+ addstr(t, e, "\n");
else
{
formatstring(text)("\n%sfrags deaths cn%s name\n", m_flags ? "flags " : "", m_teammode ? " team" : "");
- addstr(buf, text);
+ addstr(t, e, text);
}
loopv(scores)
{
@@ -495,7 +496,7 @@ const char *asciiscores(bool destjpg)
else
formatstring(text)("%s %4d %4d %2d%s %s%s\n", m_flags ? flags : "", d->frags, d->deaths, d->clientnum,
m_teammode ? team : "", d->name, d->clientrole==CR_ADMIN ? " (admin)" : d==player1 ? " (you)" : "");
- addstr(buf, text);
+ addstr(t, e, text);
}
discscores.sort(discscorecmp);
loopv(discscores)
@@ -508,15 +509,15 @@ const char *asciiscores(bool destjpg)
formatstring(text)("%s(disconnected)%s (%s%d/%d)\n", d.name, m_teammode ? team : "", m_flags ? flags : "", d.frags, d.deaths);
else
formatstring(text)("%s %4d %4d --%s %s(disconnected)\n", m_flags ? flags : "", d.frags, d.deaths, m_teammode ? team : "", d.name);
- addstr(buf, text);
+ addstr(t, e, text);
}
if(destjpg)
{
extern int minutesremaining;
formatstring(text)("(%sfrags/deaths), %d minute%s remaining\n", m_flags ? "flags/" : "", minutesremaining, minutesremaining == 1 ? "" : "s");
- addstr(buf, text);
+ addstr(t, e, text);
}
- return buf;
+ return buf + 8;
}
void consolescores()