Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

300kHz is what I'm opting to toy with for OSdev (lets me set a nice benchmark of 5k cycles/"tick", so the OS will run at 60 FPS), and definitely fits the theme of low-fi computing.  To that end, I'm working on a new sub-code for the UTL set - TIMR, which does exactly what it says on the tin.  Lets you time the number of cycles that've passed since a specific TIMR call, putting it into Register 1, and means both the programs, and operating system, can try to ensure they'll always fit into that 5k timeslot so as not to disrupt the user input & whatnot.  600kHz would make for a SLIGHTLY less complicated experience (especially for, say, filling in windows - those'll take a few OS ticks to draw in, at least!), but isn't a hugely groundbreaking increase.


I assume platform-endian; it's just Convert.ToString(disk[indexToSave])+"\n" being written to the file.   The thing that would make saving in binary cool is then it's like an actual disk image - it's the raw sequence of 1s and 0s that make it up, and by extension, it means it should take up exactly the amount of space on your RL harddrive as it has storage space within.  Saving to ELF is certainly a neat idea, but it's not always necessarily raw executable data - if I get, say, a basic text editor working in the windowed SenbOS project, it'll be saving text files to disk that could certainly LOOK like code, but decidedly aren't.


You're pretty much spot-on with what I'm thinking - the peripheral is essentially supposed to be a literal cable that plugs into one physical network port, giving a bi-directional I/O system.  You can use SETDATA to send one 32-bit packet (e.g, reading from a register or memory address, like it is with monitors) to the device on the other end, and you can use GETDATA to read any packets that device has sent you - the peripheral keeps a buffer, so you pop 'em off like key inputs.  I'm trying to figure out how many ports should be the default - 2 is what I'm thinking, maybe going up to a max of 4 for the default computer you could use in Custom mode.  Beyond that, I'm considering having a few alternate computers available to spawn in (as an and/or thing) for Custom mode, such as a router with a more limited peripheral set (e.g, small monitor capable of any resolution, drive, keyboard), but with a ton more network ports available.  You could link a bunch of 'em together to start making something that resembles anything from the internet, to a simple LAN.

The idea of writing a custom networking system to go with this is cool - like you said, simple two-person networking doesn't need much, but you could very feasibly work on writing a TCP/IP style system that'd let you hook up a bunch of different computers.  It'd probably require some cooperation between players to get it configured nicely, but could be a really neat way to share in the nerdiness of TC-06 development.  Thinking about packet ideas, there should maybe be a "I AM IP <32-bit IP>" packet (sets a cached IP address for the network port it came in on), a "WHAT IS THE IP STATUS OF <4-bit port ID>" packet (IDs 1-16 are actual ports, and shares their cached IP if applicable, ID 0 is "how many ports do you have", and should be blacklistable on certain ports so you can, say, keep a LAN from being shared to the outside world that's on the last actual network port of the device), a "SET DESTINATION IP <32-bit IP>" packet used for preparing to send data, and a "SEND DATA <32 bits of data>" packet that does exactly what it says on the tin.  To get around the 32-bit limitation, maybe assume all packets are sent in twos - first a "function ID" packet, and then an "arguments" packet?  Oh, there also definitely needs to be a "RECEIVE DATA" packet, so it won't just think someone's calling a function on it.

The networking "BIOS" could easily route something if the requested IP was connected to it, but if it doesn't know that IP, then it would probably run through and pass the "SET DESTINATION; SEND DATA" function along to all of the device it's connected to, in the hopes one of them will successfully route it.  Would definitely need to add some IP blacklisting so it won't cause a feedback loop that'd eventually end in a device trying to send that data back to its source or something like that - e.g, "BLACKLIST ME" temporarily disables the output of "WHAT IS STATUS" or similar.  Yikes, things get complicated fast.


I know very little about classic IRC, just that exists, used to be a huge deal, and that it'd be a decent idea to implement an IRC system if the Senbirnet can be a thing one day, because chatting about Senbir from within Senbir is just...so cool.  As I understand it, the protocol is high-quality and versatile - friend of mine said he was toying with writing a virtual CCG (think Hearthstone, Scrolls/Caller's Bane, etc) that used IRC under the hood to handle the networked aspects of the game, a while back.

My head's spinning just trying to imagine that setup!  I can't really imagine what it was like before the days of universal TCP/IP, ethernet, wi-fi, and so on - I've grown up in this era, and talking about the ye-olden days of internetting with family is always pretty mind-blowing and alien.  Save for the part about terrible connection speeds - those're all too familiar where I live.  Not often dialup-tier terrible, but often fairly bad - if I have internet at all, that is!  Depending on when you started playing Senbir, you might've seen the big warning I had up about potentially game-breaking bugs and an inability to patch them - I got the original LD-ready build uploaded about an hour before a storm blew out my local ISP for about a week.  That wasn't fun.

I meant the endianness wrt. a hypothetical binary format - I know of two common ways and another uncommon way to store 4-byte ints (as in, the order of those 4 bytes) that have actually been used on various platforms. Your format uses text instead of binary, so I'd assume it uses the normal way of writing numbers (most significant digit first, just using base 2 instead of 10), and endianness doesn't really come into it.

And yeah, ELF is really only appropriate if thinking of the disk image as a single program (and I'm not sure even then, really). It would probably be more appropriate to use a VM disk image format, like e.g. qcow2. But again, probably not really worth the effort at this point. (Well, I guess plain raw binary counts as a common VM image format (I use it), which shouldn't be too hard, but still.)


So, were you thinking that a single network peripheral should have multiple ports? Or just that the default computer should have multiple network peripherals, with one port each, assigned to different device numbers?

The latter would probably be easiest to use, as then you could use the protocol you suggested of simply SETDATA/GETDATA-ing to the device to write/read a word on that port, and a different network port is simply a different device number. Otherwise you'd have to design more of a protocol just for the communication between the PC and peripheral as well, making it harder to use.


Regarding custom modes, one thing I think would be neat was if that basically gave you a computer builder - you start with just the TC-06 CPU core and a slot for each device port, and for each of them you can pick which peripheral you want to be attached to that port (if any), and then configure that peripheral.

This would allow people to build a computer with whatever peripherals they need for their application - whether that is a PC with extra disks or multiple monitors, or something like a router with nothing but network devices.

It would probably require the saved-preset format to be changed, though - maybe something based on JSON so it can be structured in an extensible way (each device type could define its own config structure)?


Regarding the packets, the nice thing about all of this just being data sent across the "wire" is that players can experiment with different packets and protocols, and (if we're lucky) end up forming a consensus about which protocol to use based on what works best. That's what happened with the Internet, after all.

If you want to design a new core networking protocol, it might be an idea to look at what has already been tried to avoid some known mistakes - because yes, this gets complicated fast. Especially when you realize you can't always trust the other end of the link to not be stupid (which can be worse than them being malicious) - e.g. by using the same address as someone else (if they can set their own).

I'll note that most low-level networking works asynchronously and tends to avoid keeping state where it can (especially for things that should just work automatically or quickly), instead sending along everything that is necessary in each data packet (e.g. source address in addition to target) - and there are reasons for that. I don't know if all of those reasons apply to the Senbirnet, though.

I'll note that what you're describing with regards to packet forwarding is more like what switches do than what routers do - routers generally only forward what they're configured to forward, to the places they're configured to forward them, and anything else gets dropped. (There's often a default route, though, but that is still configuration that basically says "anything else, send to there".) Regular switches, in contrast, forward packets between their ports without any such configuration. (Managed switches may be different, but that's mostly enterprise-level stuff.)

The core routers of the Internet do have protocols they use amongst themselves to automate changing that configuration based on current conditions, but that's mostly because of the scale and conditions of the Internet, with things like multiple available paths being normal, those paths having different delay, and routers being expected to use the best path while automatically routing around problems like broken connections. (Yep - modern networking gets complicated fast even when only considering one part of it...)

Also, a common way to avoid infinite loops is to include a max hop count (sometimes called TTL (time to live)) in the packet - and then each router it passes through decrements that field, and if it's zero, drops that packet. (That's actually how traceroute is implemented, because IP routers generally send an error response back to the originator about packets that are dropped due to that.)


Regarding IRC, yes, AFAIK, it's a pretty good protocol, and quite flexible (within what it does, obviously). It's also fairly easy to understand (at least the basics), and since it's text-based (not a binary protocol), can even be used directly by humans. (I've done that with telnet, to test and try out things.)

The main problem I had with trying to use it for other things (like transferring drawing commands for a shared whiteboard) was the message limits of the server (like e.g. max 10 messages within 10 seconds), but that's because I was trying to use someone else's IRC server - if he's running his own IRC server to run the game, then he can obviously set the limits as he wants/needs to. And I suppose that kind of game doesn't really need all that many rapid-fire messages anyway.

Thinking about it, for Senbir I think the main problem with it is that it requires text parsing (and sending whole messages rather than individual characters), and that most servers have timeouts, but given a mode with decent specs, a simple client is probably doable. A full-featured server would be rather more difficult, what with having to track users and channels, route messages, etc., but we might be able to do a simplified one that works with the simple client.

It may be better (or at least easier) to just look at it for inspiration, esp. given the word-based nature of the TC-06 (while IRC is byte-based), rather than trying to implement it directly.