Quake II RTX doxygen  1.0 dev
ascii.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "client.h"
20 
21 /*
22 ===============================================================================
23 
24 STAT PROGRAMS TO TEXT
25 
26 ===============================================================================
27 */
28 
29 #define TH_WIDTH 80
30 #define TH_HEIGHT 40
31 
32 static void TH_DrawString(char *dst, int x, int y, char *src, size_t len)
33 {
34  int c;
35 
36  if (x + len > TH_WIDTH) {
37  len = TH_WIDTH - x;
38  }
39 
40  dst += y * (TH_WIDTH + 1) + x;
41  while (len--) {
42  c = *src++;
43  c &= 127;
44  switch (c) {
45  case 13: c = '>'; break;
46  case 16: c = '['; break;
47  case 17: c = ']'; break;
48  case 29: c = '<'; break;
49  case 30: c = '='; break;
50  case 31: c = '>'; break;
51  default:
52  if (c < 32) {
53  c = 32;
54  }
55  break;
56  }
57  *dst++ = c;
58  }
59 }
60 
61 static void TH_DrawCenterString(char *dst, int x, int y, char *src, size_t len)
62 {
63  x -= len / 2;
64  if (x < 0) {
65  src -= x;
66  x = 0;
67  }
68 
69  TH_DrawString(dst, x, y, src, len);
70 }
71 
72 static void TH_DrawNumber(char *dst, int x, int y, int width, int value)
73 {
74  char num[16];
75  int l;
76 
77  if (width < 1)
78  return;
79 
80  // draw number string
81  if (width > 5)
82  width = 5;
83 
84  l = Q_scnprintf(num, sizeof(num), "%d", value);
85  if (l > width)
86  l = width;
87  x += width - l;
88 
89  TH_DrawString(dst, x, y, num, l);
90 }
91 
92 static void TH_DrawLayoutString(char *dst, const char *s)
93 {
94  char buffer[MAX_QPATH];
95  int x, y;
96  int value;
97  char *token;
98  size_t len;
99  int width, index;
100  clientinfo_t *ci;
101 
102  if (!s[0])
103  return;
104 
105  x = 0;
106  y = 0;
107 
108  while (s) {
109  token = COM_Parse(&s);
110  if (token[2] == 0) {
111  if (token[0] == 'x') {
112  if (token[1] == 'l') {
113  token = COM_Parse(&s);
114  x = atoi(token) / 8;
115  continue;
116  }
117 
118  if (token[1] == 'r') {
119  token = COM_Parse(&s);
120  x = TH_WIDTH + atoi(token) / 8;
121  continue;
122  }
123 
124  if (token[1] == 'v') {
125  token = COM_Parse(&s);
126  x = TH_WIDTH / 2 - 20 + atoi(token) / 8;
127  continue;
128  }
129  }
130 
131  if (token[0] == 'y') {
132  if (token[1] == 't') {
133  token = COM_Parse(&s);
134  y = atoi(token) / 8;
135  continue;
136  }
137 
138  if (token[1] == 'b') {
139  token = COM_Parse(&s);
140  y = TH_HEIGHT + atoi(token) / 8;
141  continue;
142  }
143 
144  if (token[1] == 'v') {
145  token = COM_Parse(&s);
146  y = TH_HEIGHT / 2 - 15 + atoi(token) / 8;
147  continue;
148  }
149  }
150  }
151 
152  if (!strcmp(token, "pic")) {
153  // draw a pic from a stat number
154  COM_Parse(&s);
155  continue;
156  }
157 
158  if (!strcmp(token, "client")) {
159  // draw a deathmatch client block
160  int score, ping, time;
161 
162  token = COM_Parse(&s);
163  x = TH_WIDTH / 2 - 20 + atoi(token) / 8;
164  token = COM_Parse(&s);
165  y = TH_HEIGHT / 2 - 15 + atoi(token) / 8;
166 
167  token = COM_Parse(&s);
168  value = atoi(token);
169  if (value < 0 || value >= MAX_CLIENTS) {
170  Com_Error(ERR_DROP, "%s: invalid client index", __func__);
171  }
172  ci = &cl.clientinfo[value];
173 
174  token = COM_Parse(&s);
175  score = atoi(token);
176 
177  token = COM_Parse(&s);
178  ping = atoi(token);
179 
180  token = COM_Parse(&s);
181  time = atoi(token);
182 
183  len = strlen(ci->name);
184  TH_DrawString(dst, x + 4, y, ci->name, len);
185  len = Q_scnprintf(buffer, sizeof(buffer), "Score: %i", score);
186  TH_DrawString(dst, x + 4, y + 1, buffer, len);
187  len = Q_scnprintf(buffer, sizeof(buffer), "Ping: %i", ping);
188  TH_DrawString(dst, x + 4, y + 2, buffer, len);
189  len = Q_scnprintf(buffer, sizeof(buffer), "Time: %i", time);
190  TH_DrawString(dst, x + 4, y + 3, buffer, len);
191  continue;
192  }
193 
194  if (!strcmp(token, "ctf")) {
195  // draw a ctf client block
196  int score, ping;
197 
198  token = COM_Parse(&s);
199  x = TH_WIDTH / 2 - 20 + atoi(token) / 8;
200  token = COM_Parse(&s);
201  y = TH_HEIGHT / 2 - 15 + atoi(token) / 8;
202 
203  token = COM_Parse(&s);
204  value = atoi(token);
205  if (value < 0 || value >= MAX_CLIENTS) {
206  Com_Error(ERR_DROP, "%s: invalid client index", __func__);
207  }
208  ci = &cl.clientinfo[value];
209 
210  token = COM_Parse(&s);
211  score = atoi(token);
212 
213  token = COM_Parse(&s);
214  ping = atoi(token);
215  if (ping > 999)
216  ping = 999;
217 
218  len = Q_scnprintf(buffer, sizeof(buffer), "%3d %3d %-12.12s",
219  score, ping, ci->name);
220  TH_DrawString(dst, x, y, buffer, len);
221  continue;
222  }
223 
224  if (!strcmp(token, "picn")) {
225  // draw a pic from a name
226  COM_Parse(&s);
227  continue;
228  }
229 
230  if (!strcmp(token, "num")) {
231  // draw a number
232  token = COM_Parse(&s);
233  width = atoi(token);
234  token = COM_Parse(&s);
235  value = atoi(token);
236  if (value < 0 || value >= MAX_STATS) {
237  Com_Error(ERR_DROP, "%s: invalid stat index", __func__);
238  }
239  value = cl.frame.ps.stats[value];
240  TH_DrawNumber(dst, x, y, width, value);
241  continue;
242  }
243 
244  if (!strcmp(token, "stat_string")) {
245  token = COM_Parse(&s);
246  index = atoi(token);
247  if (index < 0 || index >= MAX_STATS) {
248  Com_Error(ERR_DROP, "%s: invalid string index", __func__);
249  }
250  index = cl.frame.ps.stats[index];
251  if (index < 0 || index >= MAX_CONFIGSTRINGS) {
252  Com_Error(ERR_DROP, "%s: invalid string index", __func__);
253  }
254  len = strlen(cl.configstrings[index]);
255  TH_DrawString(dst, x, y, cl.configstrings[index], len);
256  continue;
257  }
258 
259  if (!strncmp(token, "cstring", 7)) {
260  token = COM_Parse(&s);
261  len = strlen(token);
262  TH_DrawCenterString(dst, x + 40 / 2, y, token, len);
263  continue;
264  }
265 
266  if (!strncmp(token, "string", 6)) {
267  token = COM_Parse(&s);
268  len = strlen(token);
269  TH_DrawString(dst, x, y, token, len);
270  continue;
271  }
272 
273  if (!strcmp(token, "if")) {
274  token = COM_Parse(&s);
275  value = atoi(token);
276  if (value < 0 || value >= MAX_STATS) {
277  Com_Error(ERR_DROP, "%s: invalid stat index", __func__);
278  }
279  value = cl.frame.ps.stats[value];
280  if (!value) { // skip to endif
281  while (strcmp(token, "endif")) {
282  token = COM_Parse(&s);
283  if (!s) {
284  break;
285  }
286  }
287  }
288  continue;
289  }
290  }
291 }
292 
293 static void SCR_ScoreShot_f(void)
294 {
295  char buffer[(TH_WIDTH + 1) * TH_HEIGHT];
296  char path[MAX_OSPATH];
297  qhandle_t f;
298  int i;
299  qerror_t ret;
300 
301  if (cls.state != ca_active) {
302  Com_Printf("Must be in a level.\n");
303  return;
304  }
305 
306  if (Cmd_Argc() > 1) {
307  f = FS_EasyOpenFile(path, sizeof(path), FS_MODE_WRITE | FS_FLAG_TEXT,
308  "scoreshots/", Cmd_Argv(1), ".txt");
309  if (!f) {
310  return;
311  }
312  } else {
313  // find a file name to save it to
314  for (i = 0; i < 1000; i++) {
315  Q_snprintf(path, sizeof(path), "scoreshots/quake%03d.txt", i);
316  ret = FS_FOpenFile(path, &f, FS_MODE_WRITE | FS_FLAG_TEXT | FS_FLAG_EXCL);
317  if (f) {
318  break;
319  }
320  if (ret != Q_ERR_EXIST) {
321  Com_EPrintf("Couldn't exclusively open %s for writing: %s\n",
322  path, Q_ErrorString(ret));
323  return;
324  }
325  }
326 
327  if (i == 1000) {
328  Com_EPrintf("All scoreshot slots are full.\n");
329  return;
330  }
331  }
332 
333  memset(buffer, ' ', sizeof(buffer));
334  for (i = 0; i < TH_HEIGHT; i++) {
335  buffer[i * (TH_WIDTH + 1) + TH_WIDTH] = '\n';
336  }
337 
338  TH_DrawLayoutString(buffer, cl.configstrings[CS_STATUSBAR]);
339  TH_DrawLayoutString(buffer, cl.layout);
340 
341  FS_Write(buffer, sizeof(buffer), f);
342 
343  FS_FCloseFile(f);
344 
345  Com_Printf("Wrote %s.\n", path);
346 }
347 
348 static void SCR_ScoreDump_f(void)
349 {
350  char buffer[(TH_WIDTH + 1) * TH_HEIGHT];
351  int i;
352 
353  if (cls.state != ca_active) {
354  Com_Printf("Must be in a level.\n");
355  return;
356  }
357 
358  memset(buffer, ' ', sizeof(buffer));
359  for (i = 0; i < TH_HEIGHT - 1; i++) {
360  buffer[i * (TH_WIDTH + 1) + TH_WIDTH] = '\n';
361  }
362  buffer[i * (TH_WIDTH + 1) + TH_WIDTH] = 0;
363 
364  TH_DrawLayoutString(buffer, cl.configstrings[CS_STATUSBAR]);
365  TH_DrawLayoutString(buffer, cl.layout);
366 
367  Com_Printf("%s\n", buffer);
368 }
369 
370 void CL_InitAscii(void)
371 {
372  Cmd_AddCommand("aashot", SCR_ScoreShot_f);
373  Cmd_AddCommand("aadump", SCR_ScoreDump_f);
374 }
375 
client_state_s::frame
server_frame_t frame
Definition: client.h:212
client_state_s::configstrings
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]
Definition: client.h:289
FS_EasyOpenFile
qhandle_t FS_EasyOpenFile(char *buf, size_t size, unsigned mode, const char *dir, const char *name, const char *ext)
Definition: files.c:1846
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
Cmd_AddCommand
void Cmd_AddCommand(const char *name, xcommand_t function)
Definition: cmd.c:1562
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
ca_active
@ ca_active
Definition: client.h:340
client_static_s::state
connstate_t state
Definition: client.h:375
SCR_ScoreDump_f
static void SCR_ScoreDump_f(void)
Definition: ascii.c:348
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
CL_InitAscii
void CL_InitAscii(void)
Definition: ascii.c:370
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
TH_DrawLayoutString
static void TH_DrawLayoutString(char *dst, const char *s)
Definition: ascii.c:92
width
static int width
Definition: physical_sky.c:38
FS_FOpenFile
ssize_t FS_FOpenFile(const char *name, qhandle_t *f, unsigned mode)
Definition: files.c:1692
clientinfo_s::name
char name[MAX_QPATH]
Definition: client.h:113
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
client_state_s::layout
char layout[MAX_NET_STRING]
Definition: client.h:269
TH_HEIGHT
#define TH_HEIGHT
Definition: ascii.c:30
SCR_ScoreShot_f
static void SCR_ScoreShot_f(void)
Definition: ascii.c:293
client_state_s::clientinfo
clientinfo_t clientinfo[MAX_CLIENTS]
Definition: client.h:308
TH_DrawString
static void TH_DrawString(char *dst, int x, int y, char *src, size_t len)
Definition: ascii.c:32
cl
client_state_t cl
Definition: main.c:99
FS_Write
ssize_t FS_Write(const void *buf, size_t len, qhandle_t f)
Definition: files.c:1643
cls
client_static_t cls
Definition: main.c:98
c
statCounters_t c
Definition: main.c:30
TH_WIDTH
#define TH_WIDTH
Definition: ascii.c:29
server_frame_t::ps
player_state_t ps
Definition: client.h:137
client.h
COM_Parse
char * COM_Parse(const char **data_p)
Definition: shared.c:455
FS_FCloseFile
void FS_FCloseFile(qhandle_t f)
Definition: files.c:759
TH_DrawCenterString
static void TH_DrawCenterString(char *dst, int x, int y, char *src, size_t len)
Definition: ascii.c:61
Q_scnprintf
size_t Q_scnprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:867
clientinfo_s
Definition: client.h:112
TH_DrawNumber
static void TH_DrawNumber(char *dst, int x, int y, int width, int value)
Definition: ascii.c:72