#include #include #include #include #include typedef unsigned char byte; static byte fontbuf[4096]; #define VID_A_MDA 0 #define VID_A_CGA 1 #define VID_A_EGA 2 #define VID_A_VGA 3 byte vid_type() { union REGS inregs,outregs; /* Video adaptor type determination: Set AX=1200, BL=32 and call INT 10. */ inregs.x.ax=0x1200; inregs.h.bl=0x32; int86(0x10,&inregs,&outregs); /* If AL returns 12, you have a VGA. If not, set AH=12, BL=10 and call INT 10 again. */ if (outregs.h.al==0x12) return VID_A_VGA; inregs.h.ah=0x12; inregs.h.bl=0x10; int86(0x10,&inregs,&outregs); /* If BL returns 0,1,2,3, you have an EGA with 64,128,192,256K memory. If not, set AH=0F and call INT 10 a third time. */ if (outregs.h.bl < 4) return VID_A_EGA; inregs.h.ah=0x0F; int86(0x10,&inregs,&outregs); /* If AL is 7, you have an MDA (original monochrome adapter) or Hercules; if not, you have a CGA. */ if (outregs.h.al == 7) return VID_A_MDA; return VID_A_CGA; } static byte old_mode; #define save_mode() old_mode = get_mode() byte get_mode() { union REGS inregs,outregs; inregs.h.ah=0x0f; int86(0x10,&inregs,&outregs); return outregs.h.al; } void set_mode(byte m) { union REGS inregs,outregs; inregs.h.ah=0x00; inregs.h.al=m; int86(0x10,&inregs,&outregs); } #define restore_mode() set_mode(old_mode) int v_set_mode(byte m) { byte m1; set_mode(m); if ((m1 = get_mode()) == m) return 1; restore_mode(); fprintf(stderr, "Asked for video mode %d but got %d\n", m, m1); fprintf(stderr, "Press RETURN...\n"); getch(); return 0; } void draw_char(int ch) { union REGS inregs, outregs; inregs.h.ah = 0x09; inregs.h.al = ch; inregs.h.bh = 0; inregs.h.bl = 0x0F; inregs.x.cx = 1; int86(0x10, &inregs, &outregs); } void emit_psf(char *f, int height) { char fname[20]; FILE *fp; sprintf(fname, "%s%02d.psf", f, height); fp = fopen(fname, "wb"); if (!fp) { restore_mode(); perror(fname); exit(1); } fputc(0x36, fp); fputc(0x04, fp); fputc(0x00, fp); fputc(height, fp); fwrite(fontbuf, height, 256, fp); fclose(fp); } void save_font_16(char *filename) { int ch, n; byte far *screen = MK_FP(0xA000, 0); byte *target; if (!v_set_mode(0x11)) return; for (ch = 0; ch < 256; ch++) { draw_char(ch); target = fontbuf + 16 * ch; for (n = 0; n < 16; n++) { *target++ = screen[n * 80]; } } emit_psf(filename, 16); } void save_font_14(char *filename) { int ch, n; byte far *screen = MK_FP(0xA000, 0); byte *target; if (!v_set_mode(0x0F)) return; for (ch = 0; ch < 256; ch++) { draw_char(ch); target = fontbuf + 14 * ch; for (n = 0; n < 14; n++) { *target++ = screen[n * 80]; } } emit_psf(filename, 14); } void save_font_8(char *filename) { int ch, n; byte far *screen = MK_FP(0xB800, 0); byte *target; if (!v_set_mode(6)) return; for (ch = 0; ch < 256; ch++) { draw_char(ch); target = fontbuf + 8 * ch; for (n = 0; n < 4; n++) { *target++ = screen[n * 80]; *target++ = screen[n * 80 + 0x2000]; } } emit_psf(filename, 8); } int main(int argc, char **argv) { char fname[7]; if (argc > 1) { strncpy(fname, argv[1], 6); fname[6] = 0; } else strcpy(fname, "font"); save_mode(); switch(vid_type()) { case VID_A_VGA: save_font_16(fname); /* And fall through to CGA */ case VID_A_EGA: save_font_14(fname); /* And fall through to CGA */ case VID_A_CGA: save_font_8(fname); break; case VID_A_MDA: /* 1...5...10...15...20...25...30...35...40 */ fprintf(stderr, "This computer appears to have a Monochro" "me Display Adapter. The character\n" "patterns for this adapter are not visibl" "e to DOS programs.\n\n"); exit(1); } restore_mode(); return 0; }