rk86 2.0.6 → 2.0.7
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.
- package/package.json +1 -1
- package/rk86.js +21 -143
package/package.json
CHANGED
package/rk86.js
CHANGED
|
@@ -3103,11 +3103,6 @@ class Screen {
|
|
|
3103
3103
|
static #update_rate = 25;
|
|
3104
3104
|
machine;
|
|
3105
3105
|
cursor_rate;
|
|
3106
|
-
char_width;
|
|
3107
|
-
char_height;
|
|
3108
|
-
char_height_gap;
|
|
3109
|
-
cursor_width;
|
|
3110
|
-
cursor_height;
|
|
3111
3106
|
scale_x;
|
|
3112
3107
|
scale_y;
|
|
3113
3108
|
width;
|
|
@@ -3115,22 +3110,15 @@ class Screen {
|
|
|
3115
3110
|
cursor_state;
|
|
3116
3111
|
cursor_x;
|
|
3117
3112
|
cursor_y;
|
|
3118
|
-
last_cursor_state;
|
|
3119
|
-
last_cursor_x;
|
|
3120
|
-
last_cursor_y;
|
|
3121
|
-
font;
|
|
3122
3113
|
light_pen_x;
|
|
3123
3114
|
light_pen_y;
|
|
3124
3115
|
light_pen_active;
|
|
3125
|
-
|
|
3116
|
+
video_memory_base = 0;
|
|
3117
|
+
video_memory_size = 0;
|
|
3118
|
+
renderer;
|
|
3126
3119
|
constructor(machine) {
|
|
3127
3120
|
this.machine = machine;
|
|
3128
3121
|
this.cursor_rate = 500;
|
|
3129
|
-
this.char_width = 6;
|
|
3130
|
-
this.char_height = 8;
|
|
3131
|
-
this.char_height_gap = 2;
|
|
3132
|
-
this.cursor_width = this.char_width;
|
|
3133
|
-
this.cursor_height = 1;
|
|
3134
3122
|
this.scale_x = 1;
|
|
3135
3123
|
this.scale_y = 1;
|
|
3136
3124
|
this.width = 78;
|
|
@@ -3138,11 +3126,6 @@ class Screen {
|
|
|
3138
3126
|
this.cursor_state = false;
|
|
3139
3127
|
this.cursor_x = 0;
|
|
3140
3128
|
this.cursor_y = 0;
|
|
3141
|
-
this.last_cursor_state = false;
|
|
3142
|
-
this.last_cursor_x = 0;
|
|
3143
|
-
this.last_cursor_y = 0;
|
|
3144
|
-
this.font = new Image;
|
|
3145
|
-
this.font.src = this.machine.font;
|
|
3146
3129
|
this.light_pen_x = 0;
|
|
3147
3130
|
this.light_pen_y = 0;
|
|
3148
3131
|
this.light_pen_active = 0;
|
|
@@ -3183,73 +3166,32 @@ class Screen {
|
|
|
3183
3166
|
this.set_geometry(this.width, this.height);
|
|
3184
3167
|
this.set_video_memory(this.video_memory_base);
|
|
3185
3168
|
}
|
|
3186
|
-
start() {
|
|
3187
|
-
this.
|
|
3188
|
-
this.
|
|
3169
|
+
start(renderer) {
|
|
3170
|
+
this.renderer = renderer;
|
|
3171
|
+
this.renderer.connect(this.machine);
|
|
3189
3172
|
this.flip_cursor();
|
|
3190
|
-
this.
|
|
3191
|
-
this.machine.ui.canvas.onmouseup = () => this.light_pen_active = 0;
|
|
3192
|
-
this.machine.ui.canvas.onmousedown = () => this.light_pen_active = 1;
|
|
3193
|
-
}
|
|
3194
|
-
cache = [];
|
|
3195
|
-
init_cache(sz) {
|
|
3196
|
-
for (let i = 0;i < sz; ++i)
|
|
3197
|
-
this.cache[i] = -1;
|
|
3198
|
-
}
|
|
3199
|
-
draw_char(x, y, ch) {
|
|
3200
|
-
this.ctx.drawImage(this.font, 2, this.char_height * ch, this.char_width, this.char_height, x * this.char_width * this.scale_x, y * (this.char_height + this.char_height_gap) * this.scale_y, this.char_width * this.scale_x, this.char_height * this.scale_y);
|
|
3201
|
-
}
|
|
3202
|
-
draw_cursor(x, y, visible) {
|
|
3203
|
-
const cy = (y2) => (y2 * (this.char_height + this.char_height_gap) + this.char_height) * this.scale_y;
|
|
3204
|
-
if (this.last_cursor_x !== x || this.last_cursor_y !== y) {
|
|
3205
|
-
if (this.last_cursor_state) {
|
|
3206
|
-
this.ctx.fillStyle = "#000000";
|
|
3207
|
-
this.ctx.fillRect(this.last_cursor_x * this.char_width * this.scale_x, cy(this.last_cursor_y), this.cursor_width * this.scale_x, this.cursor_height * this.scale_y);
|
|
3208
|
-
}
|
|
3209
|
-
this.last_cursor_state = this.cursor_state;
|
|
3210
|
-
this.last_cursor_x = x;
|
|
3211
|
-
this.last_cursor_y = y;
|
|
3212
|
-
}
|
|
3213
|
-
const cx = x * this.char_width * this.scale_x;
|
|
3214
|
-
this.ctx.fillStyle = visible ? "#ffffff" : "#000000";
|
|
3215
|
-
this.ctx.fillRect(cx, cy(y), this.cursor_width * this.scale_x, this.cursor_height * this.scale_y);
|
|
3216
|
-
}
|
|
3217
|
-
flip_cursor() {
|
|
3218
|
-
this.draw_cursor(this.cursor_x, this.cursor_y, this.cursor_state);
|
|
3219
|
-
this.cursor_state = !this.cursor_state;
|
|
3220
|
-
setTimeout(() => this.flip_cursor(), this.cursor_rate);
|
|
3221
|
-
}
|
|
3222
|
-
init() {
|
|
3223
|
-
this.ctx = this.machine.ui.canvas.getContext("2d");
|
|
3173
|
+
this.render_loop();
|
|
3224
3174
|
}
|
|
3225
|
-
|
|
3226
|
-
this.
|
|
3175
|
+
render_loop() {
|
|
3176
|
+
this.renderer.update();
|
|
3177
|
+
setTimeout(() => this.render_loop(), Screen.#update_rate);
|
|
3227
3178
|
}
|
|
3228
3179
|
last_width = 0;
|
|
3229
3180
|
last_height = 0;
|
|
3230
|
-
video_memory_size = 0;
|
|
3231
3181
|
set_geometry(width, height) {
|
|
3232
3182
|
this.width = width;
|
|
3233
3183
|
this.height = height;
|
|
3234
3184
|
this.video_memory_size = width * height;
|
|
3235
3185
|
this.machine.ui.update_screen_geometry(this.width, this.height);
|
|
3236
|
-
const canvas_width = this.width * this.char_width * this.scale_x;
|
|
3237
|
-
const canvas_height = this.height * (this.char_height + this.char_height_gap) * this.scale_y;
|
|
3238
|
-
this.machine.ui.resize_canvas(canvas_width, canvas_height);
|
|
3239
|
-
this.disable_smoothing();
|
|
3240
|
-
this.ctx.fillStyle = "#000000";
|
|
3241
|
-
this.ctx.fillRect(0, 0, canvas_width, canvas_height);
|
|
3242
3186
|
if (this.last_width === this.width && this.last_height === this.height)
|
|
3243
3187
|
return;
|
|
3244
3188
|
console.log(`\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D \u0440\u0430\u0437\u043C\u0435\u0440 \u044D\u043A\u0440\u0430\u043D\u0430: ${width} x ${height}`);
|
|
3245
3189
|
this.last_width = this.width;
|
|
3246
3190
|
this.last_height = this.height;
|
|
3247
3191
|
}
|
|
3248
|
-
video_memory_base = 0;
|
|
3249
3192
|
last_video_memory_base = 0;
|
|
3250
3193
|
set_video_memory(base) {
|
|
3251
3194
|
this.video_memory_base = base;
|
|
3252
|
-
this.init_cache(this.video_memory_size);
|
|
3253
3195
|
this.machine.ui.update_video_memory_address(this.video_memory_base);
|
|
3254
3196
|
if (this.last_video_memory_base === this.video_memory_base)
|
|
3255
3197
|
return;
|
|
@@ -3257,37 +3199,12 @@ class Screen {
|
|
|
3257
3199
|
this.last_video_memory_base = this.video_memory_base;
|
|
3258
3200
|
}
|
|
3259
3201
|
set_cursor(x, y) {
|
|
3260
|
-
this.draw_cursor(this.cursor_x, this.cursor_y, false);
|
|
3261
3202
|
this.cursor_x = x;
|
|
3262
3203
|
this.cursor_y = y;
|
|
3263
3204
|
}
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
for (let y = 0;y < this.height; ++y) {
|
|
3268
|
-
for (let x = 0;x < this.width; ++x) {
|
|
3269
|
-
const cache_i = i - this.video_memory_base;
|
|
3270
|
-
const ch = memory.read(i);
|
|
3271
|
-
if (this.cache[cache_i] !== ch) {
|
|
3272
|
-
this.draw_char(x, y, ch);
|
|
3273
|
-
this.cache[cache_i] = ch;
|
|
3274
|
-
}
|
|
3275
|
-
i += 1;
|
|
3276
|
-
}
|
|
3277
|
-
}
|
|
3278
|
-
setTimeout(() => this.draw_screen(), Screen.#update_rate);
|
|
3279
|
-
}
|
|
3280
|
-
handle_mousemove(event) {
|
|
3281
|
-
const canvas = this.machine.ui.canvas;
|
|
3282
|
-
const box = canvas.getBoundingClientRect();
|
|
3283
|
-
const scaleX = canvas.width / box.width;
|
|
3284
|
-
const scaleY = canvas.height / box.height;
|
|
3285
|
-
const mouseX = (event.clientX - box.left) * scaleX;
|
|
3286
|
-
const mouseY = (event.clientY - box.top) * scaleY;
|
|
3287
|
-
const x = Math.floor(mouseX / (this.char_width * this.scale_x));
|
|
3288
|
-
const y = Math.floor(mouseY / ((this.char_height + this.char_height_gap) * this.scale_y));
|
|
3289
|
-
this.light_pen_x = x;
|
|
3290
|
-
this.light_pen_y = y;
|
|
3205
|
+
flip_cursor() {
|
|
3206
|
+
this.cursor_state = !this.cursor_state;
|
|
3207
|
+
setTimeout(() => this.flip_cursor(), this.cursor_rate);
|
|
3291
3208
|
}
|
|
3292
3209
|
}
|
|
3293
3210
|
|
|
@@ -3393,8 +3310,6 @@ class Tape {
|
|
|
3393
3310
|
}
|
|
3394
3311
|
|
|
3395
3312
|
// src/lib/rk86_terminal.ts
|
|
3396
|
-
globalThis.Image = class {
|
|
3397
|
-
};
|
|
3398
3313
|
var charMap = {
|
|
3399
3314
|
0: " ",
|
|
3400
3315
|
1: "\u2598",
|
|
@@ -3560,35 +3475,25 @@ class IO {
|
|
|
3560
3475
|
interrupt = (_iff) => {};
|
|
3561
3476
|
}
|
|
3562
3477
|
|
|
3563
|
-
class
|
|
3478
|
+
class TerminalRenderer {
|
|
3564
3479
|
machine;
|
|
3565
|
-
|
|
3566
|
-
height = 30;
|
|
3567
|
-
video_memory_base = 0;
|
|
3568
|
-
timer;
|
|
3569
|
-
constructor(machine) {
|
|
3480
|
+
connect(machine) {
|
|
3570
3481
|
this.machine = machine;
|
|
3571
3482
|
}
|
|
3572
|
-
|
|
3573
|
-
this.render();
|
|
3574
|
-
}
|
|
3575
|
-
render() {
|
|
3483
|
+
update() {
|
|
3576
3484
|
const { memory, screen } = this.machine;
|
|
3577
|
-
const cursorX = screen.cursor_x;
|
|
3578
|
-
const cursorY = screen.cursor_y;
|
|
3579
|
-
const cursorVisible = screen.cursor_state;
|
|
3580
3485
|
const dim = "\x1B[2m";
|
|
3581
3486
|
const reset = "\x1B[0m";
|
|
3582
|
-
const w =
|
|
3487
|
+
const w = screen.width;
|
|
3583
3488
|
let output = "\x1B[H";
|
|
3584
3489
|
output += `${dim}\u250C${"\u2500".repeat(w)}\u2510${reset}
|
|
3585
3490
|
`;
|
|
3586
|
-
let addr =
|
|
3587
|
-
for (let y = 0;y <
|
|
3491
|
+
let addr = screen.video_memory_base;
|
|
3492
|
+
for (let y = 0;y < screen.height; y++) {
|
|
3588
3493
|
let line = `${dim}\u2502${reset}`;
|
|
3589
3494
|
for (let x = 0;x < w; x++) {
|
|
3590
3495
|
const ch = rk86char(memory.read(addr));
|
|
3591
|
-
if (x ===
|
|
3496
|
+
if (x === screen.cursor_x && y === screen.cursor_y) {
|
|
3592
3497
|
line += `\x1B[4m${ch}${reset}`;
|
|
3593
3498
|
} else {
|
|
3594
3499
|
line += ch;
|
|
@@ -3602,7 +3507,6 @@ class TerminalScreen {
|
|
|
3602
3507
|
output += `${dim}\u2514${"\u2500".repeat(w)}\u2518${reset}
|
|
3603
3508
|
`;
|
|
3604
3509
|
process.stdout.write(output);
|
|
3605
|
-
this.timer = setTimeout(() => this.render(), 40);
|
|
3606
3510
|
}
|
|
3607
3511
|
}
|
|
3608
3512
|
var KEY_MAP = {
|
|
@@ -3788,34 +3692,8 @@ async function main() {
|
|
|
3788
3692
|
process.stdout.write("\x1B[?25l");
|
|
3789
3693
|
process.stdout.write("\x1B[2J");
|
|
3790
3694
|
setupKeyboard(keyboard);
|
|
3791
|
-
|
|
3792
|
-
const origSetGeometry = machine.screen.set_geometry.bind(machine.screen);
|
|
3793
|
-
machine.screen.set_geometry = (width, height) => {
|
|
3794
|
-
origSetGeometry(width, height);
|
|
3795
|
-
termScreen.width = width;
|
|
3796
|
-
termScreen.height = height;
|
|
3797
|
-
};
|
|
3798
|
-
const origSetVideoMemory = machine.screen.set_video_memory.bind(machine.screen);
|
|
3799
|
-
machine.screen.set_video_memory = (base) => {
|
|
3800
|
-
origSetVideoMemory(base);
|
|
3801
|
-
termScreen.video_memory_base = base;
|
|
3802
|
-
};
|
|
3803
|
-
const noopCtx = {
|
|
3804
|
-
imageSmoothingEnabled: false,
|
|
3805
|
-
fillStyle: "",
|
|
3806
|
-
fillRect() {},
|
|
3807
|
-
drawImage() {},
|
|
3808
|
-
clearRect() {}
|
|
3809
|
-
};
|
|
3810
|
-
machine.screen.ctx = noopCtx;
|
|
3811
|
-
machine.screen.init = () => {
|
|
3812
|
-
machine.screen.ctx = noopCtx;
|
|
3813
|
-
};
|
|
3814
|
-
machine.screen.draw_screen = () => {};
|
|
3815
|
-
machine.screen.draw_cursor = () => {};
|
|
3816
|
-
machine.screen.start();
|
|
3695
|
+
machine.screen.start(new TerminalRenderer);
|
|
3817
3696
|
machine.runner.execute();
|
|
3818
|
-
termScreen.start();
|
|
3819
3697
|
if (entryPoint !== undefined && !loadOnly) {
|
|
3820
3698
|
setTimeout(() => machine.cpu.jump(entryPoint), 500);
|
|
3821
3699
|
}
|