rk86 2.0.25 → 2.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/rk86.js +102 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rk86",
3
- "version": "2.0.25",
3
+ "version": "2.0.26",
4
4
  "description": "Эмулятор Радио-86РК (Intel 8080) для терминала",
5
5
  "bin": {
6
6
  "rk86": "rk86.js"
package/rk86.js CHANGED
@@ -2951,6 +2951,18 @@ var init_catalog_data = __esm(() => {
2951
2951
  checkSum: 64981,
2952
2952
  leadingE6: false
2953
2953
  },
2954
+ {
2955
+ name: "mon32-trans.bin",
2956
+ title: "\u041C\u043E\u043D\u0438\u0442\u043E\u0440 32\u041A\u0411 \u0441 \u0432\u043A\u043B\u044E\u0447\u0451\u043D\u043D\u044B\u043C transparent field-attribute mode (i8275 reset byte 4 = 0x93). \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u0434\u043B\u044F \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043D\u043D\u044B\u0445 \u043D\u0430 \u044D\u0442\u043E\u0442 \u0440\u0435\u0436\u0438\u043C (`tree2025.rk`). \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 URL-\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 `?monitor=mon32-trans.bin`.",
2957
+ description: "",
2958
+ screenshots: [],
2959
+ start: 0,
2960
+ end: 2047,
2961
+ size: 2048,
2962
+ entry: 0,
2963
+ checkSum: 4565,
2964
+ leadingE6: false
2965
+ },
2954
2966
  {
2955
2967
  name: "mon32.bin",
2956
2968
  title: '\u041E\u0440\u0438\u0433\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0439 <a href="https://github.com/begoon/rk86-maximite/blob/master/monitor/monitor32.asm">\u041C\u043E\u043D\u0438\u0442\u043E\u0440 32\u041A\u0411</a>',
@@ -2960,7 +2972,7 @@ var init_catalog_data = __esm(() => {
2960
2972
  end: 2047,
2961
2973
  size: 2048,
2962
2974
  entry: 0,
2963
- checkSum: 4565,
2975
+ checkSum: 21013,
2964
2976
  leadingE6: false
2965
2977
  },
2966
2978
  {
@@ -4083,7 +4095,7 @@ import { basename } from "path";
4083
4095
  // packages/rk86/package.json
4084
4096
  var package_default = {
4085
4097
  name: "rk86",
4086
- version: "2.0.24",
4098
+ version: "2.0.25",
4087
4099
  description: "\u042D\u043C\u0443\u043B\u044F\u0442\u043E\u0440 \u0420\u0430\u0434\u0438\u043E-86\u0420\u041A (Intel 8080) \u0434\u043B\u044F \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0430",
4088
4100
  bin: {
4089
4101
  rk86: "rk86.js"
@@ -5427,6 +5439,7 @@ class Memory {
5427
5439
  this.video_screen_size_y = this.video_screen_size_y_buf;
5428
5440
  this.machine.screen.set_geometry(this.video_screen_size_x, this.video_screen_size_y);
5429
5441
  }
5442
+ this.machine.screen.transparent_attr = (byte & 64) === 0;
5430
5443
  return;
5431
5444
  }
5432
5445
  if (vt57_reg === 57352 && byte === 128) {
@@ -5634,6 +5647,7 @@ class Screen {
5634
5647
  light_pen_active;
5635
5648
  video_memory_base = 0;
5636
5649
  video_memory_size = 0;
5650
+ transparent_attr = false;
5637
5651
  ready = false;
5638
5652
  renderer;
5639
5653
  constructor(machine) {
@@ -6056,36 +6070,104 @@ class TerminalRenderer {
6056
6070
  const dim = "\x1B[2m";
6057
6071
  const reset = "\x1B[0m";
6058
6072
  const w = screen.width;
6073
+ const ANSI_FG = ["37", "33", "35", "31", "36", "32", "34", "30"];
6059
6074
  let output = "\x1B[H";
6060
6075
  output += `${dim}\u250C${"\u2500".repeat(w)}\u2510${reset}
6061
6076
  `;
6077
+ const transparent = screen.transparent_attr;
6078
+ const blinkOff = Math.floor(Date.now() / 320) % 2 === 1;
6079
+ const FA_PENDING = -1;
6062
6080
  let addr = screen.video_memory_base;
6063
6081
  let frameStopped = false;
6082
+ let color = 0;
6083
+ let blink = false;
6064
6084
  for (let y = 0;y < screen.height; y++) {
6065
6085
  let line = `${dim}\u2502${reset}`;
6066
- let rowStopped = frameStopped;
6086
+ const cells = new Array(w);
6087
+ if (transparent) {
6088
+ const fifo = [];
6089
+ let fifoFlag = false;
6090
+ let cellCount = 0;
6091
+ let rowStopped = frameStopped;
6092
+ let bytesFetched = 0;
6093
+ while (cellCount < w && !rowStopped) {
6094
+ const raw = memory.read(addr + bytesFetched);
6095
+ bytesFetched++;
6096
+ if (fifoFlag) {
6097
+ fifo.push(raw);
6098
+ fifoFlag = false;
6099
+ continue;
6100
+ }
6101
+ if (raw >= 240) {
6102
+ cells[cellCount++] = { ch: 0, color, blink };
6103
+ rowStopped = true;
6104
+ if (raw >= 248)
6105
+ frameStopped = true;
6106
+ } else if (raw >= 192) {
6107
+ cells[cellCount++] = { ch: 0, color, blink };
6108
+ } else if (raw >= 128) {
6109
+ color = (raw & 1) << 2 | (raw & 12) >> 2;
6110
+ blink = (raw & 2) !== 0;
6111
+ cells[cellCount++] = { ch: FA_PENDING, color, blink };
6112
+ fifoFlag = true;
6113
+ } else {
6114
+ cells[cellCount++] = { ch: raw, color, blink };
6115
+ }
6116
+ }
6117
+ while (cellCount < w)
6118
+ cells[cellCount++] = { ch: 0, color, blink };
6119
+ let fifoIdx = 0;
6120
+ for (let x = 0;x < w; ++x) {
6121
+ if (cells[x].ch === FA_PENDING) {
6122
+ cells[x].ch = (fifo[fifoIdx] ?? 0) & 127;
6123
+ fifoIdx++;
6124
+ }
6125
+ }
6126
+ addr += bytesFetched;
6127
+ if (addr - screen.video_memory_base < (y + 1) * w) {
6128
+ addr = screen.video_memory_base + (y + 1) * w;
6129
+ }
6130
+ } else {
6131
+ let rowStopped = frameStopped;
6132
+ for (let x = 0;x < w; x++) {
6133
+ const raw = memory.read(addr + x);
6134
+ let ch;
6135
+ if (rowStopped) {
6136
+ ch = 0;
6137
+ } else if (raw >= 240) {
6138
+ ch = 0;
6139
+ rowStopped = true;
6140
+ if (raw >= 248)
6141
+ frameStopped = true;
6142
+ } else if (raw >= 192) {
6143
+ ch = 0;
6144
+ } else if (raw >= 128) {
6145
+ color = (raw & 1) << 2 | (raw & 12) >> 2;
6146
+ blink = (raw & 2) !== 0;
6147
+ ch = 0;
6148
+ } else {
6149
+ ch = raw;
6150
+ }
6151
+ cells[x] = { ch, color, blink };
6152
+ }
6153
+ addr += w;
6154
+ }
6155
+ let prevColor = -1;
6067
6156
  for (let x = 0;x < w; x++) {
6068
- const raw = memory.read(addr++);
6069
- let ch;
6070
- if (rowStopped) {
6071
- ch = " ";
6072
- } else if (raw >= 240) {
6073
- ch = " ";
6074
- rowStopped = true;
6075
- if (raw >= 248)
6076
- frameStopped = true;
6077
- } else if (raw >= 128) {
6078
- ch = " ";
6079
- } else {
6080
- ch = rk86char(raw);
6157
+ const cell = cells[x];
6158
+ const ch = cell.blink && blinkOff ? 0 : cell.ch;
6159
+ const glyph = rk86char(ch);
6160
+ if (cell.color !== prevColor) {
6161
+ line += `\x1B[${ANSI_FG[cell.color]}m`;
6162
+ prevColor = cell.color;
6081
6163
  }
6082
6164
  if (x === screen.cursor_x && y === screen.cursor_y) {
6083
- line += `\x1B[4m${ch}${reset}`;
6165
+ line += `\x1B[4m${glyph}\x1B[24m`;
6084
6166
  } else {
6085
- line += ch;
6167
+ line += glyph;
6086
6168
  }
6087
6169
  }
6088
- line += `${dim}\u2502${reset}`;
6170
+ line += `${reset}${dim}\u2502${reset}`;
6089
6171
  output += line + `
6090
6172
  `;
6091
6173
  }
@@ -6210,7 +6292,7 @@ function setupKeyboard(keyboard) {
6210
6292
  }
6211
6293
  });
6212
6294
  }
6213
- var MON32_B64 = "wzb4w2P+w5j7w7r8w0b8w7r8wwH+w6X8wyL5w3L+w3v6w3/6w7b6w0n7wxb7w876" + "w1L/w1b/PooyA4Axz3bNzvohAHYRX3YOAM3t+SHPdiIcdiFa/80i+c3O+iH/dSIx" + "diEqHSIvdj7DMiZ2Mc92IWb/zSL5MgKAPTICoM3u+CFs+OUhM3Z+/ljK0//+VcoA" + "8PXNLPkqK3ZNRCopdusqJ3bx/kTKxfn+Q8rX+f5Gyu35/lPK9Pn+VMr/+f5Nyib6" + "/kfKP/r+ScqG+v5Pyi37/kzKCPr+Uspo+sMA8D4zvcrx+OUhnv/NIvnhK8Pz+CEz" + "dgYAzWP+/gjK3Pj+f8rc+MS5/Hf+Dcoa+f4uymz4Bv8+Ur3Krvojw/P4eBcRM3YG" + "AMl+p8jNufwjwyL5ISd2ES12DgDN7fkRNHbNWvkiJ3YiKXbYPv8yLXbNWvkiKXbY" + "zVr5Iit22MOu+iEAABoT/g3Kjvn+LMj+IMpd+dYw+q76/gr6gvn+Efqu+v4X8q76" + "1gdPKSkpKdqu+gnDXfk3yXy6wH27yc2k+c2Q+cKi+TMzySPJzXL+/gPAzc76w676" + "5SFs/80i+eHJfsXNpfw+IM25/MHJzXj7zbn5zZb5feYPysX5w8j5Cr7K5vnNePvN" + "ufkKzbr5A82W+cPX+XHNmfnD7fl5vsx4+82W+cP0+X4CA82Z+cP/+c14+363+hX6" + "/iDSF/o+Ls25/M2W+X3mD8oI+sML+s14+825+eXN7vjh0jv65c1a+X3hdyPDJvrN" + "kPnKWvrrIiN2fjIldjb3PsMyMAAhov8iMQAxGHbB0eHx+SoWdsMmdj6QMgOgIgGg" + "OgCgAgPNmfnDbfoqAnbJ5SoAdn7hyTotdrfKkfp7Mi92zbb6zXj76814++vFzRb7" + "YGnNePvRzZD5yOvNePs+P825/MNs+D7/zf/65Qnrzf364Qnr5c0K+z7/zf/64eUh" + "AcA2ACs2TTYdNpk2kyM2J35+5iDK4fohCOA2gC4ENtA2diw2IzZJLgg2pOHJPgjN" + "mPtHPgjNmPtPyT4IzZj7d82Z+cMK+wEAAH6BT/XNkPnKn/nxeI5HzZn5wxn7ebfK" + "NfsyMHblzRb74c14++vNePvr5WBpzXj74cUBAADNRvwF4+PCTfsO5s1G/M2Q++vN" + "kPvrzYb7IQAAzZD7DubNRvzhzZD7w876xc2w+XzNpfx9zbr5wclOzUb8zZn5w4b7" + "TM1G/E3DRvzlxdVXPoAyCOAhAAA5MQAAIg12DgA6AoAPDw8P5gFf8XnmfwdPJgAl" + "yjT88ToCgA8PDw/mAbvKv/uxTxU6L3bC3PvWEkfxBcLd+xQ6AoAPDw8P5gFferf" + "yC/x5/ubC//uvMi52wwn8/hnCt/s+/zIudhYJFcK3+yEE4DbQNnYjNiM2ST4nMgH" + "APuAyAcAuCDakKg12+ToudqnDofwqDXb5zc76erfyrvrNpPnDnPvlxdX1PoAyCOAh" + "AAA5MQAAFgjxeQdPPgGpMgKAOjB2R/EFwmb8PgCpMgKAFTowdsJ6/NYOR/EFwnv8" + "FBXCWPz5IQTgNtA2diM2IzZJPicyAcA+4DIBwC4INqTx0cHhyfUPDw8Pza788eYP" + "/gr6t/zGB8YwT/XF1eXNAf4hhf3lKgJ26yoAdjoEdj367vzKZf3ic/151iBPDfrp/" + "MXNuf3Bw938rzIEdsl55n9P/h/Ko/3+DMqy/f4NyvP9/grKR/3+CMrW/f4Yyrn9/h" + "nK4v3+GsrF/f4byp79/gfCOP0B8AV4+z3CKP148z3CLv0Nwif9yXHNuf16/gPAe/" + "4IwM3i/Xr+G8LF/eXVIcJ3ERB4AZ4HGncjEwt5sMJY/dHhyXn+WcLp/M2y/T4C" + "w+r8edYgTw0+BPrq/MXNxf3Bw3f9IgB26yICdj6AMgHAfTIAwHwyAMDh0cHxyT4B" + "w+r8IfR/ESUJr3crG3uywqn9EQgDIcJ3yXsjHP5HwB4IAcD/CXr+GwFOAMLT/RYC" + "AbD4FAnJeysd/gjAHkcBQAAJev4DAbL/wvD9FhwBUAcVCcl9k9L5/SVvHggBCAAJ" + "yToCgOaAyg7+OgV2t8DlKgl2zXL+vW/KKv4+ATILdiYVryIJduEyBXbJJcIh/jzK" + "Iv48ylH+xQEDUM0n/cE6C3Ym4D0yC3bKTP4mQD7/wyL+OgKA5oDKUf46BnYvMgZ2" + "wxr+zQH+t8pj/q8yBXY6CXbJOgKA5oDCff4+/smvMgCAMgKAOgZ25gH2BjIDgDoB" + "gDzCl/49yeUuASYHfQ9vLzIAgDoBgC+3wrP+JfKc/j7/4ckuIDoBgC+3yq/+LcK1" + "/i4ILQfSw/58ZW/+Acr6/trz/gcHB8YgtP5fwgb/PiDhyQkKDX8IGRgaDB8bAAEC" + "AwQFfCHq/sP+/nwh4v6Fb37+QOHY5W86AoBn5kDCGv99/kD6P//mH+HJOgZ2t8oq" + "/33+QPoq//Ygb3zmIMI//33+QPo7/33uIOHJfeYvb33+QOHw5W/mD/4MffpQ/+4Q" + "4ckqMXbJIjF2yR9yYWRpby04NnJrAA0KLS0+AA0KGBgYGAANCiBQQy0NCiBITC0N" + "CiBCQy0NCiBERS0NCiBTUC0NCiBBRi0ZGRkZGRkACCAIACIWdvXhIh524SsiFHYh" + "AAA5MR525dXFKhR2Mc92zXj76yojds2Q+cJs+DoldnfDbPghc//NIvkhFHYGBl4j" + "VsXl6814+83u+NL2/81a+dHV63Irc+HBBSPC3v/J//8=";
6295
+ var MON32_B64 = "wzb4w2P+w5j7w7r8w0b8w7r8wwH+w6X8wyL5w3L+w3v6w3/6w7b6w0n7wxb7" + "w876w1L/w1b/PooyA4Axz3bNzvohAHYRX3YOAM3t+SHPdiIcdiFa/80i+c3O" + "+iH/dSIxdiEqHSIvdj7DMiZ2Mc92IWb/zSL5MgKAPTICoM3u+CFs+OUhM3Z+" + "/ljK0//+VcoA8PXNLPkqK3ZNRCopdusqJ3bx/kTKxfn+Q8rX+f5Gyu35/lPK" + "9Pn+VMr/+f5Nyib6/kfKP/r+ScqG+v5Pyi37/kzKCPr+Uspo+sMA8D4zvcrx" + "+OUhnv/NIvnhK8Pz+CEzdgYAzWP+/gjK3Pj+f8rc+MS5/Hf+Dcoa+f4uymz4" + "Bv8+Ur3Krvojw/P4eBcRM3YGAMl+p8jNufwjwyL5ISd2ES12DgDN7fkRNHbN" + "WvkiJ3YiKXbYPv8yLXbNWvkiKXbYzVr5Iit22MOu+iEAABoT/g3Kjvn+LMj+" + "IMpd+dYw+q76/gr6gvn+Efqu+v4X8q761gdPKSkpKdqu+gnDXfk3yXy6wH27" + "yc2k+c2Q+cKi+TMzySPJzXL+/gPAzc76w6765SFs/80i+eHJfsXNpfw+IM25" + "/MHJzXj7zbn5zZb5feYPysX5w8j5Cr7K5vnNePvNufkKzbr5A82W+cPX+XHN" + "mfnD7fl5vsx4+82W+cP0+X4CA82Z+cP/+c14+363+hX6/iDSF/o+Ls25/M2W" + "+X3mD8oI+sML+s14+825+eXN7vjh0jv65c1a+X3hdyPDJvrNkPnKWvrrIiN2" + "fjIldjb3PsMyMAAhov8iMQAxGHbB0eHx+SoWdsMmdj6QMgOgIgGgOgCgAgPN" + "mfnDbfoqAnbJ5SoAdn7hyTotdrfKkfp7Mi92zbb6zXj76814++vFzRb7YGnN" + "ePvRzZD5yOvNePs+P825/MNs+D7/zf/65Qnrzf364Qnr5c0K+z7/zf/64eUh" + "AcA2ACs2TTYdNpk2kyM2J35+5iDK4fohCOA2gC4ENtA2diw2IzZJLgg2pOHJ" + "PgjNmPtHPgjNmPtPyT4IzZj7d82Z+cMK+wEAAH6BT/XNkPnKn/nxeI5HzZn5" + "wxn7ebfKNfsyMHblzRb74c14++vNePvr5WBpzXj74cUBAADNRvwF4+PCTfsO" + "5s1G/M2Q++vNkPvrzYb7IQAAzZD7DubNRvzhzZD7w876xc2w+XzNpfx9zbr5" + "wclOzUb8zZn5w4b7TM1G/E3DRvzlxdVXPoAyCOAhAAA5MQAAIg12DgA6AoAP" + "Dw8P5gFf8XnmfwdPJgAlyjT88ToCgA8PDw/mAbvKv/uxTxU6L3bC3PvWEkfx" + "BcLd+xQ6AoAPDw8P5gFferfyC/x5/ubC//uvMi52wwn8/hnCt/s+/zIudhYJ" + "FcK3+yEE4DbQNnYjNiM2ST4nMgHAPuAyAcAuCDakKg12+ToudqnDofwqDXb5" + "zc76erfyrvrNpPnDnPvlxdX1PoAyCOAhAAA5MQAAFgjxeQdPPgGpMgKAOjB2" + "R/EFwmb8PgCpMgKAFTowdsJ6/NYOR/EFwnv8FBXCWPz5IQTgNtA2diM2IzZJ" + "PicyAcA+4DIBwC4INqTx0cHhyfUPDw8Pza788eYP/gr6t/zGB8YwT/XF1eXN" + "Af4hhf3lKgJ26yoAdjoEdj367vzKZf3ic/151iBPDfrp/MXNuf3Bw938rzIE" + "dsl55n9P/h/Ko/3+DMqy/f4NyvP9/grKR/3+CMrW/f4Yyrn9/hnK4v3+GsrF" + "/f4byp79/gfCOP0B8AV4+z3CKP148z3CLv0Nwif9yXHNuf16/gPAe/4IwM3i" + "/Xr+G8LF/eXVIcJ3ERB4AZ4HGncjEwt5sMJY/dHhyXn+WcLp/M2y/T4Cw+r8" + "edYgTw0+BPrq/MXNxf3Bw3f9IgB26yICdj6AMgHAfTIAwHwyAMDh0cHxyT4B" + "w+r8IfR/ESUJr3crG3uywqn9EQgDIcJ3yXsjHP5HwB4IAcD/CXr+GwFOAMLT" + "/RYCAbD4FAnJeysd/gjAHkcBQAAJev4DAbL/wvD9FhwBUAcVCcl9k9L5/SVv" + "HggBCAAJyToCgOaAyg7+OgV2t8DlKgl2zXL+vW/KKv4+ATILdiYVryIJduEy" + "BXbJJcIh/jzKIv48ylH+xQEDUM0n/cE6C3Ym4D0yC3bKTP4mQD7/wyL+OgKA" + "5oDKUf46BnYvMgZ2wxr+zQH+t8pj/q8yBXY6CXbJOgKA5oDCff4+/smvMgCA" + "MgKAOgZ25gH2BjIDgDoBgDzCl/49yeUuASYHfQ9vLzIAgDoBgC+3wrP+JfKc" + "/j7/4ckuIDoBgC+3yq/+LcK1/i4ILQfSw/58ZW/+Acr6/trz/gcHB8YgtP5f" + "wgb/PiDhyQkKDX8IGRgaDB8bAAECAwQFfCHq/sP+/nwh4v6Fb37+QOHY5W86" + "AoBn5kDCGv99/kD6P//mH+HJOgZ2t8oq/33+QPoq//Ygb3zmIMI//33+QPo7" + "/33uIOHJfeYvb33+QOHw5W/mD/4MffpQ/+4Q4ckqMXbJIjF2yR9yYWRpby04" + "NnJrAA0KLS0+AA0KGBgYGAANCiBQQy0NCiBITC0NCiBCQy0NCiBERS0NCiBT" + "UC0NCiBBRi0ZGRkZGRkACCAIACIWdvXhIh524SsiFHYhAAA5MR525dXFKhR2" + "Mc92zXj76yojds2Q+cJs+DoldnfDbPghc//NIvkhFHYGBl4jVsXl6814+83u" + "+NL2/81a+dHV63Irc+HBBSPC3v/J//8=";
6214
6296
  function decodeMon32() {
6215
6297
  return Array.from(new Uint8Array(Uint8Array.from(atob(MON32_B64), (c) => c.charCodeAt(0))));
6216
6298
  }