1 /*
2 psftools: Manipulate console fonts in the .PSF format
3 Copyright (C) 2003 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 #include "cnvshell.h"
20 #include "psflib.h"
21
22 /* Convert an MDA character ROM to a .PSF font.
23 *
24 * We assume the MDA ROM format, with 256 characters, each one 8x14. The
25 * ninth column is synthesized.
26 */
27
28 static char helpbuf[2048];
29 static char mdabuf[8192];
30 static PSF_FILE psf;
31 static PSF_MAPPING *codepage = NULL;
32 static int compaq = 0;
33
34 /* Program name */
35 char *cnv_progname = "MDA2PSF";
36
37 /* ddash = 1 if option started with a double-dash; else 0 */
38 /* Return NULL if OK, else error string */
cnv_set_option(int ddash,char * variable,char * value)39 char *cnv_set_option(int ddash, char *variable, char *value)
40 {
41 if (!stricmp(variable, "codepage"))
42 {
43 codepage = psf_find_mapping(value);
44 if (codepage == NULL) return "Code page name not recognised.";
45 return NULL;
46 }
47 if (!stricmp(variable, "compaq"))
48 {
49 compaq = 1;
50 return NULL;
51 }
52 if (strlen(variable) > 2000) variable[2000] = 0;
53 sprintf(helpbuf, "Unknown option: %s\n", variable);
54 return helpbuf;
55 }
56
57
58 /* Return help string */
cnv_help(void)59 char *cnv_help(void)
60 {
61 sprintf(helpbuf, "Syntax: %s mda_rom psffile { options }\n\n", cnv_progname);
62 strcat (helpbuf, "Options:\n\n"
63 "--codepage=x: Create a Unicode directory from the "
64 "specified code page\n"
65 "--compaq: Input file is in Compaq CGA format\n\n"
66 "If --compaq is not present, input file must be in the IBM"
67 " MDA/CGA character\nROM format.\n");
68
69 return helpbuf;
70 }
71
72
cnv_execute(FILE * infile,FILE * outfile)73 char *cnv_execute(FILE *infile, FILE *outfile)
74 {
75 int rv, n, m;
76 long pos;
77
78 if (infile == stdin) pos = -1;
79 else pos = ftell(infile);
80
81 /* Character size is fixed: 8x14. In an IBM ROM, the font is stored as two
82 * lots of 8x8 characters -- the first 256 give the top halves of the
83 * characters, and the second 256 give the bottom halves. In the Compaq ROM,
84 * odd-numbered characters are the top halves and even-numbered characters are
85 * the bottom halves. */
86
87 psf_file_new(&psf);
88 rv = psf_file_create(&psf, 9, 14, 256, 0);
89 if (!rv)
90 {
91 if (fread(mdabuf, 1, 4096, infile) < 4096)
92 {
93 psf_file_delete(&psf);
94 return "Could not read the input file.";
95 }
96 for (n= 0; n < 256; n++)
97 {
98 if (compaq) /* Compaq */
99 {
100 for (m = 0; m < 8; m ++) /* Top halves */
101 {
102 psf.psf_data[28*n+2*m] = mdabuf[16*n+8+m];
103 }
104 for (m = 0; m < 6; m ++) /* Bottom halves */
105 {
106 psf.psf_data[28*n+2*m+16] = mdabuf[16*n+m];
107 }
108
109 }
110 else /* IBM */
111 {
112 for (m = 0; m < 8; m++) /* Top halves */
113 {
114 psf.psf_data[28*n + 2*m ] = mdabuf[8*n+m];
115 }
116 for (m = 0; m < 6; m++) /* Bottom halves */
117 {
118 psf.psf_data[28*n + 2*m + 16] = mdabuf[8*n+m+2048];
119 }
120 }
121 /* Characters 192-224 duplicate the 8th column to give the 9th column. */
122 for (m = 0; m < 14; m++)
123 {
124 psf.psf_data[28*n + 2*m + 1] = 0;
125 if (n >= 192 && n < 224)
126 {
127 if (psf.psf_data[28*n + 2*m] & 1)
128 psf.psf_data[28*n+2*m+1] = 0x80;
129 }
130 }
131 }
132 if (codepage)
133 {
134 psf_file_create_unicode(&psf);
135 for (n = 0; n < 256; n++)
136 psf_unicode_addmap(&psf, n, codepage, n);
137 }
138 rv = psf_file_write(&psf, outfile);
139 }
140 psf_file_delete(&psf);
141 if (rv) return psf_error_string(rv);
142 return NULL;
143 }
144
145