HN user

logicalshift

72 karma
Posts0
Comments22
View on HN
No posts found.

Had a look at my bookshelf to see what I could find that was obscure, maybe these would be interesting:

First Contract (Greg Costikyan) - a book about the economics of first contact

John Courtney Grimwood (author) - science fiction, generally cyberpunk, told from the point of view of characters who don't understand the tehcnology, which gives his work a kind of mystic vibe. (Eg, Nine-tail fox is about a detective trying to solve his own murder)

Footfall (Larry Niven/Jerry Pournelle) - was a big release back in the day, but not so well known these days. Hard SF alien invasion novel (Independence Day might have ripped this off a bit)

The NASA trilogy (Stephen Baxter) - dark alternative future books, with bleak endings but great science. I think not so well known these days because of the bleakness, but that's also part of what made them memorable when I read them.

EndBASIC 3 years ago

RISC OS is still available for the Raspberry Pi. You get to basic by pressing F12 and typing ‘BASIC’, and it has a built-in ARM assembler already - the manuals are all available online, there’s a BASIC manual and the Programmers Reference Manual for the whole OS.

(It’s exactly like a BBC B because this is the same version of BASIC, ported to ARM, it even emulates some of the hardware because back in the day they wanted to make software run without porting)

In theory typing ‘*CONFIGURE LANGUAGE 20’ (BASIC being module 20) should make it into a machine that boots straight to BASIC but when I tried it just now it just ignores the setting because the keyboard drivers aren’t loaded soon enough.

I started off with a BBC Micro, followed by an Acorn A3000. My first 'PC' was a 486 card for the RISC PC - now there's an interesting architecture: the machine had two processor slots, but didn't require that the processors to have the same architecture. You could use the 486 as a very janky floating point accelerator for the ARM chip as well as to run DOS and Windows.

An interesting thing is that RISC OS is still available for the Raspberry Pi and it's a direct descendant from the operating system of the BBC Micro - not emulated. It still has the same level of direct hardware access, so if you ever wanted to use peek and poke (well, those are the ! and ? operators in BBC BASIC) on some modern graphics hardware, there's a way to do it. There's a built-in ARM assembler in there too.

What I think was really different about the time was the quality of the documentation. Nothing modern has the same sense of empathy for the user or achieves the same combination of conciseness and comprehensiveness. For instance, here's the BBC Micro's Advanced User Guide: https://stardot.org.uk/mirrors/www.bbcdocs.com/filebase/esse... (it's of particular historical note, because today's ARM architecture grew out of this system). You could build the entire computer from parts using just this 500 page manual, and you'll note that it's not actually a huge amount more complicated than Ben Eater's 6502 breadboard computer.

Weird thing: RISC OS actually has backwards compatibility with some of the old APIs so some of the stuff in the advanced user guide still works today on a Raspberry Pi (plus it comes with a BBC Micro emulator which was originally written because Acorn didn't want their new machine to fail due to a lack of software). These days there's also https://bbcmic.ro of course :-)

The Programmers Reference Manual for RISC OS is similarly well written, and surprisingly quite a lot of it is still relevant: most things still work on a Raspberry PI, and even modern operating systems still work pretty much the same way on the architecture. While things like MEMC, IOC and VIDC are long dead, there's a pretty direct lineage for the modern hardware to these older chips too.

I wrote a parser generator quite a long time ago that I think improves the syntax quite a lot, and which has an interesting approach to generalisation: you can write conditions on the lookahead (which are just grammars that need to be matched in order to pick a given rule when a conflict needs to be resolved). This construct makes it much easier to write a grammar that matches how a language is designed.

Here's an ANSI-C parser, for example: https://github.com/Logicalshift/TameParse/blob/master/Exampl... - this is an interesting example because `(foo)(bar)` is fully ambiguous in ANSI C: it can be a cast or a function call depending on if `foo` is a type or a variable.

The new construct makes it possible to extend grammars and disambiguate them - here's a C99 grammar that extends the ANSI-C grammar: https://github.com/Logicalshift/TameParse/blob/master/Exampl....

It also allows matching at least some context-sensitive languages - see https://github.com/Logicalshift/TameParse/blob/master/Exampl...

An advantage over GLR or backtracking approaches is that this still detects ambiguities in the language so it's much easier to write a grammar that doesn't end up running in exponential time or space, plus when an ambiguity is resolved by the generalisation, which version is specified by the grammar and is not arbitrary (backtracking) or left until later (GLR).

I was working on improving error handling when I stopped work on this, but my approach here was not working out.

(This is a long-abandoned project of mine but the approach to ambiguities and the syntax seem like they're novel to me and were definitely an improvement over anything else I found at the time. The lexer language has a few neat features in it too)

I've been working a 2D rendering toolkit that increasingly looks to me like it probably deserves a mention on these lists: https://github.com/logicalshift/flo_draw (but I'm not on Reddit...). Layers, vector sprites, dynamic textures and a streaming API that fits well with 'reactive' designs are amongst the features that make it stand out from what else is out there. It's super simple to get going too.

Started life as a rendering layer for FlowBetween so I could put in whatever looked like it was 'winning' later on but wound up writing my own renderer as there wasn't anything quite there yet. Still has that design so another unique thing is that it's possible to use the same API with whatever rendering layer you want.

Speaking of FlowBetween, one thing I have wanted to do for ages is to get rid of the platform-specific GUIs and use something universal. It should be easy because FlowBetween sends straightforward instructions to an independent GUI layer, but I keep bouncing off for a few reasons:

- it's a big ole task so I definitely want to pick something that's stable and also lets me hedge my bets in terms of being easy to migrate away from

- most commonly, FlowBetween needs pressure data from tablets and a lot of frameworks just don't do that (this is also in a terrible state in browsers)

- lots of GUI crates are designed as frameworks and so try to dictate the entire design of any app that uses them, which is no good for FlowBetween which tries to keep its internal design choices independent of its choice of GUI

At the moment, I suspect that some sort of imgui framework is best along with an entirely manual implementation of tablet pointer data: fits with my existing design and isn't 'contagious' in a way that could make it hard to migrate to something else later on.

You didn't say which language you're using. If you're interested in Rust, I wrote a crate which deals with a bunch of bezier operations, including boolean path operations: https://docs.rs/flo_curves/latest/flo_curves/bezier/path/ind...

The 'better way' you're talking about here is the curve clipping algorithm, my version of which is here: https://docs.rs/flo_curves/latest/flo_curves/bezier/fn.curve...

Finding the intersections between individual curves is only the first part of this operation: you also need a way to determine which edges are on the outside of the new path (flo_curves uses raycasting for this, same operation that the OP focuses on, essentially) and deal with a fairly large pile of edge cases - literally edge cases here. Things like overlapping edges, nearly overlapping edges, what happens if a ray passes through an intersection point or directly across a straight edge, precision issues, curves with loops, etc.

The main difference between the ARM1 (which was never sold in any quantity) and the ARM2 was the addition of the multiply instruction (and the multiply and accumulate instruction). They were the only multi-cycle arithmetic operation they had, and what's more you couldn't load arbitrary constants into a register with the MOV instruction or use constants with the multiply instruction itself so they were still a bit inconvenient as well as comparatively slow.

But you could write:

  MOV R1, #3
  MUL R0, R0, R1
In spite of the limitations, this gave the instruction set a certain 68000 quality to it (except much faster for a given clock speed).

To multiply the number in R0 by 3, which was pretty convenient. The ARM had a thing called the barrel shifter though, which let you add an arbitrary shift to the last operand of any arithmetic operation. All arithmetic ops take 1 processor cycle, so you could write this instead to multiply by 3 in a single cycle:

  ADD R0, R0, R0, LSL #1
Ie, add R0 to itself multiplied by 2. Constant divisions could be constructed with the SUB instruction too. Some constants required multiple instructions (but I think the maximum was something like 4 or 5 instructions for any constant? I wrote an assembler that could figure this out for you automatically in the mid-90s so I used to know for sure).

This is basically a single-instruction version of the 6502 trick (handy, because the first OS for the ARM was a hurried port of a 6502 operating system), which sort of fits with the ARM's original inspiration as being a 32-bit version of the 6502. As each instruction completes in one CPU cycle, the ARM could have fairly monstrous integer performance for the mid to late 80s if you knew how to program it.

If Rust's your language, I wrote a library that should be pretty good at 2D things: https://github.com/logicalshift/flo_draw - I wrote it while working on another project (FlowBetween) where I found debugging would be easier if I could just render something on-screen but rendering stuff on screen always required a ridiculous amount of setup.

It has some nice options for feeding its own output back into itself as it uses streams rather than callbacks so it's quite good for procedural rendering type tasks (the 'Wibble' example is a good place to start with that)

The official Rust Programming Language book is excellent and was all I really needed to learn the language. I had a small project to work on that I didn't mind rewriting after my first attempt (my build server is a NUC and I wanted to write some software flash the LEDs on the front to indicate build state)

I suspect everyone goes through a phase of hating borrowing when learning Rust: it's helpful to know that it's something that eventually 'clicks' and really stops being an issue. It didn't exist when I was learning, but 'Learning Rust with Entirely Too Many Linked Lists' looks like it would have helped a lot.

I suspect some of my experience is now out of date, as it's now spread out over quite some time. The most recent issue I had to deal with was Chrome: when drawing the canvas at high-res it was being a bit slow at blitting some bitmaps and so was running at 30fps. Something is tied to the framerate with the pointer events implementation and so the events also lagged behind, which made drawing on the canvas quite difficult as the display was 250-500ms behind the user. Eventually 'fixed' by turning the resolution down, but it was a real pain finding what part of the application had got behind (FlowBetween being designed not to lag but to catch up when the display can't keep up). That's quite a subtle one and the pointer events lagging is easily mistaken for the frame rate lagging.

Other browsers don't do this, but they've had a few other issues: what I remember in particular - some only support pressure information using the touch API, and some seemed to support pressure information on different APIs on different platforms, so both pointer events and touch events were needed.

All of these are maturity issues rather than real problems with the API, though and I haven't re-checked some of the older issues recently - that Chrome issue was still happening back in January so might still be around, but the others I last encountered over a year ago so may have been fixed by now.

I’ve been keeping an eye on the various UI libraries when they come up: right now it seems to take me around a month to add a new one so I’m waiting for one to get traction.

Something else that’s a problem is that as a drawing app, FlowBetween wants to be able to get access to data from a digitizer: pen pressure and tilt in particular. A lot of UI libraries don’t think to pass that through from the operating system, or have an awkward API (browser support is also very spotty for this)

I like to draw, and I suppose my frustrations with other animation packages that I’ve tried were the main inspiration. It’s quite nice to have something that combines two hobbies into one.

When I started I picked Rust because I’d been learning it and wanted to try using it on a more substantial project. I’m very happy with it as a choice of language: it definitely has a difficult learning curve especially with the way borrowing looks similar to references in a garbage-collected languages but works very differently. However, it’s a very expressive language: something about it makes it very easy to write code quickly that’s still very easy to follow later on.

Well, my main side project is the same as it's been for the last couple of years, an animation/vector editing tool written in Rust: https://github.com/logicalshift/flowbetween

It's sort of starting to make the transition between a pile of ideas and an actually useful tool at the moment. The whole idea is to be a vector editing application that works more like a bitmap tool when it comes to painting, so there's a flood-fill tool and a way to build up paths just by drawing on the canvas rather than having to manually mess around with control points.

The way I built the UI is unique too I think. Choices for UI librarys for Rust were quite limited when I started so I built it to be easy to move to different libraries. I don't think there's any other UI library in existence that is as seamless for switching between platforms (or which can turn from a native app to a web app with a compiler flag without resorting to something like Electron)

Been working on a piece of 2D animation/vector editing software called FlowBetween for a while now:

https://flowbetween.app

Seemed like a good way to combine my interest in building software with my other interest in creating art.

I've been spinning off the various components needed to build it as separate rust crates: interesting ones are flo_curves, desync and flo_binding.

There are a few of those out there. Nanovg seems to be the one that fits your requirements most closely. If you're into Rust, lyon (plus something like gfx-rs) is another choice.

It's also worth noting that the HTML canvas implementations in most browsers is also not too bad for performance. Quartz is also really fast, but Apple made it really easy to accidentally use a slow rendering path (especially for bitmap operations)

So, I decided to teach myself a few years ago. I made notes as I went, and the process of learning a skill like this is really quite interesting.

The first piece of advice I’d give you is to go out and buy some books. Specifically, aim to buy things that you think you’ll still want to refer to no matter how far you take your skill, rather than books aimed at beginners: books designed as reference books and aimed at artists are ideal. First book I bought was ‘Color and Light’ by James Gurney. Also, buy the book Art & Fear if you don’t own it already.

At first, this is all about fear of failure. One of the main differences in the way children learn to adults is that children don’t have this fear. It’s taught and it can be unlearnt, but you’re probably going to have to confront it at some point. Sooner is better. Books and lessons aimed at beginners almost never help here. The usual beginner-type books instead try to teach lessons that you can succeed at, trying to avoid doing things that trigger that fear. To learn, you need to try to do things you can’t already do, not avoid them (this is also the key difference between practice and rehearsal. To learn something new, you need to make sure to practice and not rehearse).

What I think is that it's better to try to learn from sources that are beyond you than those that are already in your grasp. The problem is that at first, it’s very discouraging to try to do these kinds of things. So particularly at first, I’d recommend dealing with your feelings about painting much more than the actual skill itself. In particular, remember things that make you want to paint so you can find a reason to paint every day. When it comes to fear, curiosity is its antidote. If you try to achieve a specific effect in a particular painting, you can fail and that hurts; if instead you’re just curious about what would happen if you try something new, the results are just interesting. Occasionally they’ll be much better than you’re expecting, and those instances are addictive.

The overall process of learning these skills is interesting: at first it’s a bunch of small isolated skills, like the fine motor skills needed to make your brushes go where you intend. It’s quite frustrating because things don’t work together at first - so you might find that you're able to draw individual shapes quite well but they all look wrong when you try to put them together into a picture, or your shading will always look blobby and weird in an actual picture even though it looks OK when you focus on just that. Here’s the interesting thing: the isolated skills start to link up and it seems to be a sudden thing.

For example, I once set aside a day to just focus on learning how to build up shadows as nothing had ever worked well in the past and found to my surprise that there was nothing left to learn - things I’d already learnt just linked together and everything I tried came out exactly as I'd intended (which was a great feeling as I'd been learning for 2 years at that point and 'draws weird shadows' was starting to etch it's way into my identity). I had a similar experience with learning to draw in perspective.

There’s another stage too: after a while of things linking up it develops into a kind of language - which makes me wonder if that’s what language actually is: just a way to organize and regulate different interconnected parts of the mind: it definitely explains a lot about why the experience of drawing and painting comes so naturally to some people yet is so hard to properly explain to others.

Hi, you might be interested in a crate I wrote called desync: https://docs.rs/desync/0.3.0/desync/ - it provides a very simple yet expressive API for performing asynchronous operations and has full support for the futures crate. It can be learned really quickly.

Desync takes a slightly different approach to asynchronous programming: instead of being based around the idea of scheduling operations on threads, and then synchronising data across those threads, it's based on the idea of scheduling operations on data.

There's only two basic operations: 'desync' runs an operation on some data in the background, and 'sync' runs one synchronously.

All operations are run in order and 'sync' returns a value so it's a way to retrieve data from an asynchronous operation. It's sort of like setting up some threads with some data protected by a mutex and sending results between them using mpsc channels, except without the need to build any of the scaffolding. ('sync' also makes borrowing data from one task to use in another effortless)

I've been building an animation tool that provides a UI over http (https://github.com/logicalshift/flowbetween) so it has a lot of these problems.

For running as a local app, what I really want is to be able to run the server as a UNIX-domain socket. (Well, I can do that fairly easily but what I really want is for browsers to be able to connect to one of these).

For a single-user app the main issue is that it could be running on a multi-user system so there's the possibility of contention for ports and so on, as well as the need to verify that the right person is connecting - while it's possible to just bind the server to the loopback address anybody on the same system can access it there so it's not necessarily secure enough. For localhost verification, accessing/setting some information from a file URL might work.

With the loopback address, encryption doesn't seem to matter too much: anybody capable of intercepting traffic between a piece of software and the browser will also be in a position to just directly read what you're typing. Possibly by looking over your shoulder.

However, one of the reasons I want a HTTP UI is to make it possible to use something like an iPad as an input device and there are definitely issues there when the service is something that's randomly stood up and torn down and usually running on a local network rather than the internet: in particular TLS really expects a centralized service so it seems anything other than a self-signed certificate isn't going to work and that comes with a bunch of scary messages for the user.

The other issues of authentication all seem to be much the same as for any other web app, though it seems to me that it's possible to streamline it a bit as it'll be quite common for a user already authenticated on one device only to need to prove that they're the same user on another.

I wish you luck because the standards are a mess, but the terminal seems to have been ‘good enough’ for quite a long time (which is why all the standard originate in the 1980s). I think to make a new terminal stick, it’ll need to do something that is impossible with the current implementations rather than just try to sort out the mess.

One possibility is graphical output. It’s not easy to write a ‘simple’ application that produces graphics right now in the same way you can write one that outputs text to the terminal (also: ‘moving on’ from a simple design to a more polished one generally involves rewriting the graphical portion).

A more random pet peeve: when you run a command and it goes wrong, usually the most useful error message is the first one it displays, but the terminal will scroll to display the last errors which are usually less interesting. A ‘workbook’ style terminal (like you might see in a CAS) might ameliorate this problem? It also helps with a command outputting a giant pile of garbage because a parameter was wrong, as well as the issue where if you’re running something like a compilation job over and over to fix errors it’s hard to tell which messages were from the most recent vs the previous command.

My day job used to involve parsing some fairly ill-formed languages, so I developed this: https://github.com/Logicalshift/TameParse

I noticed with the languages I was working on, the problems could be resolved by being smarter with the lookahead: this parser allows for context-free lookahead matching to resolve (or detect and defer) ambiguities.

That makes it possible to do neat things like parse C snippets without full type information or deal with keywords that aren't always keywords (eg, await in C#).