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()