This seems interesting, but I got stuck fairly early on when I read "all 32,385 possible input combinations". There are two 8 bit numbers, 16 totally independent bits. That's 65_536 combinations. 32_285 is close to half that, but not quite. Looking at it in binary it's 01111110_10000001, i.e. two 8 bit words that are the inverse of each other. How was this number arrived at, and why?
Looking later there's also a strange DAC that gives the lowest resistance to the least significant bit, thus making it the biggest contributor to the output. Very confusing.
Is that the number of adds that don’t overflow an 8-bit result?
On that hunch, I just checked and I get 32896.
Edit: if I exclude either input being zero, I get 32385.
You also get the same number when including input zeros but excluding results above 253. But I’d bet on the author’s reason being filtering of input zeros. Maybe the NN does something bad with zeros, maybe can’t learn them for some reason.
Interesting puzzle. 32385 is 255 pick 2. My guess would be, to hopefully make interpretation easier, they always had the larger number on one side. So (1,2) but not (2,1). And also 0 wasn’t included. So perhaps their generation loop looks like [[(i,j) for j (i-1 -> 1) for i (256 -> 1)]
There's probably a lot of other memory bugs though. The first thing I looked at was the shell, and almost immediately I spotted an out of bounds write (input[n] = '\0' where n could be sizeof(input)).
For sure. I’m highlighting the nastier parts of the system that Rust can’t help with. I love Rust but it’s important to understand its limitations, particularly for something like OS development. There’s a similar way to make Rust unsafe using 100% safe Rust where you poke /proc/self/mem to violate memory safety using safe IO :).
The C= 1084S he uses is a more a (very good) PAL TV than a computer monitor, even if it was sold as a monitor. So "576i" in your terminology. (It was also sometimes sold with a TV tuner, or at least the earlier 1084 (same picture tube AFAIK) was.)
I have a related complaint about modern consoles: They are frequently unreadable, because they just have to use all the pixels. I booted Debian (IIRC) on a laptop with a 13" 4K screen and got something like 426x135 characters. No chance for me to read them, but there sure were a lot of them. My eyes aren't the best, but I think most people would find that unreadable.
Defaulting to 80x25 (or anything else reasonable) in an almost infinitely ugly font would be a vast improvement.
And in 80x25, there’s so much text that it zooms past you with no chance to ever read it, and Scroll Lock won’t work. Can’t have it both ways, I suspect the truth is somewhere in the middle.
One thing that really annoys me about the HTTP standards is that some older version used to say that text/* without a declared charset was definitely latin-1 (don't remember which version exactly). Then a later version said no, text/* without a declared charset is definitely utf-8. In practice I feel this means they said "not declaring a charset is definitely not ok", but in a way that no one will understand.
Possibly a newer version that I haven't read fixed how they said that. As long as I don't check I can hope.
Using "#!sh" at the top of the file does work, but not predictably. It may execute sh in your current directory, which is what Linux does, but your shell may override that (zsh does if the first attempt fails). So it works, but not the way you want it to.
I think it's worth pointing out that the example in the article contains a bug caused by not having shadowing: "const foo3 = try foo.addFeatureB();" should not be using the original foo, but foo2.
The name sounds like it means "this is how I want you to cause the service to stop" to me (and clearly to others as well). That would be symmetrical with ExecStart meaning "this is how I want you to cause the service to start". If it runs after the service stopped it should be called "ExecAfterStop" or something like that.
That is what ExecStop means. It specifies how you want to cause the service to stop. But the lifetime of the service isn't exactly the same thing as the lifetime of the process that got started in ExecStart.
Maybe think about it this way: ExecStart is what the system will run to transition the service from the "starting" state to the "started" state. ExecStop is what the system will run to transition the service from the "stopping" state to the "stopped" state.
For a service with RemainAfterExit=no (the default), you enter the stopping state right away once the processes that got started in ExecStart exit. That's useful when you are starting some long lived process as a service, and in that case there is usually no need for an ExecStop. But semantically, ExecStop has the same meaning either way -- it's what needs to be run, if anything, to transition the service from the stopping state to the stopped state.
I have now found the documentation for ExecStop (in systemd.service(5)), which hopefully improves my understanding.
It definitely seems to be both "cause to stop" and "after (unexpected) stop" in one. You can look at $MAINPID to see which case you have. This design apparently makes sense to you, but to me and several others in this thread a service that has already stopped isn't in need of being stopped and shouldn't execute commands intended for that. (There is a separate ExecStopPost for "after stopping, for any reason".)
VGA is much easier to produce, and the RP2040 can do 1280x1024@60 no problem. The official examples use several clock cycles per pixel (2 IIRC, but it might be even more), but you don't have to.
I made half a terminal with that output, aiming for something that ran the original VT100 ROM. I never finished the emulator part, but I did write video output (including scan line emulation) for VT100 memory -> VGA. Adding SSH once the rest works should be perfectly possible. (Not bit banging ethernet at the same time, but using some external chip.)
I should probably put that online somewhere. Or finish it and then put it online.
Looking later there's also a strange DAC that gives the lowest resistance to the least significant bit, thus making it the biggest contributor to the output. Very confusing.