Aug
02

FileSieve 4.22 2017

Wasn't expecting that: made another release of FileSieve yesterday.

For no particular reason at all, a thought about the way FileSieve handles the Start automation command popped into my head while I was doing something completely unrelated.

I had a feeling of dread. I wasn't sure why, but it was there. Something was... wrong.

When my conscious mind caught up with the sub-conscious, it occurred to me: profile processing (which is what Start begins the process of but via the command-line) is threaded and consequently doesn't block the main thread. I didn't add any code to wait for that processing to exit; I just carry on with executing the remaining commands that were passed in via the command-line.

An enormous oversight as this means FileSieve is merrily executing commands while a profile is being processed, copying files and all sorts of stuff, while possibly nobbing things up left and right.

Loaded the code and then wondered how I was going to solve this. I forewent any semaphore or signalling as I wanted to get this update done and released ASAP. Instead, I made all automation commands asynchronous and then, in simple terms, busy-waited until it was complete.

I'm cheeky, me!

While I was in there, I decided to add support for allowing automation via an external file. FileSieve parses the file and then runs the encountered commands as though they were passed in via the command-line; lovely, lovely, code reuse.

As the file reading code is custom just for that task, I thought I'd allow line comments; any line that starts with a hash # character is ignored. Incidentally, all lines are trimmed of spaces.

Commands and their values can be spaced out however you want as, again, trimming is done before the fields are interpreted. As well as providing general flexibility in the syntax, it also avoids the commands/values looking all squashed together.

If the autofile is just feeding commands from the file into the command-line parser, does that mean... recursion? Yes, yes it does! If an Autofile command is encountered within an autofile, then that file is then parsed. Allowing this to continue unabated is obviously not a good idea as eventually a StackOverflowException is thrown - turns out at about 1,000 levels deep! No idea why I always thought stack overflows occurred at around 8 iterations. Maybe due to the contents of the stack / frame sizes.

Aug
01

Game of Thrones, Season 7 Episode 4 recap 2017

No idea; haven't watched it.


Comica Database Update

Oh my, no update for a few days? It's the end times!

Nah, nah; I just didn't work on anything of note to write about. Already, a lot of the stuff I blog about I would never have previously done as they're not what I'd call "major", or even exciting. But I'm making myself talk about them anyway as it keeps content coming, so don't go thinking I'm thinking that I'm working on major works of art or anything - it's just more kahnent to babble about.

Alright, Comica. Not much to report on this other than I pushed a database update out for the first time in a while. Or, at least tried to.

I received a "Comic not working" notification (a feature I built into Comica that allows users to notify me of knackered comics) and thought, "Eh - why not?". I then ran a "deep validation" within the Comica Editor to weedle out any obviously broken comics while I was fixing up the reported comic.

Thirty minutes later (yes, it takes a while to manually go through the comics that the Editor says is broken; this is why I don't do full updates often, especially as I could be working on my commercial software instead), all fixed. Hit Upload and... nothing. The little console app that does the actual uploading appeared and then immediately disappeared. Uh-oh.

Loaded up the source and, oh, I should probably upgrade all of the projects to .Net 4.7. Did that and realised the configurations (x86, x64) were all over the place; there were even Itanium configs in there for some reason. Cleaned it all up.

Stuck a break point in the uploader source and immediately found the problem: the computer name it was expecting was different, so it bailed out.

When I created the Database Uploader console app, I put a quick 'n dirty check in there to ensure that it only runs on my PC. Turns out I hadn't changed the name of the PC when I installed Windows a couple of months back.

Fixed that and everything ran as before.

This got me thinking about doing a bit of work on the "next generation" of Comica (the editor is really nice!) - except it would have to be free, and then the thinking stopped right there. Ya can't live on free, son.

Jul
29

FileSieve 4.21 2017

As an excuse to use this new keyboard, I was going to rewrite a part of the FileSieve documentation but then I realised I didn't do a blog post for today. So here I am.

Today was spent working on FileSieve and getting command-line automation happening.

As part of my App Framework library, the Parameters class provided all the functionality I needed to get things moving fast. It was simply a case of reiterating over the Parameters.List collection and performing commands (aliases are also supported) based on what was encountered.

Due to this iterative nature, FileSieve can executes multiple commands from the command-line in sequence. So, for example: you can select a profile, start it, and then select another profile and start that, even making changes to it - and only it - beforehand.

The first added command was Profile, which is used like so:

-profile="My Profile"

This makes the GUI select the My Profile profile and make it active. All following commands are then executed on that profile.

Most of the commands emulate using the application's interface, such as RadioButton.PerformClick(). There's additional sanity-checking in there as it's accepting input from the user, but there really isn't much to it.

I did wonder about adding generic automation to the App Framework for all of my software, but it'll still take manual work to specify what's what. Probably isn't worth it, to be honest. Although I think Wake On LAN Ex will benefit from automation.

The 4.22 release will feature additional commands that aren't critical to using FileSieve from the command-line.

Oh, speaking of the command-line: the nomenclature has been changed from Command-Line to Automation. The reason being that I'd like to also add support for automating FileSieve usage via a text file. It'll basically be a top-to-bottom list of commands and parameters that FS iterates through executing one at a time.

To help with any debugging issues on the user's part, all automotive actions and their outcomes are logged under the Automation category in the Log window.

FileSieve 4.21 is available from FileSieve.com.

Jul
28

Broken Pagination 2017

I was supposed to be doing smallish posts for this blog and so setting pagination to 40 posts per page seemed like a good number.

Except it didn't turn out that way; the posts are tending towards pretty large and so 40 posts was way too much. Far too much vertical text.

So I changed it to 20.

And then sorting broke.

When I originally started this blog rewrite, I couldn't get the posts returned in exactly the correct order due to the way collections et al work in Laravel, and I finally ended up doing a reverse() within the actual Blade template that displays all of the posts.

I then made changes to the Controller to reverse the results and in combination with the pagination, it went a bit... weird. Some more tarting around later yielded nothing helpful.

I remembered the stupid reverse(), ripped it out and - tada!

Now pagination is set to 10 posts per page.

Jul
27

Assembler, part 7 2017

Haven't quite gone ahead with actually executing instructions as yet because I re-worked the way a "machine" is implemented.

I ended-up ripping out the hard coded properties and features and made everything generic. There's now a set of base classes that are used for implementing the CPU, Registers, Memory, and Mnemonics.

+ BaseMachine
  + Cpu
      Registers
      Mnemonics
  + Memory
      Map

The first machine being implemented (as said from the very start) is the Motorola 68000. It's the first CPU I've used assembler with back in, ooh, 1995, maybe? It's also simpler and makes more sense than today's CPUs. Don't wanna go making things harder for myself.

Registers

The potential issue here is that registers are now loosely typed. I'm not sure how to go about implementing the usp and ssp registers. The pc (Program Counter) register can be added to the base class as all CPUs will require one. Not entirely sure what it will count, though.

When a new register is added to the Registers collection, you need to specify its base name, such as D (for a Data reg) or A (or an Address one). An index is automatically applied. The D, in this case, doesn't actually mean anything as far as the program is concerned. You can call the register(s) FloppyJobbies instead, if you wanted.

Anyway! If you wanted to add 8 Data registers, you'd do the following:

AddRegister("D", 8)

This will create 8 registers, all named D0 to D7. Basically, the index is applied directly after the base name.

Do CPUs only really have (general purpose) Data and Address registers? Could I replace the literal with an enum, instead?

Fetching a register? Like so:

GetRegister(name)

With name being, say, "D6" to get the sixth Data register.

As I've (currently) implemented the Register collection as a list of type , I've added a Dictionary for caching purposes to save having to reiterate over the list each item a register is fetched. But, as registers are uniquely-named, I may just change the base collection to a Dictionary itself.

Mnemonics

No changes have been made to mnemonics.

Memory

This currently just has a Map array of Integers. Other than that, I haven't done any further work on memory. Registers, above, is the current focus.


Assembler, part 6

Okay, okay; can't put off doing the operand parsing any longer if I want this project to progress any further.

Just like the (incomplete) line-by-line parsing of the entered sourced, I'm going with Regular Expressions. Everything is going to be regular expressions; regular expressions all the way down.

As there's no specific reason why the source and destination operands should be treated differently and so a generic parsing method is used for determining what an operand consists of.

The Operand object has, among other things, a Type enum property that specifies the type (oh, my!) of operand. This Type dictates what occurs when the instruction is executed. Currently, the following types have been defined:

Unknown
ImmediateValue
Register
Address

There will no-doubt be more as I add parsing for additional features when I get the existing ones working. Types will certainly become more granular, such as specifying whether an Address is relative or absolute. Any BaseMnemonic-inherited class should be given as much information as possible to perform their function; there's no reason why they should need to perform any of their own interrogation.

The next big step is to have the Add mnemonic adding an immediate value to a register, but before that occurs, I'm going to need to sort out a couple of other things first.

Bit-work. All operations can work with either a byte, word, or long-word. Long-word is easy, but the other two will require bit manipulation of which I haven't really done much of in .NET.

Memory. Sure, the registers are currently just an integer(?) and so easy enough to work with, but what about addresses? There's not much point having address support if there's no memory to read/write with! I haven't really thought about this.

Initial thinking would be just to allocate an array that's a property of the BaseMachine class. I'm not going to add any CPU caches or anything of the sort as it won't make any performance difference as everything is so high level. Machine (memory, CPU, registers, etc) state will easily be serialisable and so can be "saved stated" for whatever reason.

Jul
26

Logitech G19 and the Corsair K95 RGB Platinum Mechanical Keyboard 2017

After forcing myself to use the Logitech G19 keyboard for the past two years, I've finally booted it right up the arse and replaced it with a proper mechanical keyboard. A Corsair K95 RGB Platinum (click here for US version).

I kept with the G19 because of two reasons.

Reason the 1st: The built-in LCD screen. Paired with my Like A G19 application, that LCD was really useful.

Reason the 2nd: It cost £150. I had to keep using that damn thing because it cost me so much.

I still found myself reading about mechanical keyboards every few months and which switches were the best. Incidentally, the Cherry MX Blue switches sounded like my kinda thang.

The other day I decided enough's enough, and I'd go ahead and buy a mechanical keyboard at long last. It arrived today, and I realised something: the Like A G19 app will be forever retired without anyone else ever seeing it. Hmm, can't really be having that.

I quickly made some source changes, wrote a Readme.txt and shoved it outta the door. I can't really stress this strong enough: Like A G19 has no support and no real future.

This is the first and last public release; unless someone gives me a big stack of cash, I'll no longer be updating it and I won't be releasing the source. The last twenty years have proven to me that releasing software for free is a terrible idea. I've also released source to applications before and nothing good ever comes of it, either. Anyway, it's tied in with my other libraries - source of which I'll never be releasing.

If you have a Logitech G15, G510, or a G19, and you'd like to make the built-in LCD a bit more than absolutely freakin' useless, take a look at Like A G19. It's free, but it's woefully incomplete. Reading the included .txt file is a must as it tells you how to use the Profile I myself was using these last two years.

Anyway, this K95 RGB Platinum? It's awesome. Weighs in at 1.35KG due to being made of aluminium and absolutely solid. The only issue though is that I personally wanted Cherry MX Blues, as I said above, but it only comes with either MX Brown or MX Speed. I chose the Brown, but I would've loved the clicky Blues. Oh well.

Oh, and as a bonus: I'm now using a proper UK layout. It turns out the G19 had a US layout, which meant the Enter key was only single height as opposed to the double height of a UK layout. Very annoying as I was never really able to get used to it even after a couple of years.

Below is a photo of the keyboard, along with the WASD key-caps that I changed - they're included in the box along with a key-cap puller and additional QWERTY caps. They're sloped and have a textured finished.

Jul
25

Donation Page 2017

While I was fixing up an application that I hadn't worked on in a while, I noticed that it linked to a donation page on the previous blog. A donation page that no longer existed when I revamped things; I've just been sorting that out.

There's now a dedicated donate page and a link to it at the top of this very page.

I'm honestly not really expecting much from it as my software was donation-ware for almost 20 years and, well, it didn't exactly go very well. This forced me to finally start writing commercial software and stop giving it away for free. Well, there are "free editions" available so they can still be used for free if you don't require the more advanced features (and aren't particularly bothered about supporting the software). I couldn't bring myself to put the software entirely behind a paywall.

Shame, really.

(Incidentally, this is why there isn't a "next generation" of Comica as I can't really charge for it and I can no longer give away software for free)

Jul
24

Assembler, part 5 2017

In the previous version, Assembler parsed down the entered code into Instructions which contained an enum for denoting the type of that instruction. For example, Move being set as the property would mean it was a Move instruction.

Now that property has been removed and all Instructions inherit from BaseMnemonic (and some other interface). So, the Move instruction is now its own Move class.

All mnemonics for a CPU are defined within a Mnemonics collection when a Machine is instantiated (along with registers and such within the CPU class); there's (currently) a method that allows the mapping of a textual mnemonic to its class counterpart during the parsing stage; this may later be changed to a Dictionary or something.

Some limited parsing is in for determining what the source and destination operands consist of. This is the most complex part as those operands can contain everything from a plain immediate value to relative addressing.

Because of this, each instruction will have to maintain metadata on exactly what's going on within that instruction; having to parse more than once to later on to determine what needs to happen is silly, so lots of metadata is required. As a bonus, we'll get a ton of helpful debugging info for "free" when we implement all that gubbins.

On the interface side of things (c'mon, like I can resist UI work) the syntax highlighting now colourises the datatype (or size as is the actual term) for mnemonics. Turned out this was achievable via making the datatypes an operator when it comes to highlighting as they don't need to be on word boundaries - thanks to Rob for the suggestion. Still more highlighting work required.

The Registers window now has a trace of what it parsed from the entered source code and displays the interpreted code. Changed the font to a mono-space one as the other just looked messy when registers' widths didn't line up. Sorry Segoe UI - not this time.

Editor and Registers