1 /*
2 psftools: Manipulate console fonts in the .PSF format
3 Copyright (C) 2005, 2008 John Elliott
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /* Merge three PSF files into a character ROM */
21
22 #include "cnvmulti.h"
23 #include "psflib.h"
24
25
26 static char helpbuf[2048];
27 static char msgbuf[1025];
28 static int compaq;
29 static unsigned char rom[8192];
30
31 /* Program name */
32 char *cnv_progname = "PSFS2MDA";
33
34 /* ddash = 1 if option started with a double-dash; else 0 */
35 /* Return NULL if OK, else error string */
cnv_set_option(int ddash,char * variable,char * value)36 char *cnv_set_option(int ddash, char *variable, char *value)
37 {
38 if (!stricmp(variable, "compaq"))
39 {
40 compaq = 1;
41 return NULL;
42 }
43 if (!strcmp(variable, "comment"))
44 {
45 strncpy(msgbuf, value, sizeof(msgbuf)-1);
46 msgbuf[sizeof(msgbuf)-1] = 0;
47 return NULL;
48 }
49 if (strlen(variable) > 2000) variable[2000] = 0;
50 sprintf(helpbuf, "Unknown option: %s\n", variable);
51 return helpbuf;
52 }
53
54
55 /* Return help string */
cnv_help(void)56 char *cnv_help(void)
57 {
58 sprintf(helpbuf, "Builds a CGA/MDA/Compaq CGA character ROM from three "
59 "fonts\n\n"
60 "Syntax: %s source14.psf source8.psf { source8a.psf } "
61 "target.rom\n\n", cnv_progname);
62 strcat(helpbuf, "Options are: --compaq Output in Compaq CGA format\n");
63 strcat(helpbuf, " --comment=<comment>\n");
64 return helpbuf;
65 }
66
transform(PSF_FILE * psf,int y0,int dest,int step,int firstc)67 void transform(PSF_FILE *psf, int y0, int dest, int step, int firstc)
68 {
69 int n, m, y;
70 psf_dword offset;
71 psf_dword bytes_line = (psf->psf_width + 7) / 8;
72
73 for (n = 0; n < 256; n++)
74 {
75 /* Point at character glyph */
76 offset = (firstc % psf->psf_length) * psf->psf_charlen;
77 offset += bytes_line * y0;
78 y = y0;
79 /* Copy the left-hand 8x8 chunk */
80 for (m = 0; m < 8; m++)
81 {
82 if (y >= psf->psf_height)
83 rom[dest + m] = 0;
84 else rom[dest + m] = psf->psf_data[offset];
85 offset += bytes_line;
86 y++;
87 }
88 dest += step;
89 ++firstc;
90 }
91 }
92
93 /* Do the conversion */
cnv_multi(int nfiles,char ** infiles,FILE * outfile)94 char *cnv_multi(int nfiles, char **infiles, FILE *outfile)
95 {
96 int rv, nf, nc;
97 PSF_FILE psf[3];
98 FILE *fp;
99
100 if (nfiles != 3 && nfiles != 2)
101 return "Syntax error: Two or three input files must be supplied";
102
103 for (nf = 0; nf < nfiles; nf++)
104 {
105 if (!strcmp(infiles[nf], "-")) fp = stdin;
106 else fp = fopen(infiles[nf], "rb");
107
108 if (!fp)
109 {
110 perror(infiles[nf]);
111 return "Cannot open font file.";
112 }
113
114 psf_file_new(&psf[nf]);
115 rv = psf_file_read(&psf[nf], fp);
116 if (fp != stdin) fclose(fp);
117 if (rv != PSF_E_OK) return psf_error_string(rv);
118 /* PSF loaded. */
119 }
120 if (psf[0].psf_height != 14)
121 fprintf(stderr, "Warning: %s is not 14 pixels high\n", infiles[0]);
122 if (psf[1].psf_height != 8)
123 fprintf(stderr, "Warning: %s is not 8 pixels high\n", infiles[1]);
124 if (nfiles == 3 && psf[2].psf_height != 8)
125 fprintf(stderr, "Warning: %s is not 8 pixels high\n", infiles[2]);
126 /* Now generate the ROM */
127 memset(rom, 0, sizeof(rom));
128 if (compaq)
129 {
130 transform(&psf[0], 8, 0x0000, 16, 0);
131 transform(&psf[0], 0, 0x0008, 16, 0);
132 transform(&psf[1], 0, 0x1000, 16, 0);
133 if (nfiles == 2)
134 transform(&psf[1], 0, 0x1008, 16, 256);
135 else transform(&psf[2], 0, 0x1008, 16, 0);
136 /* Comment, if any */
137 for (nc = 0; nc < 1024; nc++)
138 {
139 if (msgbuf[nc] == 0) break;
140 rom[nc * 16 + 6] = msgbuf[nc];
141 }
142 }
143 else
144 {
145 transform(&psf[0], 0, 0x0000, 8, 0);
146 transform(&psf[0], 8, 0x0800, 8, 0);
147 if (nfiles == 2)
148 transform(&psf[1], 0, 0x1000, 8, 256);
149 else transform(&psf[2], 0, 0x1000, 8, 0);
150 transform(&psf[1], 0, 0x1800, 8, 0);
151 }
152 if (fwrite(rom, 1, sizeof(rom), outfile) < (int)sizeof(rom))
153 {
154 return "Error writing output file";
155 }
156 for (nf = 0; nf < nfiles; nf++)
157 {
158 psf_file_delete(&psf[nf]);
159 }
160 return NULL;
161 }
162
163