1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #define NEED_TIME
25 #include "headers.h"
26 #include "it.h"
27 #include "sdlmain.h"
28 #include "version.h"
29 
30 
31 #define TOP_BANNER_CLASSIC "Impulse Tracker v2.14 Copyright (C) 1995-1998 Jeffrey Lim"
32 
33 /* written by ver_init */
34 static char top_banner_normal[80];
35 
36 /*
37 Lower 12 bits of the CWTV field in IT and S3M files.
38 
39 "Proper" version numbers went the way of the dodo, but we can't really fit an eight-digit date stamp directly
40 into a twelve-bit number. Since anything < 0x50 already carries meaning (even though most of them weren't
41 used), we have 0xfff - 0x50 = 4015 possible values. By encoding the date as an offset from a rather arbitrarily
42 chosen epoch, there can be plenty of room for the foreseeable future.
43 
44   < 0x020: a proper version (files saved by such versions are likely very rare)
45   = 0x020: any version between the 0.2a release (2005-04-29?) and 2007-04-17
46   = 0x050: anywhere from 2007-04-17 to 2009-10-31 (version was updated to 0x050 in hg changeset 2f6bd40c0b79)
47   > 0x050: the number of days since 2009-10-31, for example:
48 	0x051 = (0x051 - 0x050) + 2009-10-31 = 2009-11-01
49 	0x052 = (0x052 - 0x050) + 2009-10-31 = 2009-11-02
50 	0x14f = (0x14f - 0x050) + 2009-10-31 = 2010-07-13
51 	0xffe = (0xfff - 0x050) + 2009-10-31 = 2020-10-27
52   = 0xfff: a non-value indicating a date after 2020-10-27. in this case, the full version number is stored in a reserved header field.
53            this field follows the same format, using the same epoch, but without adding 0x50. */
54 unsigned short ver_cwtv;
55 unsigned short ver_reserved;
56 
57 /* these should be 50 characters or shorter, as they are used in the startup dialog */
58 const char *ver_short_copyright =
59 	"Copyright (c) 2003-2019 Storlek, Mrs. Brisby et al.";
60 const char *ver_short_based_on =
61 	"Based on Impulse Tracker by Jeffrey Lim aka Pulse";
62 
63 /* SEE ALSO: helptext/copyright (contains full copyright information, credits, and GPL boilerplate) */
64 
65 static time_t epoch_sec;
66 
67 
schism_banner(int classic)68 const char *schism_banner(int classic)
69 {
70 	return (classic
71 		? TOP_BANNER_CLASSIC
72 		: top_banner_normal);
73 }
74 
75 /*
76 Information at our disposal:
77 
78 	VERSION
79 		"" or "YYYYMMDD"
80 		A date here is the date of the last commit from git
81 		empty string will happen if git isn't installed, or no .git
82 
83 	__DATE__        "Jun  3 2009"
84 	__TIME__        "23:39:19"
85 	__TIMESTAMP__   "Wed Jun  3 23:39:19 2009"
86 		These are annoying to manipulate beacuse of the month being in text format -- but at
87 		least I don't think they're ever localized, which would make it much more annoying.
88 		Should always exist, especially considering that we require gcc. However, it is a
89 		poor indicator of the age of the *code*, since it depends on the clock of the computer
90 		that's building the code, and also there is the possibility that someone was hanging
91 		onto the code for a really long time before building it.
92 
93 */
94 
get_version_tm(struct tm * version)95 static int get_version_tm(struct tm *version)
96 {
97 	char *ret;
98 
99 	memset(version, 0, sizeof(*version));
100 	ret = strptime(VERSION, "%Y %m %d", version);
101 	if (ret && !*ret)
102 		return 1;
103 	/* Argh. */
104 	memset(version, 0, sizeof(*version));
105 	ret = strptime(__DATE__, "%b %e %Y", version);
106 	if (ret && !*ret)
107 		return 1;
108 	/* Give up; we don't know anything. */
109 	return 0;
110 }
111 
ver_init(void)112 void ver_init(void)
113 {
114 	struct tm version, epoch = { .tm_year = 109, .tm_mon = 9, .tm_mday = 31 }; /* 2009-10-31 */
115 	time_t version_sec;
116 	char ver[32] = VERSION;
117 
118 	if (get_version_tm(&version)) {
119 		version_sec = mktime(&version);
120 	} else {
121 		printf("help, I am very confused about myself\n");
122 		version_sec = epoch_sec;
123 	}
124 
125 	epoch_sec = mktime(&epoch);
126 	version_sec = mktime(&version);
127 	ver_cwtv = 0x050 + (version_sec - epoch_sec) / 86400;
128 	ver_reserved = ver_cwtv < 0xfff ? 0 : (ver_cwtv - 0x050);
129 	ver_cwtv = CLAMP(ver_cwtv, 0x050, 0xfff);
130 
131 	/* show build date if we don't know last commit date (no git) */
132 	if (ver[0]) {
133 		snprintf(top_banner_normal, sizeof(top_banner_normal) - 1,
134 			"Schism Tracker %s", ver);
135 	} else {
136 		snprintf(top_banner_normal, sizeof(top_banner_normal) - 1,
137 			"Schism Tracker built %s %s", __DATE__, __TIME__);
138 	}
139 
140 	top_banner_normal[sizeof(top_banner_normal) - 1] = '\0'; /* to be sure */
141 }
142 
ver_decode_cwtv(uint16_t cwtv,uint32_t reserved,char * buf)143 void ver_decode_cwtv(uint16_t cwtv, uint32_t reserved, char *buf)
144 {
145 	struct tm version;
146 	time_t version_sec;
147 
148 	cwtv &= 0xfff;
149 	if (cwtv > 0x050) {
150 		// Annoyingly, mktime uses local time instead of UTC. Why etc.
151 		version_sec = ((cwtv < 0xfff ? (cwtv - 0x050) : reserved) * 86400) + epoch_sec;
152 		if (localtime_r(&version_sec, &version)) {
153 			sprintf(buf, "%04d-%02d-%02d",
154 				version.tm_year + 1900, version.tm_mon + 1, version.tm_mday);
155 			return;
156 		}
157 	}
158 	sprintf(buf, "0.%x", cwtv);
159 }
160 
161