openMSX
Printer.cc
Go to the documentation of this file.
1 #include "Printer.hh"
2 #include "PNG.hh"
3 #include "FileOperations.hh"
4 #include "IntegerSetting.hh"
5 #include "MSXMotherBoard.hh"
6 #include "CliComm.hh"
7 #include "MSXException.hh"
8 #include "Math.hh"
9 #include "MemBuffer.hh"
10 #include "serialize.hh"
11 #include "memory.hh"
12 #include "vla.hh"
13 #include <algorithm>
14 #include <vector>
15 #include <cassert>
16 #include <cmath>
17 #include <cstring>
18 
19 using std::max;
20 using std::min;
21 using std::string;
22 
23 namespace openmsx {
24 
25 class Paper
26 {
27 public:
28  Paper(unsigned x, unsigned y, double dotSizeX, double dotSizeY);
29  ~Paper();
30 
31  std::string save() const;
32  void setDotSize(double sizeX, double sizeY);
33  void plot(double x, double y);
34 
35 private:
36  byte& dot(unsigned x, unsigned y);
37 
38  MemBuffer<byte> buf;
39  std::vector<int> table;
40 
41  double radiusX;
42  double radiusY;
43  int radius16;
44 
45  unsigned sizeX;
46  unsigned sizeY;
47 };
48 
49 
51  : toPrint(0), prevStrobe(true)
52 {
53 }
54 
56 {
57 }
58 
60 {
61  return false; // false = low = ready
62 }
63 
64 void PrinterCore::setStrobe(bool strobe, EmuTime::param /*time*/)
65 {
66  if (!strobe && prevStrobe) {
67  // falling edge
68  write(toPrint);
69  }
70  prevStrobe = strobe;
71 }
72 
74 {
75  toPrint = data;
76 }
77 
78 void PrinterCore::plugHelper(Connector& /*connector*/, EmuTime::param /*time*/)
79 {
80  // nothing
81 }
82 
84 {
85  forceFormFeed();
86 }
87 
88 
89 /*
90 // class RawPrinter
91 
92 RawPrinter::RawPrinter()
93 {
94  Properties* properties = propGetGlobalProperties();
95  hFile = CreateFile(properties->ports.Lpt.portName, GENERIC_WRITE,
96  0, nullptr, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, nullptr);
97  if (hFile == INVALID_HANDLE_VALUE) {
98  throw MSXException();
99  }
100 }
101 
102 void RawPrinter::~RawPrinter()
103 {
104  CloseHandle(hFile);
105 }
106 
107 void RawPrinter::write(byte value)
108 {
109  unsigned dwWritten;
110  WriteFile(hFile, &value, 1, &dwWritten, nullptr);
111 }
112 
113 void RawPrinter::forceFormFeed()
114 {
115 }
116 */
117 
118 
119 // class ImagePrinter
120 
121 ImagePrinter::ImagePrinter(MSXMotherBoard& motherBoard_, bool graphicsHiLo_)
122  : motherBoard(motherBoard_)
123  , graphicsHiLo(graphicsHiLo_)
124 {
125  auto& info = motherBoard.getSharedStuff("print-resolution");
126  if (info.counter == 0) {
127  assert(!info.stuff);
128  info.stuff = new IntegerSetting(
129  motherBoard.getCommandController(), "print-resolution",
130  "resolution of the output image of emulated dot matrix printer in DPI",
131  300, 72, 1200);
132  }
133  ++info.counter;
134  dpiSetting = reinterpret_cast<IntegerSetting*>(info.stuff);
135 
136  letterQuality = false;
137  bold = false;
138  proportional = false;
139  italic = false;
140  superscript = false;
141  subscript = false;
142  doubleWidth = false;
143  underline = false;
144  doubleStrike = false;
145  escSequence = false;
146  alternateChar = false;
147  detectPaperOut = false;
148  japanese = false;
149  normalAfterLine = false;
150  ninePinGraphics = false;
151  leftToRight = false;
152  elite = false;
153  compressed = false;
154  noHighEscapeCodes = false;
155  eightBit = 0;
156  perforationSkip = 0;
158  sizeEscPos = 0;
160  ramLoadOffset = 0;
161  ramLoadEnd = 0;
163 
164  printAreaTop = -1.0;
165  printAreaBottom = 0.0;
166 }
167 
169 {
171 
172  auto& info = motherBoard.getSharedStuff("print-resolution");
173  assert(info.counter);
174  assert(dpiSetting);
175  assert(dpiSetting == info.stuff);
176  --info.counter;
177  if (info.counter == 0) {
178  delete dpiSetting;
179  info.stuff = nullptr;
180  }
181 }
182 
184 {
185  if (ramLoadOffset < ramLoadEnd) {
187  } else if (sizeRemainingDataBytes) {
188  if (eightBit == 0) {
189  data &= 0x80;
190  } else if (eightBit == 1) {
191  data |= 0x80;
192  }
193  printGraphicByte(data);
195  } else if (escSequence) {
196  escSequence = false;
197 
198  memset(&(abEscSeq), 0, sizeof(abEscSeq));
199  *(abEscSeq) = data;
200  sizeEscPos = 1;
201 
203 
204  if (!remainingCommandBytes) {
206  }
207  } else if (remainingCommandBytes) {
208  abEscSeq[sizeEscPos++] = data;
209 
210  if (!--remainingCommandBytes) {
212  }
213  } else {
214  processCharacter(data);
215  }
216 }
217 
219 {
221 }
222 
224 {
225  resetSettings();
226 
228  hpos = leftBorder;
229  vpos = pageTop;
230 }
231 
232 void ImagePrinter::plot9Dots(double x, double y, unsigned pattern)
233 {
234  for (int i = 0; i < 9; ++i) {
235  if (pattern & (1 << i)) {
236  paper->plot(x, y + (8 - i) * pixelSizeY);
237  }
238  }
239 }
240 
242 {
243  ensurePrintPage();
244 
245  double destY = vpos * pixelSizeY;
246  double destHeight = pixelSizeY * 9.0;
247 
248  // Print Data to high 8 bits
249  unsigned charBits = (graphicsHiLo ? Math::reverseByte(data) : data) << 1;
250 
251  printAreaTop = min(printAreaTop, destY);
252  printAreaBottom = max(printAreaBottom, destY + destHeight);
253 
254  // Print bit-mask
255  plot9Dots(hpos * pixelSizeX, destY, charBits);
256 
257  // Move print-position...
259 }
260 
262 {
263  hpos += offset;
264  if (unsigned(hpos) > rightBorder) {
265  hpos = leftBorder;
266  vpos += lineFeed;
267  if (vpos >= pageHeight) {
270  }
271  }
272 }
273 
275 {
276  if (!paper) {
277  // A4 paper format (210mm x 297mm) at 300dpi
278  // TODO make this configurable
279  int dpi = dpiSetting->getInt();
280  unsigned paperSizeX = unsigned((210 / 25.4) * dpi);
281  unsigned paperSizeY = unsigned((297 / 25.4) * dpi);
282 
283  unsigned dotsX, dotsY;
284  getNumberOfDots(dotsX, dotsY);
285  pixelSizeX = double(paperSizeX) / dotsX;
286  pixelSizeY = double(paperSizeY) / dotsY;
287 
288  paper = make_unique<Paper>(paperSizeX, paperSizeY,
290  }
291 }
292 
294 {
295  if (paper) {
297  try {
298  string filename = paper->save();
299  motherBoard.getMSXCliComm().printInfo(
300  "Printed to " + filename);
301  } catch (MSXException& e) {
302  motherBoard.getMSXCliComm().printWarning(
303  "Failed to print: " + e.getMessage());
304  }
305  printAreaTop = -1.0;
306  printAreaBottom = 0.0;
307  }
308  paper.reset();
309  }
310  hpos = leftBorder;
311  vpos = pageTop;
312 }
313 
314 static unsigned compress9(unsigned a)
315 {
316  unsigned result = 0;
317  for (unsigned i = 0; i < 9; ++i) {
318  if (a & (1 << i)) {
319  result |= 1 << (i / 2);
320  }
321  }
322  return result;
323 }
325 {
326  ensurePrintPage();
327 
328  double iYPos = 0;
329  byte* charBitmap = (fontInfo.useRam ? fontInfo.ram : fontInfo.rom)
330  + fontInfo.charWidth * data;
331  byte attribute = charBitmap[0];
332  unsigned start = (attribute >> 4) & 0x07;
333  unsigned end = attribute & 0x0f;
334  unsigned topBits = attribute >> 7;
335  bool script = superscript || subscript;
336 
337  if (!proportional) {
338  start = 0; // Fixed width font
339  end = fontInfo.charWidth - 1;
340  }
341  if (subscript) {
342  iYPos /= 2.0;
343  iYPos += pixelSizeY * 4.5;
344  }
345  if (script) {
346  iYPos -= pixelSizeY * 4.5;
347  }
348 
349  double hPos = hpos;
350  double headRelative = (doubleWidth ? 2 : 1) * fontInfo.pixelDelta / fontDensity;
351 
352  double destY = vpos * pixelSizeY + iYPos;
353  double destHeight = pixelSizeY * 9.0;
354  double dblStrikeOffset = doubleStrike ? (pixelSizeY / 2.5) : 0.0;
355  printAreaTop = min(printAreaTop, destY);
356  printAreaBottom = max(printAreaBottom, destY + destHeight + dblStrikeOffset);
357 
358  for (unsigned i = start; i < end; ++i) {
359  unsigned charBits = unsigned(charBitmap[i + 1]) << topBits;
360 
361  if (underline) {
362  charBits |= 2;
363  }
364  if (script) {
365  charBits = compress9(charBits);
366  }
367 
368  for (int d = 0; d <= (doubleWidth?1:0); d++) {
369  for (int b = 0; b <= (bold?1:0); ++b) {
370  for (int y = 0; y <= (doubleStrike?1:0); ++y) {
371  double destX = (hPos + (d + b / 2.0) / fontDensity) * pixelSizeX;
372  plot9Dots(destX, destY + y * dblStrikeOffset, charBits);
373  }
374  }
375  }
376  hPos += headRelative;
377  }
378  seekPrinterHeadRelative((1 + end - start) * headRelative);
379 }
380 
381 
382 // class ImagePrinterMSX
383 
384 // MSX-Font taken from NMS8250 BIOS ROM
385 static const byte MSXFontRaw[256 * 8] = {
386  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
387  0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C, // 1
388  0x3C, 0x7E, 0xDB, 0xFF, 0xFF, 0xDB, 0x66, 0x3C, // 2
389  0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, // 3
390  0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, // 4
391  0x10, 0x38, 0x54, 0xFE, 0x54, 0x10, 0x38, 0x00, // 5
392  0x10, 0x38, 0x7C, 0xFE, 0xFE, 0x10, 0x38, 0x00, // 6
393  0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, // 7
394  0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xFF, 0xFF, 0xFF, // 8
395  0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, // 9
396  0xC7, 0xBB, 0x7D, 0x7D, 0x7D, 0xBB, 0xC7, 0xFF, // 10
397  0x0F, 0x03, 0x05, 0x79, 0x88, 0x88, 0x88, 0x70, // 11
398  0x38, 0x44, 0x44, 0x44, 0x38, 0x10, 0x7C, 0x10, // 12
399  0x30, 0x28, 0x24, 0x24, 0x28, 0x20, 0xE0, 0xC0, // 13
400  0x3C, 0x24, 0x3C, 0x24, 0x24, 0xE4, 0xDC, 0x18, // 14
401  0x10, 0x54, 0x38, 0xEE, 0x38, 0x54, 0x10, 0x00, // 15
402  0x10, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x10, // 16
403  0x10, 0x10, 0x10, 0xFF, 0x00, 0x00, 0x00, 0x00, // 17
404  0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, // 18
405  0x10, 0x10, 0x10, 0xF0, 0x10, 0x10, 0x10, 0x10, // 19
406  0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, // 20
407  0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10, // 21
408  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 22
409  0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, // 23
410  0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, // 24
411  0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x10, 0x10, // 25
412  0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, // 26
413  0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, // 27
414  0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, // 28
415  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, // 29
416  0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, // 30
417  0x00, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x00, 0x00, // 31
418  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32
419  0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x00, // 33
420  0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // 34
421  0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00, // 35
422  0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00, // 36
423  0xC0, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x18, 0x00, // 37
424  0x40, 0xA0, 0x40, 0xA8, 0x90, 0x98, 0x60, 0x00, // 38
425  0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // 39
426  0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, // 40
427  0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, // 41
428  0x20, 0xA8, 0x70, 0x20, 0x70, 0xA8, 0x20, 0x00, // 42
429  0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00, // 43
430  0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, // 44
431  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, // 45
432  0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, // 46
433  0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, // 47
434  0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70, 0x00, // 48
435  0x20, 0x60, 0xA0, 0x20, 0x20, 0x20, 0xF8, 0x00, // 49
436  0x70, 0x88, 0x08, 0x10, 0x60, 0x80, 0xF8, 0x00, // 50
437  0x70, 0x88, 0x08, 0x30, 0x08, 0x88, 0x70, 0x00, // 51
438  0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10, 0x00, // 52
439  0xF8, 0x80, 0xE0, 0x10, 0x08, 0x10, 0xE0, 0x00, // 53
440  0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00, // 54
441  0xF8, 0x88, 0x10, 0x20, 0x20, 0x20, 0x20, 0x00, // 55
442  0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, // 56
443  0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60, 0x00, // 57
444  0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, // 58
445  0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x20, 0x40, // 59
446  0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, // 60
447  0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, // 61
448  0xC0, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC0, 0x00, // 62
449  0x70, 0x88, 0x08, 0x10, 0x20, 0x00, 0x20, 0x00, // 63
450  0x70, 0x88, 0x08, 0x68, 0xA8, 0xA8, 0x70, 0x00, // 64
451  0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, // 65
452  0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0xF0, 0x00, // 66
453  0x30, 0x48, 0x80, 0x80, 0x80, 0x48, 0x30, 0x00, // 67
454  0xE0, 0x50, 0x48, 0x48, 0x48, 0x50, 0xE0, 0x00, // 68
455  0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00, // 69
456  0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00, // 70
457  0x70, 0x88, 0x80, 0xB8, 0x88, 0x88, 0x70, 0x00, // 71
458  0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00, // 72
459  0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, // 73
460  0x38, 0x10, 0x10, 0x10, 0x90, 0x90, 0x60, 0x00, // 74
461  0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00, // 75
462  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00, // 76
463  0x88, 0xD8, 0xA8, 0xA8, 0x88, 0x88, 0x88, 0x00, // 77
464  0x88, 0xC8, 0xC8, 0xA8, 0x98, 0x98, 0x88, 0x00, // 78
465  0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, // 79
466  0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00, // 80
467  0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00, // 81
468  0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00, // 82
469  0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, // 83
470  0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, // 84
471  0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, // 85
472  0x88, 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, // 86
473  0x88, 0x88, 0x88, 0xA8, 0xA8, 0xD8, 0x88, 0x00, // 87
474  0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, // 88
475  0x88, 0x88, 0x88, 0x70, 0x20, 0x20, 0x20, 0x00, // 89
476  0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, // 90
477  0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x00, // 91
478  0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, // 92
479  0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, // 93
480  0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, // 94
481  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, // 95
482  0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // 96
483  0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 97
484  0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00, // 98
485  0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00, // 99
486  0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00, // 100
487  0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, // 101
488  0x10, 0x28, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x00, // 102
489  0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x70, // 103
490  0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x88, 0x00, // 104
491  0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, // 105
492  0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x90, 0x60, // 106
493  0x40, 0x40, 0x48, 0x50, 0x60, 0x50, 0x48, 0x00, // 107
494  0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, // 108
495  0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, // 109
496  0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, // 110
497  0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, // 111
498  0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80, // 112
499  0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08, // 113
500  0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00, // 114
501  0x00, 0x00, 0x78, 0x80, 0xF0, 0x08, 0xF0, 0x00, // 115
502  0x40, 0x40, 0xF0, 0x40, 0x40, 0x48, 0x30, 0x00, // 116
503  0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x68, 0x00, // 117
504  0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00, // 118
505  0x00, 0x00, 0x88, 0xA8, 0xA8, 0xA8, 0x50, 0x00, // 119
506  0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, // 120
507  0x00, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x70, // 121
508  0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00, // 122
509  0x18, 0x20, 0x20, 0x40, 0x20, 0x20, 0x18, 0x00, // 123
510  0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x00, // 124
511  0xC0, 0x20, 0x20, 0x10, 0x20, 0x20, 0xC0, 0x00, // 125
512  0x40, 0xA8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // 126
513  0x00, 0x00, 0x20, 0x50, 0xF8, 0x00, 0x00, 0x00, // 127
514  0x70, 0x88, 0x80, 0x80, 0x88, 0x70, 0x20, 0x60, // 128
515  0x90, 0x00, 0x00, 0x90, 0x90, 0x90, 0x68, 0x00, // 129
516  0x10, 0x20, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, // 130
517  0x20, 0x50, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 131
518  0x48, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 132
519  0x20, 0x10, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 133
520  0x20, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 134
521  0x00, 0x70, 0x80, 0x80, 0x80, 0x70, 0x10, 0x60, // 135
522  0x20, 0x50, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, // 136
523  0x50, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, // 137
524  0x20, 0x10, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, // 138
525  0x50, 0x00, 0x00, 0x60, 0x20, 0x20, 0x70, 0x00, // 139
526  0x20, 0x50, 0x00, 0x60, 0x20, 0x20, 0x70, 0x00, // 140
527  0x40, 0x20, 0x00, 0x60, 0x20, 0x20, 0x70, 0x00, // 141
528  0x50, 0x00, 0x20, 0x50, 0x88, 0xF8, 0x88, 0x00, // 142
529  0x20, 0x00, 0x20, 0x50, 0x88, 0xF8, 0x88, 0x00, // 143
530  0x10, 0x20, 0xF8, 0x80, 0xF0, 0x80, 0xF8, 0x00, // 144
531  0x00, 0x00, 0x6C, 0x12, 0x7E, 0x90, 0x6E, 0x00, // 145
532  0x3E, 0x50, 0x90, 0x9C, 0xF0, 0x90, 0x9E, 0x00, // 146
533  0x60, 0x90, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, // 147
534  0x90, 0x00, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, // 148
535  0x40, 0x20, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, // 149
536  0x40, 0xA0, 0x00, 0xA0, 0xA0, 0xA0, 0x50, 0x00, // 150
537  0x40, 0x20, 0x00, 0xA0, 0xA0, 0xA0, 0x50, 0x00, // 151
538  0x90, 0x00, 0x90, 0x90, 0xB0, 0x50, 0x10, 0xE0, // 152
539  0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, // 153
540  0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, // 154
541  0x20, 0x20, 0x78, 0x80, 0x80, 0x78, 0x20, 0x20, // 155
542  0x18, 0x24, 0x20, 0xF8, 0x20, 0xE2, 0x5C, 0x00, // 156
543  0x88, 0x50, 0x20, 0xF8, 0x20, 0xF8, 0x20, 0x00, // 157
544  0xC0, 0xA0, 0xA0, 0xC8, 0x9C, 0x88, 0x88, 0x8C, // 158
545  0x18, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x40, // 159
546  0x10, 0x20, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 160
547  0x10, 0x20, 0x00, 0x60, 0x20, 0x20, 0x70, 0x00, // 161
548  0x20, 0x40, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, // 162
549  0x20, 0x40, 0x00, 0x90, 0x90, 0x90, 0x68, 0x00, // 163
550  0x50, 0xA0, 0x00, 0xA0, 0xD0, 0x90, 0x90, 0x00, // 164
551  0x28, 0x50, 0x00, 0xC8, 0xA8, 0x98, 0x88, 0x00, // 165
552  0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0xF8, // 166
553  0x00, 0x60, 0x90, 0x90, 0x90, 0x60, 0x00, 0xF0, // 167
554  0x20, 0x00, 0x20, 0x40, 0x80, 0x88, 0x70, 0x00, // 168
555  0x00, 0x00, 0x00, 0xF8, 0x80, 0x80, 0x00, 0x00, // 169
556  0x00, 0x00, 0x00, 0xF8, 0x08, 0x08, 0x00, 0x00, // 170
557  0x84, 0x88, 0x90, 0xA8, 0x54, 0x84, 0x08, 0x1C, // 171
558  0x84, 0x88, 0x90, 0xA8, 0x58, 0xA8, 0x3C, 0x08, // 172
559  0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, // 173
560  0x00, 0x00, 0x24, 0x48, 0x90, 0x48, 0x24, 0x00, // 174
561  0x00, 0x00, 0x90, 0x48, 0x24, 0x48, 0x90, 0x00, // 175
562  0x28, 0x50, 0x20, 0x50, 0x88, 0xF8, 0x88, 0x00, // 176
563  0x28, 0x50, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, // 177
564  0x28, 0x50, 0x00, 0x70, 0x20, 0x20, 0x70, 0x00, // 178
565  0x28, 0x50, 0x00, 0x20, 0x20, 0x20, 0x70, 0x00, // 179
566  0x28, 0x50, 0x00, 0x70, 0x88, 0x88, 0x70, 0x00, // 180
567  0x50, 0xA0, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, // 181
568  0x28, 0x50, 0x00, 0x88, 0x88, 0x88, 0x70, 0x00, // 182
569  0x50, 0xA0, 0x00, 0xA0, 0xA0, 0xA0, 0x50, 0x00, // 183
570  0xFC, 0x48, 0x48, 0x48, 0xE8, 0x08, 0x50, 0x20, // 184
571  0x00, 0x50, 0x00, 0x50, 0x50, 0x50, 0x10, 0x20, // 185
572  0xC0, 0x44, 0xC8, 0x54, 0xEC, 0x54, 0x9E, 0x04, // 186
573  0x10, 0xA8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // 187
574  0x00, 0x20, 0x50, 0x88, 0x50, 0x20, 0x00, 0x00, // 188
575  0x88, 0x10, 0x20, 0x40, 0x80, 0x28, 0x00, 0x00, // 189
576  0x7C, 0xA8, 0xA8, 0x68, 0x28, 0x28, 0x28, 0x00, // 190
577  0x38, 0x40, 0x30, 0x48, 0x48, 0x30, 0x08, 0x70, // 191
578  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, // 192
579  0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, // 193
580  0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 194
581  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 195
582  0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, // 196
583  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, // 197
584  0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, // 198
585  0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, // 199
586  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, // 200
587  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, // 201
588  0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, // 202
589  0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88, // 203
590  0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11, // 204
591  0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, // 205
592  0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, // 206
593  0x80, 0xC0, 0xE0, 0xF0, 0xE0, 0xC0, 0x80, 0x00, // 207
594  0x01, 0x03, 0x07, 0x0F, 0x07, 0x03, 0x01, 0x00, // 208
595  0xFF, 0x7E, 0x3C, 0x18, 0x18, 0x3C, 0x7E, 0xFF, // 209
596  0x81, 0xC3, 0xE7, 0xFF, 0xFF, 0xE7, 0xC3, 0x81, // 210
597  0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, // 211
598  0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, // 212
599  0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, // 213
600  0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, // 214
601  0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, // 215
602  0x00, 0x20, 0x20, 0x50, 0x50, 0x88, 0xF8, 0x00, // 216
603  0x20, 0x20, 0x70, 0x20, 0x70, 0x20, 0x20, 0x00, // 217
604  0x00, 0x00, 0x00, 0x50, 0x88, 0xA8, 0x50, 0x00, // 218
605  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 219
606  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, // 220
607  0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, // 221
608  0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, // 222
609  0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // 223
610  0x00, 0x00, 0x68, 0x90, 0x90, 0x90, 0x68, 0x00, // 224
611  0x30, 0x48, 0x48, 0x70, 0x48, 0x48, 0x70, 0xC0, // 225
612  0xF8, 0x88, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, // 226
613  0xF8, 0x50, 0x50, 0x50, 0x50, 0x50, 0x98, 0x00, // 227
614  0xF8, 0x88, 0x40, 0x20, 0x40, 0x88, 0xF8, 0x00, // 228
615  0x00, 0x00, 0x78, 0x90, 0x90, 0x90, 0x60, 0x00, // 229
616  0x00, 0x50, 0x50, 0x50, 0x50, 0x68, 0x80, 0x80, // 230
617  0x00, 0x50, 0xA0, 0x20, 0x20, 0x20, 0x20, 0x00, // 231
618  0xF8, 0x20, 0x70, 0xA8, 0xA8, 0x70, 0x20, 0xF8, // 232
619  0x20, 0x50, 0x88, 0xF8, 0x88, 0x50, 0x20, 0x00, // 233
620  0x70, 0x88, 0x88, 0x88, 0x50, 0x50, 0xD8, 0x00, // 234
621  0x30, 0x40, 0x40, 0x20, 0x50, 0x50, 0x50, 0x20, // 235
622  0x00, 0x00, 0x00, 0x50, 0xA8, 0xA8, 0x50, 0x00, // 236
623  0x08, 0x70, 0xA8, 0xA8, 0xA8, 0x70, 0x80, 0x00, // 237
624  0x38, 0x40, 0x80, 0xF8, 0x80, 0x40, 0x38, 0x00, // 238
625  0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, // 239
626  0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, // 240
627  0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0xF8, 0x00, // 241
628  0xC0, 0x30, 0x08, 0x30, 0xC0, 0x00, 0xF8, 0x00, // 242
629  0x18, 0x60, 0x80, 0x60, 0x18, 0x00, 0xF8, 0x00, // 243
630  0x10, 0x28, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // 244
631  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0x40, // 245
632  0x00, 0x20, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x00, // 246
633  0x00, 0x50, 0xA0, 0x00, 0x50, 0xA0, 0x00, 0x00, // 247
634  0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, // 248
635  0x00, 0x30, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, // 249
636  0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, // 250
637  0x3E, 0x20, 0x20, 0x20, 0xA0, 0x60, 0x20, 0x00, // 251
638  0xA0, 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, // 252
639  0x40, 0xA0, 0x20, 0x40, 0xE0, 0x00, 0x00, 0x00, // 253
640  0x00, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, // 254
641  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 255
642 };
643 
644 static byte MSXFont[256 * 9];
645 
647  : ImagePrinter(motherBoard, true)
648 {
649  msxPrnSetFont(MSXFontRaw);
651 }
652 
653 const string& ImagePrinterMSX::getName() const
654 {
655  static const string name("msx-printer");
656  return name;
657 }
658 
660 {
661  // TODO which printer type
662  return "Emulate MSX printer, prints to image.";
663 }
664 
665 void ImagePrinterMSX::msxPrnSetFont(const byte* msxBits)
666 {
667  // Convert MSX printer font to Epson printer font
668  byte* font = MSXFont;
669 
670  for (int i = 0; i < 256; ++i) {
671  byte oneBits = 0;
672  int start = -1;
673  int end = 0;
674 
675  // Rotate MSX character
676  for (int j = 0; j < 8; ++j) {
677  byte charBits = 0;
678  for (int k = 0; k < 8; ++k) {
679  charBits |= ((msxBits[7 - k] >> (7 - j)) & 1) << k;
680  }
681 
682  oneBits |= charBits;
683  if (oneBits != 0 && start < 0) start = j;
684  if (charBits != 0) end = j;
685  font[j + 1] = charBits;
686  }
687 
688  end = end + 1;
689  if (start < 0 || start >= 7) start = 0;
690  if (end == 1) end = 5;
691  if (end >= 7) end = 7;
692  font[0] = (start << 4) | end;
693 
694  font += 9;
695  msxBits += 8;
696  }
697 }
698 
699 void ImagePrinterMSX::getNumberOfDots(unsigned& dotsX, unsigned& dotsY)
700 {
701  dotsX = 825;
702  dotsY = 825;
703 }
704 
705 void ImagePrinterMSX::resetSettings()
706 {
707  lineFeed = 12.0;
708  leftBorder = 48;
709  rightBorder = 800;
710  graphDensity = 1.0;
711  fontDensity = 1.0;
712  pageTop = 48;
713  lines = 72;
714  fontWidth = 8;
715  eightBit = -1;
716 
717  // note: this only overwrites 9/12 of the fontInfo.rom array.
718  memcpy(fontInfo.rom, MSXFont, sizeof(MSXFont));
719  fontInfo.charWidth = 9;
720  fontInfo.pixelDelta = 1.0;
721  fontInfo.useRam = false;
722 }
723 
724 
725 unsigned ImagePrinterMSX::calcEscSequenceLength(byte character)
726 {
727  switch (character) {
728  case 'C':
729  return 1;
730  case 'T': case 'Z':
731  return 2;
732  case 'O': case '\\': case 'L': case '/':
733  return 3;
734  case 'S':
735  return 4;
736  case 'G':
737  return 7;
738  default:
739  return 0;
740  }
741 }
742 
743 unsigned ImagePrinterMSX::parseNumber(unsigned sizeStart, unsigned sizeChars)
744 {
745  unsigned Value = 0;
746  while (sizeChars--) {
747  Value = Value * 10;
748  byte data = abEscSeq[sizeStart++];
749  if (data >= '0' && data <= '9') {
750  Value += unsigned(data - '0');
751  }
752  }
753  return Value;
754 }
755 
756 void ImagePrinterMSX::processEscSequence()
757 {
758  switch (abEscSeq[0]) {
759  case 'N':
760  proportional = false;
761  fontDensity = 1.0;
762  break;
763  case 'E':
764  proportional = false;
765  fontDensity = 1.40;
766  break;
767  case 'Q':
768  proportional = false;
769  fontDensity = 1.72;
770  break;
771  case 'P':
772  proportional = true;
773  fontDensity = 0.90;
774  break;
775  case '!':
776  letterQuality = true;
777  break;
778  case '\"':
779  letterQuality = false;
780  break;
781  case 'C':
782  switch (abEscSeq[1]) {
783  case 'D':
784  doubleStrike = true;
785  break;
786  case 'd':
787  doubleStrike = false;
788  break;
789  case 'I':
790  italic = true;
791  break;
792  case 'i':
793  italic = false;
794  break;
795  case 'B':
796  bold = true;
797  break;
798  case 'b':
799  bold = false;
800  break;
801  case 'S':
802  superscript = true;
803  break;
804  case 's':
805  superscript = false;
806  break;
807  case 'U':
808  subscript = true;
809  break;
810  case 'u':
811  subscript = false;
812  break;
813  }
814  break;
815  case '(': // ???: Set a horizontal tab position
816  break;
817  case ')': // ???: Partially delete a horizontal tab position
818  break;
819  case '2': // ???: Clear horizontal tabs
820  break;
821  case 'O':
822  switch (abEscSeq[1]) {
823  case 'S':
824  perforationSkip = parseNumber(2, 2);
825  break;
826  case 'I': // ???: Set page-height(inches)
827  break;
828  default: // ???: Set page-height (lines)
829  break;
830  }
831  break;
832  case '/': // Right margin
833  break;
834  case 'L':
835  leftBorder = parseNumber(1, 3);
836  break;
837  case 'A': // ???: Line-feed 1/6"
838  lineFeed = 12.0;
839  break;
840  case 'B': // ???: Line-feed 1/9"
841  lineFeed = 8.0;
842  break;
843  case 'T': // ???: Line-feed nn/144"
844  lineFeed = parseNumber(1, 2) / 2.0;
845  break;
846  case 'Z': // ???: Line-feed nn/216"
847  lineFeed = parseNumber(1, 2) / 3.0;
848  break;
849  case '[': // ???: Uni-directional printing
850  break;
851  case ']': // ???: Bi-directional printing
852  break;
853  case 'p':
854  detectPaperOut = true;
855  break;
856  case 'q':
857  detectPaperOut = false;
858  break;
859  case 13: // (ESC, CR) Move printer-head to end-position
860  break;
861  case '@':
863  break;
864  case '\\':
865  rightBorder = parseNumber(1, 3);
866  break;
867  case 'G':
868  graphDensity = parseNumber(1, 3) / 100.0;
869  if (graphDensity < 0.1) {
870  graphDensity = 0.1;
871  }
872  sizeRemainingDataBytes = parseNumber(4, 4);
873  break;
874  case 'S': // Print graphics, density depending on font
875  sizeRemainingDataBytes = parseNumber(1, 4);
876  break;
877  case 'X':
878  underline = true;
879  break;
880  case 'Y':
881  underline = false;
882  break;
883  case '&':
884  case '$':
885  japanese = !japanese;
886  break;
887  case 'f': // ???: Scroll paper forward
888  break;
889  case 'r': // ???: Scroll paper back
890  break;
891  }
892 }
893 
894 void ImagePrinterMSX::processCharacter(byte data)
895 {
896  if (alternateChar) {
897  // Print SOH-preceded character
898  printVisibleCharacter(data & 0x1F);
899  alternateChar = false;
900  } else {
901  switch (data) {
902  case 1: // SOH: A symbolcode preceding code
903  alternateChar = true;
904  break;
905  case 7: // BEL: Audible beep (buzzer, 0.3s)
906  break;
907  case 8: // BS: Backstep (1 Character)
908  // TODO: fix for other font-sizes
909  hpos -= 8;
910  if (hpos < leftBorder) {
911  hpos = leftBorder;
912  }
913  break;
914  case 9: { // HAT: Horizontal tabulator
915  // TODO: fix for other font-sizes
916  hpos = ((unsigned(hpos) + 64 - leftBorder) & ~63)
917  + leftBorder;
918  if (hpos < rightBorder) {
919  break;
920  }
921  hpos = leftBorder;
922  // fall thru: CR/LF
923  }
924  case 10: // LF: Carriage return + Line feed
925  case 11: // VT: Vertical tabulator (like LF)
926  //hpos = leftBorder;
927  vpos += lineFeed;
928  if (vpos >= pageHeight) {
930  }
931  break;
932  case 12: // FF: Form feed
933  ensurePrintPage();
935  break;
936  case 13: // CR: Carriage return
937  hpos = leftBorder;
938  break;
939  case 14: // SO: Double character-width on
940  doubleWidth = true;
941  break;
942  case 15: // SI: Double character-width off
943  doubleWidth = false;
944  break;
945  case 27:
946  escSequence = true;
947  break;
948  default:
949  if (data >= 32) {
950  // Yes, we can print it!
951  printVisibleCharacter(data);
952  }
953  break;
954  }
955  }
956 }
957 
958 template<typename Archive>
959 void ImagePrinterMSX::serialize(Archive& /*ar*/, unsigned /*version*/)
960 {
961  // TODO is this worth it?
962 }
965 
966 
967 // class ImagePrinterEpson
968 
969 static const byte EpsonFontRom[] = {
970  0x8b, 0x04, 0x0a, 0x20, 0x8a, 0x60, 0x0a, 0x20, 0x1c, 0x02, 0x00, 0x00, // 0
971  0x8b, 0x1c, 0x22, 0x08, 0xa2, 0x48, 0x22, 0x08, 0x22, 0x18, 0x00, 0x00, // 1
972  0x9b, 0x00, 0x3c, 0x00, 0x82, 0x40, 0x02, 0x00, 0x3c, 0x02, 0x00, 0x00, // 2
973  0x9a, 0x00, 0x1c, 0x22, 0x80, 0x62, 0x00, 0x22, 0x1c, 0x00, 0x00, 0x00, // 3
974  0x96, 0x00, 0x12, 0x80, 0x5e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 4
975  0xa7, 0x00, 0x00, 0x40, 0xa0, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x00, 0x00, // 5
976  0x8b, 0x12, 0x00, 0x7e, 0x80, 0x12, 0x80, 0x02, 0x80, 0x42, 0x00, 0x00, // 6
977  0xc8, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 7
978  0x8b, 0x06, 0x00, 0x09, 0x00, 0x51, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, // 8
979  0x8b, 0x5e, 0x80, 0x10, 0x80, 0x08, 0x40, 0x04, 0x40, 0x9e, 0x00, 0x00, // 9
980  0x8a, 0x40, 0x9e, 0x00, 0x90, 0x40, 0x10, 0x4e, 0x80, 0x00, 0x00, 0x00, // 10
981  0x8b, 0x92, 0x28, 0x44, 0x00, 0x44, 0x00, 0x44, 0x28, 0x92, 0x00, 0x00, // 11
982  0x8b, 0xfe, 0x00, 0xa0, 0x00, 0x48, 0x00, 0x1e, 0x00, 0x0a, 0x00, 0x00, // 12
983  0x8b, 0x06, 0x08, 0x54, 0xa0, 0x04, 0xa0, 0x54, 0x08, 0x06, 0x00, 0x00, // 13
984  0x8b, 0x04, 0x0a, 0x20, 0x0a, 0xa0, 0x0a, 0x20, 0x1c, 0x02, 0x00, 0x00, // 14
985  0x0a, 0x38, 0x44, 0x01, 0x44, 0x01, 0x46, 0x00, 0x44, 0x00, 0x00, 0x00, // 15
986  0x9a, 0x00, 0x50, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x14, 0x00, 0x00, 0x00, // 16
987  0x8a, 0x7e, 0x80, 0x00, 0x80, 0x12, 0x80, 0x12, 0x6c, 0x00, 0x00, 0x00, // 17
988  0x8b, 0x3e, 0x40, 0x90, 0x00, 0xfe, 0x00, 0x92, 0x00, 0x92, 0x00, 0x00, // 18
989  0x8b, 0x2c, 0x02, 0x28, 0x02, 0x1c, 0x20, 0x0a, 0x20, 0x1a, 0x00, 0x00, // 19
990  0x8b, 0x3a, 0x44, 0x00, 0x8a, 0x10, 0xa2, 0x00, 0x44, 0xb8, 0x00, 0x00, // 20
991  0x8b, 0x02, 0x08, 0x14, 0x22, 0x08, 0x22, 0x14, 0x08, 0x20, 0x00, 0x00, // 21
992  0xa9, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // 22
993  0x8b, 0x06, 0x88, 0x14, 0x20, 0x44, 0x20, 0x14, 0x88, 0x06, 0x00, 0x00, // 23
994  0x8b, 0x1c, 0xa2, 0x00, 0x22, 0x00, 0x22, 0x00, 0xa2, 0x1c, 0x00, 0x00, // 24
995  0x8b, 0x3c, 0x82, 0x00, 0x02, 0x00, 0x02, 0x00, 0x82, 0x3c, 0x00, 0x00, // 25
996  0x8b, 0x04, 0x0a, 0xa0, 0x0a, 0x20, 0x0a, 0xa0, 0x1c, 0x02, 0x00, 0x00, // 26
997  0x9a, 0x00, 0x1c, 0xa2, 0x00, 0x22, 0x00, 0xa2, 0x1c, 0x00, 0x00, 0x00, // 27
998  0x8a, 0x3c, 0x80, 0x02, 0x00, 0x02, 0x80, 0x3c, 0x02, 0x00, 0x00, 0x00, // 28
999  0x8b, 0x3e, 0x00, 0x2a, 0x00, 0x6a, 0x80, 0x2a, 0x00, 0x22, 0x00, 0x00, // 29
1000  0x8b, 0x1c, 0x22, 0x08, 0x22, 0x48, 0xa2, 0x08, 0x22, 0x18, 0x00, 0x00, // 30
1001  0x8b, 0xa8, 0x00, 0x68, 0x00, 0x3e, 0x00, 0x68, 0x00, 0xa8, 0x00, 0x00, // 31
1002  0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32
1003  0xc8, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 33
1004  0xa9, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, // 34
1005  0x8b, 0x28, 0x00, 0xfe, 0x00, 0x28, 0x00, 0xfe, 0x00, 0x28, 0x00, 0x00, // 35
1006  0x8b, 0x24, 0x00, 0x54, 0x00, 0xfe, 0x00, 0x54, 0x00, 0x48, 0x00, 0x00, // 36
1007  0x8b, 0xc0, 0x02, 0xc4, 0x08, 0x10, 0x20, 0x46, 0x80, 0x06, 0x00, 0x00, // 37
1008  0x8b, 0x4c, 0xa0, 0x12, 0xa0, 0x4a, 0x00, 0x04, 0x08, 0x12, 0x00, 0x00, // 38
1009  0xc8, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, // 39
1010  0xc9, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, // 40
1011  0xa7, 0x00, 0x00, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 41
1012  0x8b, 0x10, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x10, 0x00, 0x00, // 42
1013  0x8b, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, // 43
1014  0x39, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, // 44
1015  0x8b, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, // 45
1016  0xa8, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 46
1017  0x9a, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, // 47
1018  0x8b, 0x38, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x38, 0x00, 0x00, // 48
1019  0xa9, 0x00, 0x00, 0x42, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, // 49
1020  0x8b, 0x42, 0x80, 0x06, 0x80, 0x0a, 0x80, 0x12, 0x80, 0x62, 0x00, 0x00, // 50
1021  0x8b, 0x84, 0x00, 0x82, 0x00, 0xa2, 0x00, 0xd2, 0x00, 0x8c, 0x00, 0x00, // 51
1022  0x8b, 0x08, 0x10, 0x28, 0x40, 0x88, 0x00, 0xfe, 0x00, 0x08, 0x00, 0x00, // 52
1023  0x8b, 0xe4, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0xa0, 0x02, 0x9c, 0x00, 0x00, // 53
1024  0x8b, 0x0c, 0x12, 0x20, 0x52, 0x80, 0x12, 0x00, 0x12, 0x0c, 0x00, 0x00, // 54
1025  0x8b, 0x80, 0x00, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x80, 0x00, 0x00, // 55
1026  0x8b, 0x6c, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x6c, 0x00, 0x00, // 56
1027  0x8b, 0x60, 0x90, 0x00, 0x90, 0x02, 0x94, 0x08, 0x90, 0x60, 0x00, 0x00, // 57
1028  0xa7, 0x00, 0x00, 0x36, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 58
1029  0x27, 0x00, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 59
1030  0x89, 0x10, 0x00, 0x28, 0x00, 0x44, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, // 60
1031  0x8b, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, // 61
1032  0xab, 0x00, 0x00, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00, // 62
1033  0x8b, 0x40, 0x80, 0x00, 0x80, 0x0a, 0x80, 0x10, 0x80, 0x60, 0x00, 0x00, // 63
1034  0x8b, 0x38, 0x44, 0x82, 0x10, 0xaa, 0x00, 0xaa, 0x00, 0x7a, 0x00, 0x00, // 64
1035  0x8b, 0x1e, 0x20, 0x48, 0x80, 0x08, 0x80, 0x48, 0x20, 0x1e, 0x00, 0x00, // 65
1036  0x8b, 0x82, 0x7c, 0x82, 0x10, 0x82, 0x10, 0x82, 0x10, 0x6c, 0x00, 0x00, // 66
1037  0x8b, 0x7c, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x44, 0x00, 0x00, // 67
1038  0x8b, 0x82, 0x7c, 0x82, 0x00, 0x82, 0x00, 0x82, 0x44, 0x38, 0x00, 0x00, // 68
1039  0x8b, 0xfe, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x82, 0x00, 0x00, // 69
1040  0x8b, 0xfe, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x80, 0x00, 0x00, // 70
1041  0x8b, 0x7c, 0x82, 0x00, 0x82, 0x10, 0x82, 0x10, 0x82, 0x5c, 0x00, 0x00, // 71
1042  0x8b, 0xfe, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x00, // 72
1043  0xa9, 0x00, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, // 73
1044  0x8a, 0x0c, 0x02, 0x00, 0x82, 0x00, 0x82, 0x7c, 0x80, 0x00, 0x00, 0x00, // 74
1045  0x8b, 0xfe, 0x00, 0x10, 0x00, 0x28, 0x00, 0x44, 0x00, 0x82, 0x00, 0x00, // 75
1046  0x8b, 0xfe, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, // 76
1047  0x8b, 0xfe, 0x00, 0x40, 0x20, 0x10, 0x20, 0x40, 0x00, 0xfe, 0x00, 0x00, // 77
1048  0x8b, 0xfe, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0xfe, 0x00, 0x00, // 78
1049  0x8b, 0x7c, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x7c, 0x00, 0x00, // 79
1050  0x8b, 0xfe, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x60, 0x00, 0x00, // 80
1051  0x8b, 0x7c, 0x82, 0x00, 0x82, 0x08, 0x82, 0x04, 0x80, 0x7a, 0x00, 0x00, // 81
1052  0x8b, 0xfe, 0x00, 0x90, 0x00, 0x90, 0x00, 0x98, 0x04, 0x62, 0x00, 0x00, // 82
1053  0x8b, 0x64, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x4c, 0x00, 0x00, // 83
1054  0x8b, 0x80, 0x00, 0x80, 0x00, 0xfe, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, // 84
1055  0x8b, 0xfc, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xfc, 0x00, 0x00, // 85
1056  0x8b, 0xe0, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0xe0, 0x00, 0x00, // 86
1057  0x8b, 0xfc, 0x02, 0x04, 0x08, 0x30, 0x08, 0x04, 0x02, 0xfc, 0x00, 0x00, // 87
1058  0x9a, 0x00, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, // 88
1059  0x8b, 0x80, 0x40, 0x20, 0x10, 0x0e, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, // 89
1060  0x9a, 0x00, 0x82, 0x04, 0x8a, 0x10, 0xa2, 0x40, 0x82, 0x00, 0x00, 0x00, // 90
1061  0xa9, 0x00, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, // 91
1062  0x9a, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00, 0x00, // 92
1063  0xa9, 0x00, 0x00, 0x82, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, // 93
1064  0x8b, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, // 94
1065  0x0b, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, // 95
1066  0xb7, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 96
1067  0x8b, 0x04, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x1c, 0x02, 0x00, 0x00, // 97
1068  0x8a, 0xfe, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x1c, 0x00, 0x00, 0x00, // 98
1069  0x8a, 0x1c, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x00, 0x00, // 99
1070  0x8a, 0x1c, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0xfe, 0x00, 0x00, 0x00, // 100
1071  0x8b, 0x1c, 0x22, 0x08, 0x22, 0x08, 0x22, 0x08, 0x22, 0x18, 0x00, 0x00, // 101
1072  0x89, 0x10, 0x00, 0x10, 0x7e, 0x90, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, // 102
1073  0x0a, 0x38, 0x44, 0x01, 0x44, 0x01, 0x44, 0x01, 0x7e, 0x00, 0x00, 0x00, // 103
1074  0x8a, 0xfe, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x1e, 0x00, 0x00, 0x00, // 104
1075  0x98, 0x00, 0x22, 0x00, 0xbe, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 105
1076  0x99, 0x00, 0x01, 0x00, 0x01, 0x20, 0x01, 0xbe, 0x00, 0x00, 0x00, 0x00, // 106
1077  0x9a, 0x00, 0xfe, 0x00, 0x08, 0x00, 0x14, 0x00, 0x22, 0x00, 0x00, 0x00, // 107
1078  0x98, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 108
1079  0x8b, 0x1e, 0x20, 0x00, 0x20, 0x1e, 0x20, 0x00, 0x20, 0x1e, 0x00, 0x00, // 109
1080  0x8a, 0x3e, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x1e, 0x00, 0x00, 0x00, // 110
1081  0x8b, 0x1c, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x1c, 0x00, 0x00, // 111
1082  0x0a, 0x7f, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x38, 0x00, 0x00, 0x00, // 112
1083  0x1b, 0x00, 0x38, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7e, 0x00, 0x00, // 113
1084  0x8a, 0x3e, 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, // 114
1085  0x8b, 0x10, 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x04, 0x00, 0x00, // 115
1086  0x8a, 0x20, 0x00, 0x7c, 0x02, 0x20, 0x02, 0x20, 0x02, 0x00, 0x00, 0x00, // 116
1087  0x8b, 0x3c, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3c, 0x02, 0x00, 0x00, // 117
1088  0x8b, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, // 118
1089  0x8b, 0x3c, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x3c, 0x00, 0x00, // 119
1090  0x89, 0x22, 0x14, 0x00, 0x08, 0x00, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, // 120
1091  0x0b, 0x40, 0x20, 0x11, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, // 121
1092  0x89, 0x22, 0x04, 0x22, 0x08, 0x22, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, // 122
1093  0xaa, 0x00, 0x00, 0x10, 0x00, 0x6c, 0x82, 0x00, 0x82, 0x00, 0x00, 0x00, // 123
1094  0xc7, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 124
1095  0xaa, 0x00, 0x82, 0x00, 0x82, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, // 125
1096  0x8b, 0x40, 0x80, 0x00, 0x80, 0x40, 0x20, 0x00, 0x20, 0x40, 0x00, 0x00, // 126
1097  0x8b, 0x7c, 0x82, 0x04, 0x8a, 0x10, 0xa2, 0x40, 0x82, 0x7c, 0x00, 0x00, // 127
1098  0x8a, 0x04, 0x0a, 0x80, 0x2a, 0x60, 0x0a, 0x24, 0x1a, 0x00, 0x00, 0x00, // 128
1099  0x8a, 0x0c, 0x12, 0x28, 0x82, 0x68, 0x02, 0x28, 0x10, 0x00, 0x00, 0x00, // 129
1100  0x8a, 0x0c, 0x32, 0x00, 0x82, 0x40, 0x02, 0x0c, 0x32, 0x00, 0x00, 0x00, // 130
1101  0x8a, 0x0c, 0x12, 0x00, 0xa0, 0x42, 0x00, 0x24, 0x18, 0x00, 0x00, 0x00, // 131
1102  0x98, 0x00, 0x02, 0x00, 0x16, 0x88, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, // 132
1103  0xa9, 0x00, 0x00, 0x40, 0xa0, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x00, 0x00, // 133
1104  0x8b, 0x12, 0x00, 0x1e, 0x60, 0x12, 0x80, 0x12, 0x80, 0x40, 0x00, 0x00, // 134
1105  0x9a, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x80, 0x00, 0x00, 0x00, // 135
1106  0x8a, 0x06, 0x01, 0x08, 0x01, 0x10, 0x21, 0x80, 0x02, 0x00, 0x00, 0x00, // 136
1107  0x8b, 0x06, 0x58, 0x80, 0x08, 0x84, 0x40, 0x06, 0x58, 0x80, 0x00, 0x00, // 137
1108  0x8b, 0x12, 0x4c, 0x80, 0x10, 0x80, 0x50, 0x02, 0x4c, 0x80, 0x00, 0x00, // 138
1109  0x8b, 0x02, 0x18, 0x24, 0x80, 0x44, 0x02, 0x48, 0x30, 0x80, 0x00, 0x00, // 139
1110  0x8b, 0x06, 0x38, 0xc0, 0x20, 0x88, 0x26, 0xd8, 0x02, 0x08, 0x00, 0x00, // 140
1111  0x8b, 0x02, 0x04, 0x08, 0x14, 0x40, 0xa4, 0x00, 0xbe, 0x40, 0x00, 0x00, // 141
1112  0x8a, 0x04, 0x0a, 0x20, 0x0a, 0x20, 0x8a, 0x24, 0x1a, 0x00, 0x00, 0x00, // 142
1113  0x1b, 0x00, 0x18, 0x21, 0x04, 0x41, 0x06, 0x40, 0x04, 0x40, 0x00, 0x00, // 143
1114  0x8b, 0x02, 0x10, 0x6a, 0x00, 0xaa, 0x00, 0xac, 0x10, 0x80, 0x00, 0x00, // 144
1115  0x8a, 0x06, 0x18, 0x60, 0x00, 0x82, 0x10, 0x82, 0x6c, 0x00, 0x00, 0x00, // 145
1116  0x8b, 0x0e, 0x30, 0x40, 0x90, 0x0e, 0x70, 0x82, 0x10, 0x82, 0x00, 0x00, // 146
1117  0x8b, 0x04, 0x22, 0x08, 0x22, 0x1c, 0x22, 0x08, 0x22, 0x10, 0x00, 0x00, // 147
1118  0x8b, 0x1a, 0x24, 0x42, 0x08, 0x92, 0x20, 0x84, 0x48, 0xb0, 0x00, 0x00, // 148
1119  0x8a, 0x0c, 0x11, 0x02, 0x2c, 0x12, 0x20, 0x44, 0x18, 0x00, 0x00, 0x00, // 149
1120  0xa9, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // 150
1121  0x8b, 0x02, 0x04, 0x08, 0x14, 0x80, 0x24, 0x00, 0x3e, 0x80, 0x00, 0x00, // 151
1122  0x8b, 0x0c, 0x12, 0x00, 0xa2, 0x00, 0x22, 0x00, 0xa4, 0x18, 0x00, 0x00, // 152
1123  0x8b, 0x0c, 0x32, 0x00, 0x82, 0x00, 0x02, 0x00, 0x8c, 0x30, 0x00, 0x00, // 153
1124  0x8a, 0x04, 0x0a, 0x20, 0x8a, 0x20, 0x0a, 0x24, 0x9a, 0x00, 0x00, 0x00, // 154
1125  0x8a, 0x0c, 0x12, 0x00, 0xa0, 0x02, 0x00, 0x24, 0x98, 0x00, 0x00, 0x00, // 155
1126  0x8b, 0x0c, 0x32, 0x80, 0x02, 0x00, 0x02, 0x0c, 0xb2, 0x00, 0x00, 0x00, // 156
1127  0x8b, 0x06, 0x18, 0x22, 0x08, 0x22, 0x48, 0x22, 0x80, 0x20, 0x00, 0x00, // 157
1128  0x8a, 0x0c, 0x12, 0x28, 0x02, 0x68, 0x02, 0xa8, 0x10, 0x00, 0x00, 0x00, // 158
1129  0x8b, 0x08, 0x20, 0x88, 0x66, 0x18, 0x20, 0x48, 0x20, 0x80, 0x00, 0x00, // 159
1130  0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 160
1131  0x9a, 0x00, 0x02, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, // 161
1132  0x9a, 0x00, 0x20, 0x40, 0x80, 0x00, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, // 162
1133  0x8b, 0x28, 0x06, 0x38, 0xc0, 0x28, 0x06, 0x38, 0xc0, 0x28, 0x00, 0x00, // 163
1134  0x8a, 0x00, 0x24, 0x10, 0x46, 0x38, 0xc4, 0x10, 0x48, 0x00, 0x00, 0x00, // 164
1135  0x8b, 0x40, 0x82, 0x44, 0x88, 0x10, 0x22, 0x44, 0x82, 0x04, 0x00, 0x00, // 165
1136  0x8b, 0x0c, 0x10, 0x42, 0xa0, 0x12, 0xa8, 0x44, 0x0a, 0x10, 0x00, 0x00, // 166
1137  0xc8, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, // 167
1138  0xba, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, // 168
1139  0x98, 0x00, 0x02, 0x00, 0x04, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, // 169
1140  0x8b, 0x10, 0x04, 0x50, 0x28, 0x10, 0x28, 0x14, 0x40, 0x10, 0x00, 0x00, // 170
1141  0x8b, 0x10, 0x00, 0x14, 0x08, 0x10, 0x20, 0x50, 0x00, 0x10, 0x00, 0x00, // 171
1142  0x29, 0x00, 0x00, 0x01, 0x04, 0x0a, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, // 172
1143  0x8b, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, // 173
1144  0xa8, 0x00, 0x00, 0x02, 0x04, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // 174
1145  0x9a, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, // 175
1146  0x8b, 0x1c, 0x20, 0x42, 0x00, 0x82, 0x00, 0x84, 0x08, 0x70, 0x00, 0x00, // 176
1147  0x99, 0x00, 0x02, 0x00, 0x46, 0x18, 0x62, 0x80, 0x00, 0x00, 0x00, 0x00, // 177
1148  0x8b, 0x02, 0x40, 0x06, 0x80, 0x0a, 0x80, 0x12, 0x80, 0x60, 0x00, 0x00, // 178
1149  0x8b, 0x04, 0x00, 0x82, 0x00, 0x92, 0x00, 0xb2, 0x4c, 0x80, 0x00, 0x00, // 179
1150  0x8b, 0x08, 0x10, 0x08, 0x20, 0x08, 0x46, 0x38, 0xc0, 0x08, 0x00, 0x00, // 180
1151  0x8b, 0x04, 0x60, 0x82, 0x20, 0x82, 0x20, 0x84, 0x18, 0x80, 0x00, 0x00, // 181
1152  0x8a, 0x0c, 0x10, 0x22, 0x10, 0x42, 0x10, 0x82, 0x0c, 0x00, 0x00, 0x00, // 182
1153  0x8b, 0x80, 0x02, 0x84, 0x08, 0x90, 0x20, 0x80, 0x40, 0x80, 0x00, 0x00, // 183
1154  0x8b, 0x0c, 0x62, 0x10, 0x82, 0x10, 0x82, 0x10, 0x8c, 0x60, 0x00, 0x00, // 184
1155  0x8a, 0x60, 0x02, 0x90, 0x04, 0x90, 0x08, 0x90, 0x60, 0x00, 0x00, 0x00, // 185
1156  0xa9, 0x00, 0x00, 0x02, 0x14, 0x22, 0x14, 0x20, 0x00, 0x00, 0x00, 0x00, // 186
1157  0x2a, 0x00, 0x00, 0x01, 0x04, 0x2a, 0x44, 0x28, 0x40, 0x00, 0x00, 0x00, // 187
1158  0x9a, 0x00, 0x10, 0x08, 0x24, 0x02, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, // 188
1159  0x8a, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x00, 0x00, 0x00, // 189
1160  0x9a, 0x00, 0x02, 0x00, 0x04, 0x80, 0x48, 0x20, 0x10, 0x00, 0x00, 0x00, // 190
1161  0x8a, 0x48, 0x02, 0x80, 0x08, 0x80, 0x10, 0x80, 0x60, 0x00, 0x00, 0x00, // 191
1162  0x8b, 0x1c, 0x20, 0x42, 0x80, 0x12, 0x88, 0x22, 0x88, 0x70, 0x00, 0x00, // 192
1163  0x8b, 0x02, 0x04, 0x08, 0x10, 0x28, 0x40, 0x88, 0x00, 0xfe, 0x00, 0x00, // 193
1164  0x8b, 0x06, 0x98, 0x62, 0x80, 0x12, 0x80, 0x12, 0x8c, 0x60, 0x00, 0x00, // 194
1165  0x8b, 0x1c, 0x22, 0x40, 0x82, 0x00, 0x82, 0x00, 0x84, 0x40, 0x00, 0x00, // 195
1166  0x8b, 0x06, 0x98, 0x62, 0x80, 0x02, 0x80, 0x04, 0x88, 0x70, 0x00, 0x00, // 196
1167  0x8b, 0x06, 0x38, 0xc2, 0x10, 0x82, 0x10, 0x82, 0x00, 0x80, 0x00, 0x00, // 197
1168  0x8b, 0x06, 0x38, 0xc0, 0x10, 0x80, 0x10, 0x80, 0x00, 0x80, 0x00, 0x00, // 198
1169  0x8b, 0x1c, 0x22, 0x40, 0x82, 0x00, 0x92, 0x04, 0x98, 0x40, 0x00, 0x00, // 199
1170  0x8b, 0x06, 0x38, 0xc0, 0x10, 0x00, 0x10, 0x06, 0x38, 0xc0, 0x00, 0x00, // 200
1171  0x92, 0x00, 0x02, 0x00, 0x86, 0x18, 0xe2, 0x00, 0x80, 0x00, 0x00, 0x00, // 201
1172  0x8b, 0x0c, 0x02, 0x00, 0x02, 0x80, 0x04, 0x98, 0x60, 0x80, 0x00, 0x00, // 202
1173  0x8b, 0x06, 0x38, 0xc0, 0x10, 0x20, 0x08, 0x44, 0x02, 0x80, 0x00, 0x00, // 203
1174  0x9a, 0x00, 0x06, 0x18, 0x62, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, // 204
1175  0x8b, 0x06, 0x38, 0xc0, 0x00, 0x30, 0x00, 0x46, 0x38, 0xc0, 0x00, 0x00, // 205
1176  0x8b, 0x06, 0x38, 0xc0, 0x20, 0x10, 0x08, 0x06, 0x38, 0xc0, 0x00, 0x00, // 206
1177  0x8b, 0x0c, 0x32, 0x40, 0x82, 0x00, 0x82, 0x04, 0x98, 0x60, 0x00, 0x00, // 207
1178  0x8b, 0x06, 0x18, 0x60, 0x90, 0x00, 0x90, 0x00, 0x90, 0x60, 0x00, 0x00, // 208
1179  0x8b, 0x1c, 0x20, 0x42, 0x00, 0x8a, 0x00, 0x84, 0x0a, 0x70, 0x00, 0x00, // 209
1180  0x8b, 0x06, 0x18, 0x60, 0x80, 0x10, 0x88, 0x14, 0x82, 0x60, 0x00, 0x00, // 210
1181  0x8b, 0x04, 0x62, 0x00, 0x92, 0x00, 0x92, 0x00, 0x8c, 0x40, 0x00, 0x00, // 211
1182  0x8b, 0x80, 0x00, 0x86, 0x18, 0xe0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, // 212
1183  0x8b, 0x0c, 0x32, 0xc0, 0x02, 0x00, 0x02, 0x0c, 0x30, 0xc0, 0x00, 0x00, // 213
1184  0x9b, 0x00, 0xfe, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, // 214
1185  0x8b, 0x06, 0x38, 0xc4, 0x08, 0x10, 0x08, 0x06, 0x38, 0xc0, 0x00, 0x00, // 215
1186  0x8b, 0x02, 0x84, 0x48, 0x20, 0x18, 0x24, 0x02, 0x40, 0x80, 0x00, 0x00, // 216
1187  0x8b, 0x80, 0x40, 0x26, 0x18, 0x00, 0x20, 0x00, 0x40, 0x80, 0x00, 0x00, // 217
1188  0x8b, 0x02, 0x04, 0x8a, 0x00, 0x92, 0x00, 0xa2, 0x40, 0x80, 0x00, 0x00, // 218
1189  0x9b, 0x00, 0x06, 0x18, 0x62, 0x80, 0x02, 0x80, 0x00, 0x80, 0x00, 0x00, // 219
1190  0xa8, 0x00, 0x00, 0xc0, 0x30, 0x0c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 220
1191  0x8a, 0x02, 0x00, 0x02, 0x80, 0x06, 0x98, 0x60, 0x80, 0x00, 0x00, 0x00, // 221
1192  0x9a, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00, // 222
1193  0x0b, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, // 223
1194  0xb7, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 224
1195  0x8a, 0x04, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x24, 0x1a, 0x00, 0x00, 0x00, // 225
1196  0x8a, 0x06, 0x18, 0xe2, 0x00, 0x22, 0x00, 0x24, 0x18, 0x00, 0x00, 0x00, // 226
1197  0x8a, 0x0c, 0x10, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x00, 0x00, 0x00, // 227
1198  0x8b, 0x0c, 0x10, 0x02, 0x20, 0x02, 0x20, 0x06, 0x38, 0xc0, 0x00, 0x00, // 228
1199  0x8a, 0x0c, 0x12, 0x28, 0x02, 0x28, 0x02, 0x28, 0x10, 0x00, 0x00, 0x00, // 229
1200  0x8b, 0x20, 0x00, 0x26, 0x18, 0x60, 0x00, 0xa0, 0x00, 0x80, 0x00, 0x00, // 230
1201  0x1b, 0x00, 0x18, 0x25, 0x00, 0x45, 0x00, 0x46, 0x18, 0x60, 0x00, 0x00, // 231
1202  0x8a, 0x06, 0x18, 0xe0, 0x00, 0x20, 0x00, 0x26, 0x18, 0x00, 0x00, 0x00, // 232
1203  0x99, 0x00, 0x02, 0x00, 0x26, 0x18, 0x22, 0x80, 0x00, 0x00, 0x00, 0x00, // 233
1204  0x89, 0x01, 0x00, 0x01, 0x00, 0x26, 0x18, 0xa0, 0x00, 0x00, 0x00, 0x00, // 234
1205  0x8a, 0x06, 0x18, 0x60, 0x88, 0x04, 0x12, 0x00, 0x20, 0x00, 0x00, 0x00, // 235
1206  0x99, 0x00, 0x02, 0x00, 0x06, 0x98, 0x62, 0x80, 0x00, 0x00, 0x00, 0x00, // 236
1207  0x8a, 0x26, 0x18, 0x20, 0x06, 0x38, 0x00, 0x26, 0x18, 0x00, 0x00, 0x00, // 237
1208  0x89, 0x26, 0x18, 0x20, 0x00, 0x20, 0x06, 0x18, 0x00, 0x00, 0x00, 0x00, // 238
1209  0x8a, 0x0c, 0x12, 0x00, 0x20, 0x02, 0x00, 0x24, 0x18, 0x00, 0x00, 0x00, // 239
1210  0x0a, 0x03, 0x1c, 0x60, 0x04, 0x40, 0x04, 0x48, 0x30, 0x00, 0x00, 0x00, // 240
1211  0x1b, 0x00, 0x18, 0x24, 0x00, 0x44, 0x00, 0x47, 0x18, 0x60, 0x00, 0x00, // 241
1212  0x89, 0x06, 0x38, 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, // 242
1213  0x8a, 0x02, 0x10, 0x02, 0x28, 0x02, 0x28, 0x04, 0x20, 0x00, 0x00, 0x00, // 243
1214  0x9a, 0x00, 0x20, 0x0c, 0x32, 0xc0, 0x22, 0x00, 0x20, 0x00, 0x00, 0x00, // 244
1215  0x8a, 0x0c, 0x32, 0x00, 0x02, 0x00, 0x02, 0x0c, 0x32, 0x00, 0x00, 0x00, // 245
1216  0x9a, 0x00, 0x3e, 0x00, 0x04, 0x00, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, // 246
1217  0x8b, 0x0e, 0x30, 0x04, 0x00, 0x18, 0x04, 0x00, 0x06, 0x38, 0x00, 0x00, // 247
1218  0x8b, 0x02, 0x00, 0x24, 0x10, 0x08, 0x04, 0x12, 0x00, 0x20, 0x00, 0x00, // 248
1219  0x1b, 0x00, 0x40, 0x21, 0x12, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, // 249
1220  0x8b, 0x02, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x20, 0x00, 0x00, // 250
1221  0x9a, 0x00, 0x10, 0x04, 0x1a, 0x60, 0x82, 0x00, 0x80, 0x00, 0x00, 0x00, // 251
1222  0x99, 0x00, 0x02, 0x04, 0x08, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, // 252
1223  0x9a, 0x00, 0x02, 0x00, 0x82, 0x0c, 0xb0, 0x40, 0x10, 0x00, 0x00, 0x00, // 253
1224  0x8b, 0x40, 0x80, 0x00, 0x80, 0x40, 0x20, 0x00, 0x20, 0x40, 0x00, 0x00, // 254
1225  0x8b, 0x1a, 0x24, 0x42, 0x08, 0x92, 0x20, 0x84, 0x48, 0xb0, 0x00, 0x00 // 255
1226 };
1227 
1229  : ImagePrinter(motherBoard, false)
1230 {
1232 }
1233 
1234 const string& ImagePrinterEpson::getName() const
1235 {
1236  static const string name("epson-printer");
1237  return name;
1238 }
1239 
1241 {
1242  return "Emulate Epson FX80 printer, prints to image.";
1243 }
1244 
1245 void ImagePrinterEpson::getNumberOfDots(unsigned& dotsX, unsigned& dotsY)
1246 {
1247  dotsX = 610;
1248  dotsY = 825;
1249 }
1250 
1251 void ImagePrinterEpson::resetSettings()
1252 {
1253  lineFeed = 12.0;
1254  leftBorder = 48;
1255  rightBorder = leftBorder + 480;
1256  graphDensity = 1.0;
1257  fontDensity = 1.0;
1258  pageTop = 48;
1259  lines = 72;
1260  fontWidth = 6;
1261  eightBit = -1;
1262 
1263  memcpy(fontInfo.rom, EpsonFontRom, sizeof(EpsonFontRom));
1264  fontInfo.charWidth = 12;
1265  fontInfo.pixelDelta = 0.5;
1266  fontInfo.useRam = false;
1267 }
1268 
1269 unsigned ImagePrinterEpson::calcEscSequenceLength(byte character)
1270 {
1271  switch (character & 127) {
1272  case '!': case '-': case '/': case '3': case 'A': case 'J':
1273  case 'N': case 'Q': case 'R': case 'S': case 'U': case 'W':
1274  case 'b': case 'i': case 'j': case 'l': case 'p': case 's':
1275  return 1;
1276  case '%': case '?': case 'K': case 'L': case 'Z': case '^':
1277  return 2;
1278  case '*': case ':': case '&':
1279  return 3;
1280  case 'B': // Set tabs, variable length (up to 16 tabs)
1281  return 0;
1282  case 'C': // Set form length, variable length (2 or 3)
1283  return 0;
1284  case 'D': // Set tabs, variable length (up to 32 tabs)
1285  return 0;
1286  default:
1287  return 0;
1288  }
1289 }
1290 
1291 unsigned ImagePrinterEpson::parseNumber(unsigned sizeStart, unsigned sizeChars)
1292 {
1293  unsigned Value = 0;
1294  sizeStart += sizeChars;
1295  while (sizeChars--) {
1296  Value = Value * 256 + abEscSeq[--sizeStart];
1297  }
1298  return Value;
1299 }
1300 
1301 void ImagePrinterEpson::processEscSequence()
1302 {
1303  byte character = abEscSeq[0] & 127;
1304 
1305  switch (character) {
1306  case '!': { // Master Print Mode Select
1307  unsigned masterSelect = parseNumber(1, 1);
1308  elite = (masterSelect & 1) != 0;
1309  compressed = (masterSelect & 4) != 0;
1310  bold = (masterSelect & 8) != 0;
1311  doubleStrike = (masterSelect & 16) != 0;
1312  doubleWidth = (masterSelect & 32) != 0;
1313 
1314  if (elite) {
1315  fontDensity = 1.20;
1316  } else if (compressed) {
1317  fontDensity = 1.72;
1318  } else {
1319  fontDensity = 1.00;
1320  }
1321  break;
1322  }
1323  case '#': // Accept Eight Bit as-is
1324  break;
1325  case '%': // Activates Character Set
1326  fontInfo.useRam = parseNumber(1, 1) & 1;
1327  break;
1328  case '&': // Custom character set, variable length
1329  ramLoadOffset = 12 * parseNumber(2, 1);
1330  ramLoadEnd = 12 * parseNumber(3, 1) + 12;
1331  if (ramLoadEnd <= ramLoadOffset) {
1333  }
1334  break;
1335  case '*': // Turn Graphics Mode ON
1336  ninePinGraphics = false;
1337  switch (parseNumber(1, 1)) {
1338  default:
1339  case 0:
1340  graphDensity = 1.0;
1341  break;
1342  case 1: case 2:
1343  graphDensity = 2.0;
1344  break;
1345  case 3:
1346  graphDensity = 4.0;
1347  break;
1348  case 4:
1349  graphDensity = 1.33;
1350  break;
1351  case 5:
1352  graphDensity = 1.2;
1353  break;
1354  case 6:
1355  graphDensity = 1.5;
1356  break;
1357  }
1358  sizeRemainingDataBytes = parseNumber(2, 2);
1359  break;
1360  case '-': // Turn Underline Mode ON/OFF
1361  underline = parseNumber(1, 1) != 0;
1362  break;
1363  case '/': // Selects Vertical Tab Channel
1364  break;
1365  case '0': // Sets Line Spacing to 1/8 inch
1366  lineFeed = 9.0;
1367  break;
1368  case '1': // Sets Line Spacing to 7/72 inch
1369  lineFeed = 7.0;
1370  break;
1371  case '2': // Sets Line Spacing to 1/6 inch
1372  lineFeed = 12.0;
1373  break;
1374  case '3': // Sets Line Spacing to n/216 inch
1375  lineFeed = (parseNumber(1, 1) & 127) / 3.0;
1376  break;
1377  case '4': // Turn Italic Mode ON
1378  italic = true;
1379  break;
1380  case '5': // Turn Italic Mode OFF
1381  italic = false;
1382  break;
1383  case '6': // Turn Printing of International Italic characters ON
1384  noHighEscapeCodes = true;
1385  break;
1386  case '7': // Turn Printing of International Italic characters OFF
1387  noHighEscapeCodes = false;
1388  break;
1389  case '8': // Turn Paper Out Sensor ON
1390  detectPaperOut = true;
1391  break;
1392  case '9': // Turn Paper Out Sensor OFF
1393  detectPaperOut = false;
1394  break;
1395  case ':': // Copies Rom Character set to RAM
1396  memcpy(fontInfo.ram, fontInfo.rom, sizeof(fontInfo.ram));
1397  break;
1398  case '<': // Turn Uni-directional printing ON (left to right)
1399  leftToRight = true;
1400  break;
1401  case '=': // Sets eight bit to 0
1402  eightBit = 0;
1403  break;
1404  case '>': // Sets eight bit to 1
1405  eightBit = 1;
1406  break;
1407  case '?': // Redefines Graphics Codes
1408  break;
1409  case '@': // Reset
1410  eightBit = -1;
1411  ninePinGraphics = false;
1412  graphDensity = 1.0;
1413  fontDensity = 1.0;
1414  underline = false;
1415  lineFeed = 12.0;
1416  italic = false;
1417  detectPaperOut = false;
1418  leftToRight = false;
1419  doubleStrike = false;
1420  elite = false;
1421  compressed = false;
1422  rightBorder = 6 * 78;
1423  subscript = false;
1424  superscript = false;
1425  doubleWidth = false;
1426  bold = false;
1427  proportional = false;
1428  fontInfo.useRam = false;
1429  noHighEscapeCodes = false;
1430  alternateChar = false;
1431  countryCode = CC_USA;
1432  break;
1433  case 'A': // Sets Line Spacing to n/72 inch
1434  lineFeed = parseNumber(1, 1) & 127;
1435  break;
1436  case 'B': // Set tabs, variable length (up to 16 tabs)
1437  break;
1438  case 'C': // Set form length, variable length (2 or 3)
1439  break;
1440  case 'D': // Set tabs, variable length (up to 32 tabs)
1441  break;
1442  case 'E': // Turn Emphasized Mode ON
1443  bold = true;
1444  break;
1445  case 'F': // Turn Emphasized Mode OFF
1446  bold = false;
1447  break;
1448  case 'G': // Turn Double Strike Mode ON
1449  doubleStrike = true;
1450  break;
1451  case 'H': // Turn Double Strike Mode OFF
1452  doubleStrike = false;
1453  break;
1454  case 'I': // Enables printing of chars 1-31
1455  alternateChar = parseNumber(1, 1) & 1;
1456  break;
1457  case 'J': // Forces Line Feed with n/216 inch
1458  vpos += (parseNumber(1, 1) & 127) / 3.0;
1459  if (vpos >= pageHeight) {
1461  }
1462  break;
1463  case 'K': // Turn Single Density Graphics on (480 dot mode)
1464  graphDensity = 1.0;
1465  ninePinGraphics = false;
1466  sizeRemainingDataBytes = parseNumber(1, 2);
1467  break;
1468  case 'L': // Turn Double Density Graphics on (960 dot mode)
1469  graphDensity = 2.0;
1470  ninePinGraphics = false;
1471  sizeRemainingDataBytes = parseNumber(1, 2);
1472  break;
1473  case 'M': // Turn Elite mode ON
1474  elite = true;
1475  fontDensity = 1.20;
1476  break;
1477  case 'N': // Turn Skip Over Perforation ON
1478  break;
1479  case 'O': // Turn Skip Over Perforation OFF
1480  break;
1481  case 'P': // Turn Elite mode OFF
1482  elite = false;
1483  fontDensity = compressed ? 1.72 : 1.00;
1484  break;
1485  case 'Q': { // Set Right Margin
1486  int width = parseNumber(1, 2);
1487  if (width > 78) width = 78; // FIXME Font dependent !!
1488  rightBorder = 6 * width;
1489  break;
1490  }
1491  case 'R': // Select International Character Set
1492  countryCode = static_cast<CountryCode>(parseNumber(1, 1));
1493  if (countryCode > CC_JAPAN) {
1494  countryCode = CC_USA;
1495  }
1496  break;
1497  case 'S': { // Turn Script Mode ON
1498  int script = parseNumber(1, 1) & 1;
1499  superscript = script == 0;
1500  subscript = script == 1;
1501  break;
1502  }
1503  case 'T': // Turn Script Mode OFF
1504  subscript = false;
1505  superscript = false;
1506  break;
1507  case 'U': // Turn Uni-directional mode ON/OFF
1508  leftToRight = parseNumber(1, 1) != 0;
1509  break;
1510  case 'W': // Turn Expanded Mode ON/OFF
1511  normalAfterLine = false;
1512  doubleWidth = parseNumber(1, 1) != 0;
1513  break;
1514  case 'Y': // Turn High Speed Double Density Graphics ON
1515  break;
1516  case 'Z': // Turns Quadruple Density Graphics ON
1517  graphDensity = 4.0;
1518  ninePinGraphics = false;
1519  sizeRemainingDataBytes = parseNumber(1, 2);
1520  break;
1521  case '^': // Turn Nine Pin Graphics Mode ON
1522  graphDensity = parseNumber(1, 1) ? 2.0 : 1.0;
1523  ninePinGraphics = true;
1524  sizeRemainingDataBytes = 2 * parseNumber(2, 2);
1525  break;
1526  case 'b': // Set Vertical Tab
1527  break;
1528  case 'i': // Turn Immediate Mode ON/OFF
1529  break;
1530  case 'j': // Immediate Reverse Line Feed
1531  vpos -= (parseNumber(1, 1) & 127) / 3.0;
1532  if (vpos < pageTop) {
1533  vpos = pageTop;
1534  }
1535  break;
1536  case 'l': // Set Left Margin
1537  break;
1538  case 'p': // Turn proportional mode ON/OFF
1539  proportional = parseNumber(1, 1) != 0;
1540  break;
1541  case 's': // Set Print Speed
1542  break;
1543  case 127: // Deletes Last Character in Buffer
1544  break;
1545  }
1546 }
1547 
1548 // International character code translation for the Epson FX-80 printer
1549 // US FR DE GB DK SE IT SP JP
1550 static byte intlChar35 [9] = { 35, 35, 35, 6, 35, 35, 35, 12, 35 };
1551 static byte intlChar36 [9] = { 36, 36, 36, 36, 36, 11, 36, 36, 36 };
1552 static byte intlChar64 [9] = { 64, 0, 16, 64, 64, 29, 64, 64, 64 };
1553 static byte intlChar91 [9] = { 91, 5, 23, 91, 18, 23, 5, 7, 91 };
1554 static byte intlChar92 [9] = { 92, 15, 24, 92, 20, 24, 92, 9, 31 };
1555 static byte intlChar93 [9] = { 93, 16, 25, 93, 13, 13, 30, 8, 93 };
1556 static byte intlChar94 [9] = { 94, 94, 94, 94, 94, 25, 94, 94, 94 };
1557 static byte intlChar96 [9] = { 96, 96, 96, 96, 96, 30, 2, 96, 96 };
1558 static byte intlChar123[9] = { 123, 30, 26, 123, 19, 26, 0, 22, 123 };
1559 static byte intlChar124[9] = { 124, 2, 27, 124, 21, 27, 3, 10, 124 };
1560 static byte intlChar125[9] = { 125, 1, 28, 125, 14, 14, 1, 125, 125 };
1561 static byte intlChar126[9] = { 126, 22, 17, 126, 126, 28, 4, 126, 126 };
1562 
1563 void ImagePrinterEpson::processCharacter(byte data)
1564 {
1565  if (data >= 32) {
1566  if (italic) {
1567  data |= 128;
1568  } else {
1569  data &= 127;
1570  }
1571  }
1572 
1573  if (!noHighEscapeCodes && data >= 128 && data < 160) {
1574  data &= 31;
1575  }
1576 
1577  // Convert international characters
1578  switch (data & 0x7f) {
1579  case 35: data = (data & 0x80) | intlChar35 [countryCode]; break;
1580  case 36: data = (data & 0x80) | intlChar36 [countryCode]; break;
1581  case 64: data = (data & 0x80) | intlChar64 [countryCode]; break;
1582  case 91: data = (data & 0x80) | intlChar91 [countryCode]; break;
1583  case 92: data = (data & 0x80) | intlChar92 [countryCode]; break;
1584  case 93: data = (data & 0x80) | intlChar93 [countryCode]; break;
1585  case 94: data = (data & 0x80) | intlChar94 [countryCode]; break;
1586  case 96: data = (data & 0x80) | intlChar96 [countryCode]; break;
1587  case 123: data = (data & 0x80) | intlChar123[countryCode]; break;
1588  case 124: data = (data & 0x80) | intlChar124[countryCode]; break;
1589  case 125: data = (data & 0x80) | intlChar125[countryCode]; break;
1590  case 126: data = (data & 0x80) | intlChar126[countryCode]; break;
1591  }
1592 
1593  if (data >= 32) {
1594  printVisibleCharacter(data);
1595  return;
1596  }
1597 
1598  switch (data) {
1599  case 0: // Terminates horizontal and vertical TAB setting
1600  break;
1601  case 7: // Sound beeper
1602  break;
1603  case 8: // Backspace
1604  // TODO: fix for other font-sizes
1605  hpos -= 8;
1606  if (hpos < leftBorder) {
1607  hpos = leftBorder;
1608  }
1609  break;
1610  case 9: { // Horizontal TAB
1611  // TODO: fix for other font-sizes
1612  hpos = ((unsigned(hpos) + 64 - leftBorder) & ~63)
1613  + leftBorder;
1614  if (hpos < rightBorder) {
1615  break;
1616  }
1617  hpos = leftBorder;
1618  // fall thru: CR/LF
1619  }
1620  case 10: // Line Feed
1621  case 11: // Vertical TAB
1622  vpos += lineFeed;
1623  if (vpos >= pageHeight) {
1625  }
1626  break;
1627  case 12: // Form Feed
1628  ensurePrintPage();
1630  break;
1631  case 13: // Carrige return
1632  hpos = leftBorder;
1633  break;
1634  case 14: // Turns expanded mode ON
1635  doubleWidth = true;
1636  normalAfterLine = true;
1637  break;
1638  case 15: // Shift in. Emties buffer, turns compressed mode ON (17.16 cpi)
1639  compressed = true;
1640  if (!elite) {
1641  fontDensity = 1.72;
1642  }
1643  break;
1644  case 17: // Device Control 1:
1645  break;
1646  case 18: // Device Control 2: turns compressed mode OFF
1647  compressed = false;
1648  fontDensity = 1.00;
1649  break;
1650  case 19: // Device Control 3:
1651  break;
1652  case 20: // Device Control 4: Turns expanded mode OFF
1653  doubleWidth = false;
1654  break;
1655  case 24: // Cancels all text in the print buffer
1656  break;
1657  case 27: // Escape
1658  escSequence = true;
1659  break;
1660  default:
1661  if (alternateChar) {
1662  printVisibleCharacter(data);
1663  }
1664  break;
1665  }
1666 }
1667 
1668 template<typename Archive>
1669 void ImagePrinterEpson::serialize(Archive& /*ar*/, unsigned /*version*/)
1670 {
1671  // TODO is this worth it?
1672 }
1675 
1676 
1677 // class Paper
1678 
1679 Paper::Paper(unsigned x, unsigned y, double dotSizeX, double dotSizeY)
1680  : buf(x * y)
1681  , sizeX(x), sizeY(y)
1682 {
1683  memset(buf.data(), 255, x * y);
1684  setDotSize(dotSizeX, dotSizeY);
1685 }
1686 
1688 {
1689 }
1690 
1691 string Paper::save() const
1692 {
1693  string filename = FileOperations::getNextNumberedFileName(
1694  "prints", "page", ".png");
1695  VLA(const void*, rowPointers, sizeY);
1696  for (unsigned y = 0; y < sizeY; ++y) {
1697  rowPointers[y] = &buf[sizeX * y];
1698  }
1699  PNG::saveGrayscale(sizeX, sizeY, rowPointers, filename);
1700  return filename;
1701 }
1702 
1703 void Paper::setDotSize(double sizeX, double sizeY)
1704 {
1705  radiusX = sizeX / 2.0;
1706  radiusY = sizeY / 2.0;
1707 
1708  int rx = int(16 * radiusX);
1709  int ry = int(16 * radiusY);
1710  radius16 = ry;
1711 
1712  table.clear();
1713  table.resize(2 * (radius16 + 16), -(1 << 30));
1714 
1715  int offset = ry + 16;
1716  int rx2 = 2 * rx * rx;
1717  int ry2 = 2 * ry * ry;
1718 
1719  int x = 0;
1720  int y = ry;
1721  int de_x = ry * ry;
1722  int de_y = (1 - 2 * ry) * rx * rx;
1723  int e = 0;
1724  int sx = 0;
1725  int sy = rx2 * ry;
1726  while (sx <= sy) {
1727  table[offset - y - 1] = x;
1728  table[offset + y ] = x;
1729  x += 1;
1730  sx += ry2;
1731  e += de_x;
1732  de_x += ry2;
1733  if ((2 * e + de_y) > 0) {
1734  y -= 1;
1735  sy -= rx2;
1736  e += de_y;
1737  de_y += rx2;
1738  }
1739  }
1740 
1741  x = rx;
1742  y = 0;
1743  de_x = (1 - 2 * rx) * ry * ry;
1744  de_y = rx * rx;
1745  e = 0;
1746  sx = ry2 * rx;
1747  sy = 0;
1748  while (sy <= sx) {
1749  table[offset - y - 1] = x;
1750  table[offset + y ] = x;
1751  y += 1;
1752  sy += rx2;
1753  e += de_y;
1754  de_y += rx2;
1755  if ((2 * e + de_x) > 0) {
1756  x -= 1;
1757  sx -= ry2;
1758  e += de_x;
1759  de_x += ry2;
1760  }
1761  }
1762 }
1763 
1764 void Paper::plot(double xPos, double yPos)
1765 {
1766  unsigned xx1 = max<int>(int(floor(xPos - radiusX)), 0);
1767  unsigned xx2 = min<int>(int(ceil (xPos + radiusX)), sizeX);
1768  unsigned yy1 = max<int>(int(floor(yPos - radiusY)), 0);
1769  unsigned yy2 = min<int>(int(ceil (yPos + radiusY)), sizeY);
1770 
1771  int y = 16 * yy1 - int(16 * yPos) + 16 + radius16;
1772  for (unsigned yy = yy1; yy < yy2; ++yy) {
1773  int x = 16 * xx1 - int(16 * xPos);
1774  for (unsigned xx = xx1; xx < xx2; ++xx) {
1775  int sum = 0;
1776  for (int i = 0; i < 16; ++i) {
1777  int a = table[y + i];
1778  if (x < -a) {
1779  int t = 16 + a + x;
1780  if (t > 0) {
1781  sum += min(t, 2 * a);
1782  }
1783  } else {
1784  int t = a - x;
1785  if (t > 0) {
1786  sum += min(16, t);
1787  }
1788  }
1789  }
1790  dot(xx, yy) = max(0, dot(xx, yy) - sum);
1791  x += 16;
1792  }
1793  y += 16;
1794  }
1795 }
1796 
1797 byte& Paper::dot(unsigned x, unsigned y)
1798 {
1799  assert(x < sizeX);
1800  assert(y < sizeY);
1801  return buf[y * sizeX + x];
1802 }
1803 
1804 } // namespace openmsx
virtual string_ref getDescription() const
Description for this pluggable.
Definition: Printer.cc:1240
signed char offset
Definition: CPUCore.cc:252
void seekPrinterHeadRelative(double offset)
Definition: Printer.cc:261
Represents something you can plug devices into.
Definition: Connector.hh:21
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer,"CassettePlayer")
void resetEmulatedPrinter()
Definition: Printer.cc:223
virtual void forceFormFeed()=0
virtual bool getStatus(EmuTime::param time)
Returns the STATUS signal: false = low = ready, true = high = not ready.
Definition: Printer.cc:59
byte ram[256 *MAX_FONT_WIDTH]
Definition: Printer.hh:135
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:33
unsigned sizeRemainingDataBytes
Definition: Printer.hh:112
void printGraphicByte(byte data)
Definition: Printer.cc:241
virtual void unplugHelper(EmuTime::param time)
Definition: Printer.cc:83
void printWarning(string_ref message)
Definition: CliComm.cc:28
virtual void plugHelper(Connector &connector, EmuTime::param time)
Definition: Printer.cc:78
virtual void forceFormFeed()
Definition: Printer.cc:218
ImagePrinterEpson(MSXMotherBoard &motherBoard)
Definition: Printer.cc:1228
ImagePrinterMSX(MSXMotherBoard &motherBoard)
Definition: Printer.cc:646
SharedStuff & getSharedStuff(string_ref name)
virtual ~PrinterCore()
Definition: Printer.cc:55
This class implements a subset of the proposal for std::string_ref (proposed for the next c++ standar...
Definition: string_ref.hh:18
void serialize(Archive &ar, unsigned version)
Definition: Printer.cc:959
CountryCode countryCode
Definition: Printer.hh:127
struct openmsx::ImagePrinter::FontInfo fontInfo
void serialize(Archive &ar, unsigned version)
Definition: Printer.cc:1669
virtual void write(byte data)=0
unsigned rightBorder
Definition: Printer.hh:108
virtual unsigned calcEscSequenceLength(byte character)=0
unsigned perforationSkip
Definition: Printer.hh:106
void flushEmulatedPrinter()
Definition: Printer.cc:293
virtual void processCharacter(byte data)=0
A Setting with an integer value.
void setDotSize(double sizeX, double sizeY)
Definition: Printer.cc:1703
const std::string & getMessage() const
Definition: MSXException.hh:14
void printVisibleCharacter(byte data)
Definition: Printer.cc:324
string getNextNumberedFileName(string_ref directory, string_ref prefix, string_ref extension)
Gets the next numbered file name with the specified prefix in the specified directory, with the specified extension.
CommandController & getCommandController()
unsigned remainingCommandBytes
Definition: Printer.hh:110
virtual const std::string & getName() const
Name used to identify this pluggable.
Definition: Printer.cc:653
byte rom[256 *MAX_FONT_WIDTH]
Definition: Printer.hh:134
unsigned ramLoadOffset
Definition: Printer.hh:113
virtual void setStrobe(bool strobe, EmuTime::param time)
Sets the strobe signal: false = low, true = high.
Definition: Printer.cc:64
void saveGrayscale(unsigned width, unsigned height, const void **rowPointers, const std::string &filename)
Definition: PNG.cc:415
Dot Matrix Printer Emulation code mostly copied from blueMSX but changed to: OO-style save to png ima...
void plot9Dots(double x, double y, unsigned pattern)
Definition: Printer.cc:232
std::string save() const
Definition: Printer.cc:1691
virtual const std::string & getName() const
Name used to identify this pluggable.
Definition: Printer.cc:1234
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:802
uint8_t * data()
virtual void write(byte data)
Definition: Printer.cc:183
ImagePrinter(MSXMotherBoard &motherBoard, bool graphicsHiLo)
Definition: Printer.cc:121
virtual void writeData(byte data, EmuTime::param time)
Sets the data signals.
Definition: Printer.cc:73
void plot(double x, double y)
Definition: Printer.cc:1764
void printInfo(string_ref message)
Definition: CliComm.cc:23
virtual void resetSettings()=0
byte reverseByte(byte a)
Reverse the bits in a byte.
Definition: Math.hh:148
virtual void processEscSequence()=0
virtual string_ref getDescription() const
Description for this pluggable.
Definition: Printer.cc:659
virtual void getNumberOfDots(unsigned &dotsX, unsigned &dotsY)=0
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:10
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:94
byte abEscSeq[MAX_ESC_CMDSIZE]
Definition: Printer.hh:130
Paper(unsigned x, unsigned y, double dotSizeX, double dotSizeY)
Definition: Printer.cc:1679