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