Skip to content

Commit a9eb0ed

Browse files
committed
Separate Beebjit call
1 parent b56e096 commit a9eb0ed

File tree

4 files changed

+107
-100
lines changed

4 files changed

+107
-100
lines changed

beebjit.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
const fs = require('fs');
2+
3+
function exec(cmd) {
4+
const exec = require('child_process').exec;
5+
return new Promise((resolve, reject) => {
6+
exec(cmd, (error, stdout, stderr) => {
7+
if (error) {
8+
console.warn(error);
9+
}
10+
resolve(stdout? stdout.trim() : stderr);
11+
});
12+
});
13+
}
14+
15+
16+
async function beebjit(c, jsbeeb){
17+
18+
// Run tweet on emulator
19+
var tokenised;
20+
try {
21+
var basic = c.input;
22+
var tmp = basic.replace(/\#\w+/g, "").trim(); // get rid of tags and white space
23+
if (tmp.match(/^\d/) != null) {
24+
// If there are line numbers remove a trailing explicit "RUN".
25+
basic = basic.replace(/\n\s*RUN[\s\n]*$/, "");
26+
}
27+
28+
console.log(basic)
29+
tokenised = await jsbeeb.tokenise(basic);
30+
await fs.writeFileSync("./tmp/tweet.bas",tokenised,{encoding:"binary"});
31+
await fs.writeFileSync("./tmp/keys.bin","RUN\r",{encoding:"binary"});
32+
33+
var keyboardBuffer = "03e0"; // BBC Micro OS 1.20
34+
var IBP = 0x02E1; // input pointer
35+
var OBP = 0x02D8; // output pointer
36+
37+
var page = ( c.flags.includes("gxr.rom") ) ? "1c00" : "1900";
38+
var end = parseInt(page,16) + tokenised.length;
39+
var endLow = (end & 0xff).toString(16);
40+
var endHigh = ((end >>> 8) & 0xff).toString(16);
41+
42+
// beebjit debug commands
43+
var commands = "'"+
44+
["breakat 725000",
45+
"c",
46+
"loadmem ../tmp/tweet.bas "+page, // paste tokenised program into PAGE
47+
"loadmem ../tmp/keys.bin "+keyboardBuffer, // 0x03E0 OS 1.2
48+
"writem 02e1 e4", // Advance pointer 4 bytes
49+
"writem 0000 "+endLow, // LOWMEM
50+
"writem 0001 "+endHigh,
51+
"writem 0002 "+endLow, // VARTOP
52+
"writem 0003 "+endHigh,
53+
"writem 0012 "+endLow, // TOP
54+
"writem 0013 "+endHigh,
55+
"c"
56+
].join(";")+"'";
57+
58+
} catch (e) {
59+
console.log("Tokenisation FAILED");
60+
console.log(e);
61+
setTimeout(requestTweet, POLL_DELAY);
62+
return;
63+
}
64+
65+
let beebjit_cmd = "cd beebjit && ./beebjit -fast -headless -frames-dir ../tmp/ -cycles "+c.cycles+" "+c.flags+" -commands "+commands;
66+
await exec(beebjit_cmd );
67+
console.log(beebjit_cmd);
68+
}
69+
70+
module.exports = beebjit;

client.js

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const https = require('https');
1717
const cert_path = "./certs/";
1818
const parser = require('./parser');
1919
const gifsicle = require('gifsicle');
20+
const beebjit = require('./beebjit');
2021

2122
var mastodon = TRY ? null : require(TEST ? './test' : './mastodon');
2223

@@ -54,12 +55,12 @@ var clientID = "Cli0";
5455
'jsunzip': 'lib/jsunzip',
5556
'promise': 'lib/promise-6.0.0',
5657
'underscore': 'lib/underscore-min',
57-
'emulator':'../../emulator'
58+
'emulator':'../../jsbeeb'
5859
}
5960
});
6061

6162
requirejs(['emulator'],
62-
function (emulator) {
63+
function (jsbeeb) {
6364
"use strict";
6465

6566
async function run(tweet){
@@ -69,86 +70,41 @@ var clientID = "Cli0";
6970
var c = parser.parseTweet(tweet);
7071

7172
console.log("Parser output",c);
73+
7274
// If rude or not basic, skip it
7375
if (!c.isBASIC) {
7476
console.log ("No BASIC detected");
7577
setTimeout(requestTweet, POLL_DELAY);
7678
return;
7779
}
80+
7881
if (c.rude) {
7982
console.warn("BLOCKED @"+tweet.user.screen_name)
8083
await mastodon.block(tweet);
8184
setTimeout(requestTweet, POLL_DELAY);
8285
return;
8386
}
8487

85-
var start = new Date()
88+
let start = new Date()
89+
let media_path = "./tmp/"+tweet.id;
8690

87-
var media_path = "./tmp/"+tweet.id;
88-
// Emulate
91+
// Emulate on Beebjit
8992
if (c.emulator == "beebjit") {
93+
9094
var frame_path = "./tmp/beebjit_frame_";
9195
var audio_file = null;
9296
var pixel_format = "bgra";
9397
var emu_name = "beebjit";
9498

95-
// Run tweet on emulator
96-
var tokenised;
97-
try {
98-
var basic = c.input;
99-
var tmp = basic.replace(/\#\w+/g, "").trim(); // get rid of tags and white space
100-
if (tmp.match(/^\d/) != null) {
101-
// If there are line numbers remove a trailing explicit "RUN".
102-
basic = basic.replace(/\n\s*RUN[\s\n]*$/, "");
103-
}
99+
await beebjit(c, jsbeeb);
104100

105-
console.log(basic)
106-
tokenised = await emulator.tokenise(basic);
107-
await fs.writeFileSync("./tmp/tweet.bas",tokenised,{encoding:"binary"});
108-
await fs.writeFileSync("./tmp/keys.bin","RUN\r",{encoding:"binary"});
109-
110-
var keyboardBuffer = "03e0"; // BBC Micro OS 1.20
111-
var IBP = 0x02E1; // input pointer
112-
var OBP = 0x02D8; // output pointer
113-
114-
var page = ( c.flags.includes("gxr.rom") ) ? "1c00" : "1900";
115-
var end = parseInt(page,16) + tokenised.length;
116-
var endLow = (end & 0xff).toString(16);
117-
var endHigh = ((end >>> 8) & 0xff).toString(16);
118-
119-
// beebjit debug commands
120-
var commands = "'"+
121-
["breakat 725000",
122-
"c",
123-
"loadmem ../tmp/tweet.bas "+page, // paste tokenised program into PAGE
124-
"loadmem ../tmp/keys.bin "+keyboardBuffer, // 0x03E0 OS 1.2
125-
"writem 02e1 e4", // Advance pointer 4 bytes
126-
"writem 0000 "+endLow, // LOWMEM
127-
"writem 0001 "+endHigh,
128-
"writem 0002 "+endLow, // VARTOP
129-
"writem 0003 "+endHigh,
130-
"writem 0012 "+endLow, // TOP
131-
"writem 0013 "+endHigh,
132-
"c"
133-
].join(";")+"'";
134-
135-
} catch (e) {
136-
console.log("Tokenisation FAILED");
137-
console.log(e);
138-
setTimeout(requestTweet, POLL_DELAY);
139-
return;
140-
}
141-
142-
let beebjit_cmd = "cd beebjit && ./beebjit -fast -headless -frames-dir ../tmp/ " + c.flags + " -commands " + commands;
143-
await exec(beebjit_cmd );
144-
console.log(beebjit_cmd);
145101
} else // JSbeeb
146102
{
147103
var frame_path = media_path + "frame";
148-
var audio_file = media_path + "audiotrack.raw";
104+
audio_file = media_path + "audiotrack.raw";
149105
var pixel_format = "rgba";
150106
var emu_name = "jsbeeb";
151-
var frames = await emulator.emulate(c.input,frame_path,audio_file,emulationDuration,startFrame);
107+
var frames = await jsbeeb.emulate(c.input,frame_path,audio_file,emulationDuration,startFrame);
152108
if (!fs.existsSync(audio_file)) audio_file = null;
153109
}
154110

@@ -162,14 +118,14 @@ var clientID = "Cli0";
162118
console.log(emu_name+" DONE in %ds ",end/1000);
163119

164120
// Count unique video frames
165-
var shasum_check = (await exec("sha1sum client.js | awk '{print $1}' | wc -l")); // should equal 1
166-
var shasum = (shasum_check > 0) ? "sha1sum" : "shasum";
121+
var shasum_check = (await exec("sha1sum client.js | awk '{print $1}' | wc -l")); // should equal 1
122+
var shasum = (shasum_check > 0) ? "sha1sum" : "shasum";
167123
var frames = (await exec(shasum+" "+frame_path+"*."+pixel_format+" | awk '{print $1}' | wc -l"));
168124
var uniqueFrames = (await exec(shasum+" "+frame_path+"*."+pixel_format+" | awk '{print $1}' | sort | uniq | wc -l"));
169125

170126
console.log("Captured "+frames+" frames ("+uniqueFrames+" unique) "+frame_path);
171127

172-
start = new Date();
128+
start = new Date();
173129

174130
if (frames == 0) {
175131
// NO VIDEO -> NOTHING
@@ -179,6 +135,7 @@ var clientID = "Cli0";
179135
var mediaFilename = media_path+'.png';
180136
var mediaType = 'image/png';
181137
var ffmpegCmd = './ffmpeg -hide_banner -y -f rawvideo -pixel_format '+pixel_format+' -video_size 640x512 -i '+frame_path+(frames-1)+'.'+pixel_format+' -vf "scale=1280:1024" '+mediaFilename
138+
182139
} else {
183140
// ANIMATION OR STATIC IMAGE WITH SOUND -> GIF
184141
var mediaFilename = media_path+'.gif';
@@ -196,7 +153,9 @@ var clientID = "Cli0";
196153
} else {
197154
var checksum = '';
198155
}
156+
199157
exec('rm -f '+frame_path+'*.'+pixel_format);
158+
200159
if (audio_file !== null) {
201160
fs.unlinkSync(audio_file);
202161
}

emulator.js renamed to jsbeeb.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function (Cpu6502, Video, SoundChip, models, DdNoise, Cmos, utils,fdc,tokeniser
2929
async function emulate(input,frame_path,audio_file,duration,capture_start) {
3030

3131
var frameBuffer32 = new Uint32Array(1024 * 625);
32-
var soundBuffer = new Float32Array(44100 * duration).fill(0);
32+
var soundBuffer = new Float32Array(44100 * duration).fill(0);
3333
var soundPoint = 0;
3434
var frame = 0;
3535
var soundChip = new SoundChip.SoundChip(44100);
@@ -167,7 +167,7 @@ function (Cpu6502, Video, SoundChip, models, DdNoise, Cmos, utils,fdc,tokeniser
167167
}
168168
return;
169169
}
170-
170+
171171
// The following is from https://github.com/mattgodbolt/jsbeeb/blob/master/tests/test.js
172172
function runFor(cycles) {
173173
var left = cycles;
@@ -189,7 +189,7 @@ function (Cpu6502, Video, SoundChip, models, DdNoise, Cmos, utils,fdc,tokeniser
189189
});
190190
}
191191

192-
192+
193193
function runUntilInput() {
194194
var idleAddr = processor.model.isMaster ? 0xe7e6 : 0xe581;
195195
var hit = false;

parser.js

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,82 +40,60 @@ function processInput(toot) {
4040
console.log(toot.text)
4141
htmlparser.parseComplete(toot.text);
4242
out = out.trim();
43-
// out = out.replace(/^W+/g,""); // remove whitespace at beginning of lines
44-
// out = out.replace(/\n\n/g,"\n"); // remove empty lines
45-
out = out.replace(/[]/g,'"'); // replace italic quotes
43+
out = out.replace(/[]/g,'"');
4644
console.log(out)
4745

4846
return out;
4947
}
5048

51-
function parseTweet(tweet){
52-
var graphemes = splitter.splitGraphemes(tweet.text.trim());
53-
var one_hour = 2000000*60*60;
49+
function parseTweet(toot){
50+
var graphemes = splitter.splitGraphemes(toot.text.trim());
51+
var one_hour = 2000000*60*60;
5452

5553
var c = {
5654
emulator: "beebjit",
57-
flags: "-accurate -rom 7 roms/gxr.rom -opt video:paint-start-cycles=60680000,video:border-chars=0 -frame-cycles 1 -max-frames 150 -cycles 69000000",
55+
flags: "-accurate -rom 7 roms/gxr.rom -opt video:paint-start-cycles=60680000,video:border-chars=0 -frame-cycles 1 -max-frames 150",
56+
cycles: 69000000,
5857
compressed: false,
5958
input: "",
6059
mode: 1,
6160
isBASIC: true
6261
}
6362

64-
6563
for (let i = 0; i<graphemes.length; i++){
6664

6765
switch (graphemes[i]){
6866

69-
7067
case "🚀": // Snapshot after three hours emulation time
7168
c.emulator = "beebjit";
72-
c.flags = "-cycles "+(3*one_hour+4000000000)+" -frame-cycles "+3*one_hour+" -opt video:border-chars=0";
69+
c.flags = " -frame-cycles "+3*one_hour+" -opt video:border-chars=0";
7370
c.isBASIC = true;
74-
c.mode = 2;
71+
c.mode = 2;
72+
c.cycles = (3*one_hour+4000000000);
7573
break;
76-
/*
77-
case "⏳": // Time lapse of three hours execution time
78-
case "⌛":
79-
c.emulator = "beebjit"; //
80-
c.flags = "-cycles "+(3*one_hour+4000000)+" -frame-cycles 4000000 -opt video:border-chars=0,video:paint-start-cycles=4000000,video:paint-cycles="+(3*one_hour/150)+" -max-frames 150";
81-
c.isBASIC = true;
82-
break;
83-
8474

85-
case "⏰": // Fast run 3 hours then 3 seconds time lapse
86-
c.emulator = "beebjit";
87-
c.flags = "-cycles "+(3*one_hour+9000000)+" -opt video:paint-start-cycles="+(3*one_hour)+",video:paint-cycles=40000,video:border-chars=0 -frame-cycles 1 -max-frames 150";
88-
c.isBASIC = true;
89-
break;
90-
*/
9175
case "🎬": // Fast run 3 hours then 3 seconds time lapse
9276
c.emulator = "beebjit";
93-
c.flags = "-opt video:paint-start-cycles="+(3*one_hour)+",video:border-chars=0 -frame-cycles 1 -max-frames 150 -exit-on-max-frames -cycles "+((3*one_hour)+8000000);
94-
// c.flags = "-cycles "+(3*one_hour+9000000)+" -opt video:paint-start-cycles="+(3*one_hour)+",video:paint-cycles=40000,video:border-chars=0 -frame-cycles 1 -max-frames 150";
95-
c.isBASIC = true;
96-
c.mode = 3;
77+
c.flags = "-opt video:paint-start-cycles="+(3*one_hour)+",video:border-chars=0 -frame-cycles 1 -max-frames 150 -exit-on-max-frames";
78+
c.cycles = ((3*one_hour)+8000000);
79+
c.isBASIC = true;
80+
c.mode = 3;
9781
break;
9882

9983
case "⛔": // Do not run
10084
c.isBASIC = false;
101-
c.mode = 0;
85+
c.mode = 0;
10286
return c;
10387

10488
default:
10589
c.input += graphemes[i];
10690
var g = graphemes[i].codePointAt(0);
107-
// if (g > 1024 && g < 0x10FF) {c.compressed = true;}
10891
}
10992
}
110-
tweet.text = c.input;
111-
c.input = processInput(tweet);
93+
toot.text = c.input;
94+
c.input = processInput(toot);
11295
c.rude = (customFilter.clean(c.input) != c.input);
11396

114-
// c.emulator = "beebjit";
115-
// c.flags = "-cycles "+(3*one_hour+4000000000)+" -frame-cycles "+3*one_hour+" -opt video:border-chars=0";
116-
// c.isBASIC = true;
117-
// c.mode = 2;
118-
11997
console.log("\n",c);
12098
return c;
12199
}

0 commit comments

Comments
 (0)