Tuesday, December 31, 2013

FMod - Yay, Galaxy Levels!

List of compression types which I never want to hear about again: {LZW, Carmack}

It is really awful when documentation is inaccurate, inconsistent, and confusing. I did finally manage to navigate and experiment enough with the gamemaps format to make it work! To start out, I made things easier for myself in the future: I changed the compression/decompression algorithms to take in a reference to an output stream instead of creating a new stream and returning that.

Something I missed when reading the documentation was that the address mentioned by a Cramack far pointer needs to be multiplied by two because it's in words. Two of the three documents I read made no mention of that and the one that did, did so very unobviously. With that done, I was able to load and resave gamemaps and maphead successfully!

Next up is Galaxy graphics, which includes Huffman compression. I have absolutely no idea how that works, but I have set up some nice interfaces and classes for the strange chunk handling.

Monday, December 30, 2013

FMod - Galaxy Levels are Complicated

This FMod development series is monopolizing my blog. It will probably take a break when I resume classes in a week. Until then, old file formats engage!

Despite my tendency to busy myself with many projects at once, within each of those I focus on one task. Continuing from yesterday, I worked on the Galaxy level class. After a more careful read of the existing documentation, I discovered that my Carmack decompressor was incorrect. After changing it to use the right order of bytes, it expanded the chunks much more sensibly. However, there was another problem: some extra bytes are present between the address referenced in the level header and the apparent start of actual data. I determined the offset to be 8, but soon ran into the problem of decompression flags pointing to negative addresses. After digging through ever more obscure documentation, I discovered that four of my eight offset bytes had a purpose: decompressed length. The other four were actually part of the important data; I had dismissed them because they didn't represent the first tile - they were an RLEW flag. After adjusting my reader and writer accordingly, it worked a lot better. I still have one problem left to work out: it starts behaving unpredictably after encountering a far reference.

Sunday, December 29, 2013

FMod - Galaxy Levels

With basically all the Vorticons resources done, I figured it was time to move on to Galaxy modding. As I started in Vorticons with levels, I figured it would be good to do that with Galaxy as well. The game maps file is just a single file containing multiple levels, so I created two classes: one for the collection and one for a single level. With a new format came (of course) another compression method, this one called Carmack. It's very easy to decompress, but considerably difficult to compress. Fortunately, unlike LZW, it doesn't have to be compressed to maximum efficiency.

The decompressor appears to work well and my temporary compressor just escapes the flags instead of actually compressing. It can load all the level information from maphead and the individual headers in gamemaps, but I'm still uncertain as to whether it is reading level data correctly. Due to an issue with my handling of unsigned integers, resaving the maps collection does not work at all.

Saturday, December 28, 2013

FMod - No More LZW

If I ever see the letters "L", "Z", and "W" together in that order ever again in my life, I think I will scream.

Including my research today, I have discovered three incorrect implementation of the LZW compression algorithm. Surprisingly, I got correct results from, of all places, Wikipedia. My problem was that I was always using the newly generated code instead of emitting the code for the longest string already in the dictionary. With that done, Keen 1 accepted my compressed version with one problem: sprite colors planes were obviously offset. It turns out that Keen 2, against which I had been testing uncompressed IO, never had small-sprite aberrations. My handling of those was incorrect. After correcting that, everything worked great in Keen 1 - but trying to compress the graphics of Keen 2 resulted in something incredibly messed up. Apparently, the "decompressing graphics" message shown by Keen 2 never actually decompressed the graphics; they removed that functionality for the later games. I'll just have to not compress those games' graphics.

LZW: done. Next up: Carmack.

Friday, December 27, 2013

FMod - EGA Recompilation

The EGA format is surprisingly very simple. It doesn't require crazy bit-nonaligned IO, just shuffling some bits into different groups. That only has to be done at the end, so before then, I can just worry about putting the right color bytes down. Just as I expected, the header is written last, compiled from a list of entries generated while copying image data. It worked almost perfectly the first time. I had assumed, under the guidance of an online file format, that I could leave the smooth movement sprite duplicates to Keen. That was not the case. Actually duplicating the entry fixed the clipping problem.

However, when I tested the VortGraphics ToFiles method with compression, it failed in the most annoying way possible: it only partially succeeded. The tiles are only partially corrupted; I can still see the outline of the items and some of the color planes are correct. However, without looking closely, everything looks like garbage. I rewrote the core of the compression algorithm according to a different online guide and it still fails similarly. Just when I thought I was done with LZW...

FMod - The Vorticons EGA Reader

It's very difficult to follow file format specifications when they're wrong. This problem occurs semi-frequently when using community-produced documentation for old games like Commander Keen. Therefore, creating the EGA graphics exporter of FMod was challenging. First, the least significant bit in the header's compression flags does not tell whether that header is compressed; it refers to the latch file - the header is never compressed because that would be impossible.

Also, the tileset is not one big bitmap. It is actually about six hundred small 16x16 pixel bitmaps (32 rows each). If you try to read it as a large bitmap, you will spray rows nonsensically throughout the tile array.

Fortunately, those errors were the extent of the confusion. It was actually pretty easy to read the separate color planes into a more easily accessible array and then use that to put together the rows. The extractor first reads the header to get all the information about each entry and then puts each into the VortGraphics instance's appropriate list.

For my test program, I just had it use my ToFile method of the bitmap class on each of the graphics entries. I was shocked when it worked almost perfectly the first time. (The tiles were corrupted as I mentioned above, but that was an easy fix.) Tomorrow, recompilation of the three EGA files!

Wednesday, December 25, 2013

FMod - LZW Done

I have definitely had enough LZW compression for a while. Today, I modified the decompression algorithm to use byte arrays instead of strings and bytes instead of booleans (booleans always take four bytes). That was easy, but there was still one major thing left to do: compression.

Since I am now very familiar with the LZW way, compression was not as difficult. It did, however, require consulting a few more sources for examples in other languages. It didn't help that the site I referenced for decompression had an incorrect algorithm for compression. I did not heed the Internet's suggestions to use a real dictionary or any kind of hashing, instead using my trusty list of byte array. It required some more super inline lambdas to make accessing it work, but it's pretty fast.

Bit-level IO is done in the opposite order as decompression; it reads the input by bytes and keeps an output list of bits, which is shoved into bytes when the output is finalized.

Check it out - Keen LZW compressor in VB.NET

Tuesday, December 24, 2013

FMod - LZW Decompression

It took me two days total, but I finally got an LZW decompression algorithm for the Keen EGA format working in Visual Basic. It uses all manner of crazy stuff, from bit lists to multiline lambdas. It could definitely use some cleaning up and refactoring; during my work I switched from byte arrays to strings.

It successfully decompressed Keen 1's "egalatch" and "egasprit" files, which the game accepted after I changed the "egahead" compression flag manually. Tomorrow, I will do my refactoring on the decompressor and implement compression, which hopefully will be easier.

View the algorithm on PasteBin

Monday, December 23, 2013

FMod - LZW Rage

After opening a gazillion tabs about file formats in my browser, I got to work this morning on the EGA graphics and LZW compression format. The first order of business was to get a quick mock-up of the header ready in the FromFiles method of the new VortGraphics class. With that ready, I put on my pay attention face and added a DecompressLZW method to my compression library.

It took me an hour just to get any idea of what LZW is even supposed to do. I found three different algorithms, two of which were psuedocode and one of which was in C. (I did later find a really messy un-object-oriented one in QuickBasic.) At first I was going to use an jagged array of bytes to manage the dictionary, but realized that would become terrible with the extended-bit entries and changed it to a dictionary of unsigned integer and byte array.

Since bit operations are truly awful in high-level languages, I created a list of booleans to store the each bit. Later, thinking that was a waste of memory, I created a bit getter lambda (which are the super inline functions I wanted) to find a single bit in the data stream. That failed due to weird side effects of the overloaded And operator. So, I created an inline iterator function to figure out the bits as I needed them. That failed because some buffering thing done automatically caused it to read more bytes and get out of sync. At the end of my fiddling with the data handling, it was back to the boolean bit list.

I ran into all kinds of problems with dictionary keys. First, it was crashing with KeyNotFoundException immediately after preemptively adding the value for that key. Then, after I did some value remembering stuff, it crashed with NullReferenceException in the outputter section. Tweaking the data reading loop to accommodate that just resulted in early exit.

The core algorithm has been rewritten at least four times. I have been working with Visual Studio, XVI32, and Keen on this the entire day. It is still not working.

Sunday, December 22, 2013

FMod - Bitmap

I was right. FMod is going to usurp all my free time for the next few months. Sigh... let's dev!

Since it will probably become important at some point, I wrote a class to encapsulate a 16-color (4-bit) bitmap that doesn't really conform to any standard but Keen's. That was exceedingly painful because [1] two pixels are packed into each byte, [2] each row has to be a multiple of four bytes - not pixels - long, which wouldn't be so bad if it weren't for the fact that [3] the entire thing is actually stored upside down - but still left to right. The first problem I encountered was that the bottom image was interspersed with black horizontal lines and made the entire image. It didn't take terribly long to figure out that I had made an error in calculating the start of a new line of pixels. However, the next problem was much more painful: assigned pixels were being shifted to the left one. It took literally two hours of messing with ten lines of loop code to make any headway on it. The shift was fixed by adding calls to Math.Ceiling in various places, but then I was stuck with a black vertical line on the left. Fortunately, a little more shuffling of "+1", "-1", "*2", and "/2" fixed it.

With the bitmap class working well, I ripped the compression algorithms out of the level IO code and into their own reusable module. That module will later contain implementations of LZW and Carmack compression.

Saturday, December 21, 2013

FMod - Just a Side Project

Time to start another large project! Now I have four ongoing: HigherPower (suspended until Forge updates), Logofrag (never made it to the add frag screen), NetBLAM (unsure where to go now), and this.

What's this? It's FMod: a total mod creator for Commander Keen. My vision is for this to be able to do all operations necessary to creating a Keen mod - tiles, levels, sprites, texts, behaviors, and other miscellaneous stuff. I really want this to just be a side project that I work on when I genuinely don't have anything else to do. Unfortunately, it will probably usurp all my free time like my other projects initially did.

Anyway, I started by creating a class for Vorticons-engine levels. Since it was essentially ripped from FleexCore, it wasn't that hard to write the original code. The trouble came when I tried to remove extraneous functionality and use streams instead of VB6-style files for the IO. I deleted a bunch of unnecessary code, cleaning it up quite a bit. In the process, I moved all the number-shifting functions (e.g. converting an unsigned 16-bit integer to a byte array for writing) to their own module, accessible to any class.

When I tested the new class, it worked - kind of. When it resaved the level, everything was shifted two tiles to the right. I had no idea what was going on, but continued adjustments to various numbers and addresses created a different problem. Tiles weren't shifted, but sprites were going completely crazy, having a million junk sprites covering the top half of the level, shifting the real ones down. It took a hex editor and Mindbelt to figure it out, but I finally noticed that I had forgotten to multiply the area by two in calculating the plane size. With that fixed, the test succeeded. It's very important to remember variable sizes.

Here we go!

Robotics - Smoking Pointers

Though there was a robotics meeting this Wednesday, I didn't log it here because I had more interesting thoughts to put here instead.

Since it was the first day of finals, there were not very many people there. In fact, it was just me, the supervisor, and a builder. The builder wasn't doing much of anything when I arrived; there really was not much to be done without the input of the lead builder. He left, leaving just me and the supervisor. As I am not a builder, I couldn't do anything at all (besides adjust a little bit of wiring). I did some poking around in the intrinsics definitions and learned all manner of interesting things about how RobotC does stuff. I finished coding my attempt at circumventing the field control system, which I began testing at the prompting of the mentor. It used jumps to hardcoded pointers in addition to all manner of other terrible stuff, so I really didn't expect it to work. However, it definitely did. Ending the program in the debugger failed to stop the motors, resulting in some smoke.

After those tests, an engineer from John Deere arrived to help us. We did some fiddling with the hanger bar, but discovered its motors could not maintain the position and trying to do so resulted in bowing of the channels. Since my attempts at end-of-game circumvention were uncontrollable, they were abandoned and we still have a lot of work left to do.

Thursday, December 19, 2013

Super Inline Functions?

I did some more thinking about what would be awesome to have in .NET and remembered something about my new implementation of SupaChat Server. For a lot of the commands, it tries to find a group object for a group ID specified somewhere in the arguments array. Therefore, I have to have code like this in those case blocks:

Dim TargetGroup As Group = Groups.Find(Function(g) g.ID = _
 Args(1))
If TargetGroup Is Nothing Then
 Sender.SendData("*G* Group doesn't exist!")
 Return
End If
If Not Sender.RepUser.InGroup(TargetGroup) Then
 Sender.SendData("*G* You're not there!")
 Return
End If

In addition to being simplified by the breaker subs I talked about last time, this is kind of a pain and is very repetitive. I would like to always define variables for things like the target group, target user, and sending rank and have them only set by one line - a "set-up" call if you will. However, that would require a new kind of inline sub. It's hard to explain, but I was thinking of something like this:

Breakable Sub HandleCommand(Command As String, Args() As String)
 Dim TargetGroup As Group
 ' other variables
 Inline Breaker(1) Sub GetGroup(ByInline TargetGroup As Group, _
  ArgPos As Integer, NeedsPresent As Boolean)
  TargetGroup = Groups.Find(Function(g) g.ID = Args(ArgPos))
  ' etc from code in last section
 End Sub
 Select Case UCase(Command)
  Case "LEAVEGROUP"
   GetGroup(1, True)
   ' other instructions
  ' other commands
 End Select
 ' other stuff
End Sub

That "inline" sub inside the command handler sub is only visible and runnable in the context of that one sub. Variables passed ByInline pass a double-strong pointer, so setting where it points inside the inline sub would change what it points to back in the root sub. Inline subs must appear after all local variables they use. When invoking inline subs, ByInline parameters cannot be specified; they are taken from the current accessible variable set.

This would be an amazing feature. Get on it, Microsoft!

Wednesday, December 18, 2013

Force Multiple Returns - "Breakers"

I would really, really like a way in .NET to unwind the stack twice in a return-like statement. This would be exceedingly useful in request handling methods that check some conditions and exit the big handler if the check fails. There is currently no way to do this without inserting "if check is false then exit" everywhere. It's even more of a pain in ASP .NET applications that require the request to be aborted if the page will not be fully served.

Sub Page_Load() Handles Me.Load
 If Not IsUserAdmin(Session("UserID")) Then
  Response.Redirect("PermissionDenied.html")
  Exit Sub
 End If
 ' actual page loading stuff
End Sub

Here, it would be excellent if the check function could cancel the Page_Load routine. (It might be necessary to pass the Response variable to an auth function.) I was thinking something like this:

Breaker(1) Sub EnsureUserAdmin(ID As Integer, _
 Handler As HttpResponse)
 If Not IsUserAdmin(ID) Then
  Handler.Redirect("PermissionDenied.html")
  Break 1
 End If
End Sub

Breakable Sub Page_Load() Handles Me.Load
 EnsureUserAdmin(Session("UserID"), Response)
 ' administrative things
End Sub

The parameter to the Breaker keyword specifies how many frames up the stack the method can break. The Breakable keyword flags the method as being able to use breaker methods.

I realize it's kind of redundant for void returners as they could be changed into Booleans, but for functions that can actually have a useful output, it would be a real pain to use a composite/nullable structure. Please, Microsoft?

Tuesday, December 17, 2013

Watch out for Shadows

While messing around with types for a personal project, I ran into some unusual problems involving the Shadows operator. For background, let me explain that I had two classes, one of which extended the other, each of which containing an identically named class that would hold additional data for it. I wanted one class to override the other in the derived class, thereby swapping out the data type of that extra storage field. Since classes can't be declared Overloads, I settled for Shadows, which seems to have the same effect. I applied it to both the class and the field.

But it doesn't! Members declared Shadows will only be called if the invocation is on an object that is strictly known to be of the derived type! I was actually declaring two fields with an identical name but different data types. When I used the polymorphic approach and simply read from the field, I was only accessing the field declared by the superclass, never the subclass.

Shadows is not the same as Overloads. Make sure you know you're creating two different members when using it. In my case, the issue was solved by changing the field to a property and giving the conflicting members (both class and field) different names. Then, I could just have the subclass report its own field of its own data type.

Monday, December 16, 2013

Assembler Simulator

I was reading about old assembly code today and I thought "I would really like to see how drastic these crazy speed tweaks are!" I don't have access to an assembler or a machine slow enough to let me notice, so I decided it would be a good idea for someone to build a program that simulates running assembler code on various old CPUs. It would be fine if it was in some high-level language; I just want to be able to control the clock speed and watch memory locations. There should be readouts for the registers and a display corresponding to a graphics memory location. Of course, all of this would be simulated - but it would make perusing old documentation so much more interesting. I just might make this.

Sunday, December 15, 2013

Crushers - Seedy

I was in the mood to play a little Crushers today. Shortly after playing a few games, I was in the mood to make some additions and changes to it. First, I fixed a bug that allowed the player to suffocate in thin yet open areas. After I saw some amazing events unfold in-game, I decided that I wanted a way to seed the RNG with a value that would cause it to repeat all the block-related events. It took me quite a while to figure out that, if I wanted block falls to be repeatable, player actions could not be sources of randomness. Once I got the idea, it was trivial to remove randomness from the oxygen particles and add a seed dialog to the main menu. Now, players can replay awesome situations!

Saturday, December 14, 2013

Robotics - A Little Trim

We were again very understaffed at the robotics team meeting today. There was, fortunately, one more person - a builder - present. I was alone for the first few minutes and finished up our wiring changes. The rest of the time was used to switch out the gears - getting us under the height limit - and to cut off the very ends of the flag raiser which were hitting the hanger bar. I also adjusted the programming in an attempt to keep motors running after the end of the tele-op period.

Friday, December 13, 2013

Robotics - Wires Everywhere

As there was only one other person at today's robotics meeting, not a whole lot was done. Since neither of us is actually on the build team, pretty much nothing got done. We did, however, figure out how to use wire crimpers to extend some tightly-strung cables, routing them along the metal beams. We also discovered a problem that caused the flag turner to yank the cables out of the hanger bar, which was also fixed by making the wires longer and getting them out of the way. Hopefully, more people will be at tomorrow's meeting so we can actually attach stuff.

Wednesday, December 11, 2013

Robotics - Redesign Again

Over the last few weeks, we have yet again revamped our robot's layout. Since we decided not to use the conveyor belt as a block-moving mechanism, it has been coerced into a tank-like movement system. The center of the robot has been cleared out and replaced with a swingable bar controlled by two motors, which we use to hang! The flag raiser, due to length constraints, has been flipped around and now points forward. It's somewhat difficult to set it up in such a way that it doesn't interfere with the hanger bar or our many cables. Surprisingly, pretty much everything worked on our first run of the new system; we just need to reaffix the crate and find a permanent place for the battery.

Saturday, December 7, 2013

The CLI/CIL/CLS/CTS Specification

Most .NET programmers aren't aware that it's compatible with other languages that we don't usually consider part of that family, like Mono. This is because its written assemblies and execution environment are standard - set by Microsoft and quite a few other companies. The spec provides details on the Common Language Specification, the Common Intermediary Language, the Common Type System, in addition to a lot of helpful tips for programmers. The thing, at its heart, is comprised of a list of rules for compilers and translators that, if followed, guarantee security and compatibility. The ECMA also packages an XML file than contains information on all necessary base classes.

ECMA page
Direct PDF link
Mirrored BCL XML

Friday, December 6, 2013

RSS MP3 Downloader

A lot of RSS feeds always contain an attached MP3 file, like podcasts. It's very difficult, if not impossible, to download them all at once without manually initiated every download. I don't know of any browser that is good at handling RSS that it can do so for multiple different feeds.

I encountered this issue while trying to fetch all podcasts from Reasons to Believe and therefore invented RTBDownload. It's a tiny little application that takes a folder path and an RSS XML file, parsing it for titles and file links. It then downloads all the MP3 files and places them in the folder you specify.

RTBDownload for Windows 7 and above

When it launches, navigate to the folder you want to put them all in, paste the URL of the XML file (with Edit -> Paste), and press Enter. It will inform you when it begins downloading each file. It is possible to run multiple instances of it downloading different feeds.

Thursday, December 5, 2013

F#

I saw the name of F# in my Visual Studio add-ons dialog today and it made me remember how interesting that language is. I can't write anything it it without extensively using reference material, but it appears very powerful and very well integrated with the CLI. A while ago, I thought it was Microsoft's answer to R, but that does not appear to be the case. It is more like a .NET-compliant version of Haskell with more object-oriented features.

Some of its most interesting abilities are its handlings of the functional pattern. Types are handled in a way less painful than in VB and even more flexibly than in C#. However, the nature of variables and assignments to them seems a little bit strange, at least from my VB perspective.

Who should use F#? I'm not sure, to be honest. It does look like a good language to know should you ever stumble upon an amazing possible use of it.

Tuesday, December 3, 2013

Do Not Use - Pixela Camera Utilities

Canon "FS" video cameras ship with a whole ton of software installation discs. The cameras are great, the software not so much. This is similar to the junk you get when purchasing a new computer from most big-name companies: not-so-great video editors, default music files, and generally useless stuff. It's true that one of those utilities is "necessary" to transfer the video files from the camera, but there's another, probably cheaper, way to do it. Instead of buying all those discs (I'm fairly certain it's actually optional), just get a USB-adapted SD card reader. Pop the card out of the camera, connect it through the reader, and copy the video files out with Explorer. Much cheaper, less junkware.

Monday, December 2, 2013

.NET - Writing Your Own .NET Compiler

Reflection in .NET is exceedingly easy. It's also incredibly versatile; in fact, it's possible to create new classes, methods, and other fancy stuff with the *Builder classes. Add those to an Assembly and you've got yourself an entire library in memory. There's one method that makes it all even more amazing: the Save method on AssemblyBuilder. It will take all the dynamically generated code and dump it into a legit .NET library on your hard drive. I think you can even make DLLs by specifying the appropriate options in AppDomain.DefineDynamicAssembly.

So, if you're good at using ILGenerator, you can take in a text file, do whatever parsing and understanding you need, create the appropriate classes and method bodies on the fly, and create a new CLI-compliant executable. This is, essentially, a compiler. Learn more by reading the documentation on the types in System.Reflection!

Sunday, December 1, 2013

Do Not Use - Print Shop Pro

Broderbund Print Shop Pro is a pretty nice application. It contains a huge amount of templates for printing on and designing for special papers types in addition to having a massive library of clip art-like stuff. However, it really messes with your system when you actually go to print. The times I have attempted to use it, my printer spooler went insane. I don't remember what I had to do to fix it, but it was awful. There's got to be another good way to lay out labels and special documents - PSP just breaks stuff.

Friday, November 29, 2013

FTB Unleashed - Tinker's Construct Smelting, Casts, and Patterns

Tinker's Construct is a remarkably well documented mod compared to most Minecraft mods, especially those in FTB. In fact, it even gives you pretty awesome in-game manuals. However, it took me forever to figure out what you actually have to do to get making custom tools.

As you probably gathered from the first in-game book, you need some workshop blocks. However, what you might not have understood is that, to start out, you just need a Stencil Table, Part Builder, and Tool Station. They're all just wood. Make a couple of spare blank patterns as well.

Shove a blank pattern in the Stencil Table and click Next and/or Previous until you find a fragment that looks useful (I recommend pickaxe head). Take it out. Shove that into a square slot in the Part Builder and some wood or cobble in the ingot-like slot. Take the new piece out. This does not work with metals. For metal, you need a Smeltery. You can do similar things using just this set-up to make pretty lame composite tools if you figure out the Tool Station. In the Tool Station, you click the type of tool you want to make on the left and then put in the components in the slots which will appear.

However, I think it's pretty easy to advance to the next stage: smelting. Gather a whole bunch of clay, sand, and gravel. Combine it into grout and smelt that into Seared Bricks. Create exactly 18 Seared Brick blocks, 1 Smeltery Controller, 1 Seared Tank, 1 Seared Faucet, 1 Smeltery Drain, and 1 Casting Table. Put a 3x3 square of the Seared Brick blocks on the ground to start. Then, up one level and not directly above the bricks, place the Controller, Tank, and Drain facing in. Complete a ring around the outside (corners unnecessary) with the rest of the bricks. Attach the Faucet to the outside of the Drain and place the Casting Table directly underneath it.

Once that's all done, grab a bucket of lava and use it on the Tank. It should light up the Controller as well. You now have a functional Smeltery! Now, find those tool parts you made earlier and right-click the Casting Table with one. It should insert itself. Pop in 2 gold ingots or 1 ore into the Controller and let it melt. Right-click the Faucet and the liquid should pour into the Table. If you've set things up correctly, it will cool after three seconds, producing a solid cast around the part. Pop both of them out, and you have a cast! I'm fairly certain you can just throw out the cheap part.

Now, it's time to make a part with metal. If your Smeltery still had liquid metal in it, break and replace the Controller. Casts must be filled with a different material than was used to make them. Put in metal of your choice (I did iron the first time). Pop the cast back into the Casting Table and, once the metal is liquid, right-click the Faucet. If it doesn't cool into the part after a few seconds, put in more metal. Once solid, pop both of them out and you have a metal part!

Once you've made enough parts for a tool, put them together in the Tool Station. You can also modify them there by adding unusual substances found in the second book you got.

Wednesday, November 27, 2013

Creating Extension Methods in VB .NET

An "extension method" is a method of a class or interface that is actually defined in a different module, usually by a different author. They are usually used to "extend" the functionality of existing types without creating new ones.

In C#, creating extension methods is pretty easy. Simply put a "this" before the type on the first argument, which indicates that it is the instance on which the method is running. In VB, it's slightly different but still pretty simple. First, import System.Runtime.CompilerServices at the top of the file containing the module. Then, apply the <Extension> attribute to the Sub or Function. When writing the method body, write as if the first argument is the current object. It obviously has to be the same type as the type to which you'd like to apply the extension.

Here's one I like to add to the string type:

Imports System.Runtime.CompilerServices

Module Extensions
 <Extension> Public Function EqCaseless(This As String, _
  Other As String) As Boolean
  Return String.Equals(This, Other, _
   StringComparison.InvariantCultureIgnoreCase)
 End Sub
End Module

Then, I can compare strings caselessly like this:

If input.EqCaseless("splosions") Then End

Tuesday, November 26, 2013

Fixing SupaChat

A couple of years ago, I wrote a chat server called SupaChat Server and a lightweight client for it. A project I did for World Literature - a Beowulf text-based RPG as a SupaChat Server snap-in - reminded me of it. Like I wrote a few weeks ago, it's really not that bad. However, it has a major problem. Instead of multithreading it myself, I just had timers in the main form that triggered read and ping events. While it was pinging all the clients and actually waiting for a reply, no messages would be processed. That caused all manner of ping timeout disconnections (especially because it happened every three seconds) in my presentation. I then decided that I should refactor it to resolve those problems. It'll take a lot of rewriting to implement a proper threading and queue system, but the server should run a lot better.

Monday, November 25, 2013

Tour of Interesting Registry Places, Part II

Open up your Registry Editor or registry inspector of your choice and check out these cool places in Windows! All of these things start in \HKCU\Software\Microsoft\Windows\CurrentVersion
  • \AccountPicture points to, obviously, your account picture, but also your name. Your name doesn't have to be the same as the name of your Microsoft account. Those parts are stored in FirstName and LastName, both of which will be overridden if DisplayName is not blank.
  • \Authentication\LogonUI\Notifications\Badge contains one folder for each application that can display a notification on the lock screen. There are keys for the version, rank in the list, and what looks like a COM+ package descriptor.
  • \Explorer\Advanced has settings for Windows Explorer that aren't usually accessible. Most of them seem to be Booleans, but there are some that take integers, all as a REG_DWORD. Notable are DontPrettyPath, IconsOnly, ServerAdminUI, and ShowInfoTip.
  • \Explorer\BitBucket\Volume\ keeps the Recycle Bin settings for your drives, each of which gets its own folder. Each folder contains MaxCapacity, the number of megabytes your RB can hold, and NukeOnDelete, which specifies whether or not to permadelete all the time.
  • \Explorer\FileExts, which might be the target of HKCR, manages the "Open With" list for each file extension. It can contain the folders OpenWithList and OpenWithProgids for each extension. In OpenWithList, MRUList is a list of characters, the key named by each of which contains one entry. OpenWithProgids contains the friendly name of the file type.
  • \Explorer\Ribbon contains QatItems, an XML string stored as a REG_BINARY. It appears to be where the Explorer ribbon loads its items from.
  • \Explorer\RunMRU lists the autocomplete items in the Run box, stored in a manner similar to that of OpenWithList under FileExts.
  • \Policies\Explorer has a single entry, NoDriveTypeAutoRun. I'm fairly certain it will switch off auto-run for all removable drives, a wise security measure.

Sunday, November 24, 2013

Tour of Interesting Registry Places, Part I

The Windows Registry was an idea that looked really good on paper and is moderately decent in practice. Over the years, it has become a convoluted place full of no-ops, interesting structures, settings that you can't find anywhere else, and a whole lot of confusing keys. I did a little poking around there today and discovered that it is pretty awesome just to see what you can do there. Let's do a tour!

All you need is a copy of Windows! Even a fresh install should have the structure and a lot of stuff in place. To begin our tour, launch the Registry Editor by typing "regedit" in the Run box (press Windows+R). If you've had it open before, collapse the open keys to start from the beginning.

  • HKCU\Environment contains your environment variables. An example of these is PATH. You can add REG_SZ values to allow expansion of %pathvariables% in the Address Bar.
  • HKCU\Control Panel\Colors specifies the RGB colors of Windows controls in various states. They are stores as REG_SZ which consist of three numbers (red, green, blue) delimited by spaces. Adding new entries won't do anything.
  • HKCU\Control Panel\Mouse contains settings that are usually configured with the Mouse dialog in Control Panel. However, you can also set the rectangle in which a second click in rapid succession will count as a double click, whether the computer will beep when the mouse is clicked, and some other interesting things I don't know about. Most are numbers stored as REG_SZ.
  • HKCU\Console changes the visual properties of the command prompt. The most interesting entries are the ones beginning with "ColorTable", for they map the QuickBASIC/DOS 16 colors to RGB Windows colors. They are stored as REG_DWORD with only the last six hex digits used. Boolean flags in this folder are also REG_DWORD, simply 0x0 or 0x1.
As I continue exploring, I will write more!

Friday, November 22, 2013

Intro to Boolean Algebra: A PowerPoint

For a book presentation (on Randall Hyde's The Art of Assembly Language), I created a small PowerPoint to give an introduction to Boolean algebra. It requires some talking on stuff that's not actually on the screen, but is that not how presentations are supposed to be? Anyway, it might be useful for a CS class. It starts with the 0/1 closedness and ends with minterms and simplification.

Download Ben Nordick's Intro to Boolean Algebra

Thursday, November 21, 2013

Install IIS on Windows XP without CD

IIS 6.0 is a very solid HTTP server (among a bunch of other Web-related services) that can be run on any Windows XP Pro computer. It's installation is usually pretty simple: Turn it on, put in your Windows install disc, and watch it install. However, you can't do the normal installation without your CD. After a little searching on the web, I have discovered a way by which IIS can be (legally) installed without having to track down that disc.

First, you'll need to download a disc image that contains the necessary files, for example this one for 32-bit SP2 (will work for installing IIS on SP3). Open a command prompt, navigate to the folder containing it and run it with the /extract switch with the destination folder path as an argument. An i386 folder will be created there, which will contain the files necessary to install IIS. Point the snap-in installer to that place and you'll be going!

Wednesday, November 20, 2013

Robotics - Focus Shift

We have determined after our disastrous failure at the first FTC qualifier that we need to change our focus. The block-moving conveyors, while pretty awesome, don't work that well. They require a lot of space and maintenance. However, one major thing makes us want to get rid of them: They don't score very many points at all. The bonuses in this game are so overpowered that actually taking blocks and putting them in the appropriate places is pointless. So, we are just going to have a little shelf-like thing that will dump the block we place on it into the infrared crate in the autonomous period. Even though only a few people were at today's meeting, the redesign has started. It should take only a few weeks to get the fixtures in and maybe another week or two to make them work well. Then, it's all practice and fine-tuning!

Monday, November 18, 2013

.NET - Guide to Server Basics, Part II

Now that you have a listener to catch new connections, it's time to actually communicate with them. I recommend another thread for reading in data. We'll use a queue of messages, but we'll need a new class to keep track of messages.

Public Class QueuedMessage
 Public Received As DateTime
 Public Data As String
 Public Sender As ClientCon
 Public Sub New(R As DateTime, D As String, S as ClientCon)
  Received = R
  Data = D
  Sender = ClientCon
 End Sub
End Class

Now we can make that queue and add data-reading and message-processing loops.

Public ProcessQueue As New List(Of QueuedMessage)
Public Sub ReadData()
 Do
  For Each c In Cons
   Try
    If Not c.Connected Then Exit Try
    Dim s As String = c.Reader.ReadLine()
    Dim msg As New QueuedMessage(Now, s, c)
    If Trim(s) <> "" Then ProcessQueue.Add(msg)
   Catch ex As Exception
   End Try
  Next
 Loop
End Sub
Public Sub ProcessLines()
 Do
  If ProcessQueue.Count > 0 Then
   Dim d As QueuedMessage = ProcessQueue(0)
   'Your handling code here using d
   ProcessQueue.RemoveAt(0)
  End If
 Loop
End Sub

Insert calls to start threads for those loops to the server's initialization sub. For convenience, I recommend having a writing sub in the connection class. Also, soon we'll need a time field to keep track of keep-alives.

Public LastKA As DateTime
Public Sub Send(Data As String)
 Writer.WriteLine(Data)
End Sub

Set the timer and give the client a little head start in the client acceptance code:

c.LastKA = Now.AddSeconds(5)

With that ready, insert a line into the data-reading loop that resets that field when data is received.

c.LastKA = Now

Prepare to enforce the timeout.

Public Sub Discon(Con As ClientCon)
 Con.Client.Close()
 Cons.Remove(Con)
End Sub

Finally, add a check loop sub.

Public Sub CheckKA()
 Do
  For Each c In Cons
   If c.LastKA.AddSeconds(10) < Now Then Discon(c)
  Next
 Loop
End Sub

Just make sure to have the client send updates or useless KA messages once every few seconds. I'm not sure what I'll cover next time.

Sunday, November 17, 2013

.NET - Guide to Server Basics, Part I

It's moderately difficult to create a server application for the first time. This guide should help you establish a listener and an array of connections.

First, you're going to need to import System.Net.Sockets and System.IO. System.Threading is useful if you want a multithreaded listener. I recommend creating a class to hold connection objects.

Class ClientCon
 Public Client As TcpClient
 Public Stream As NetworkStream
 Public Reader As StreamReader
 Public Writer As StreamWriter
End Class
Dim Cons As New List(Of ClientCon)

The collection of connections is helpful to check all the clients in one sweep. Declare a listener as a TcpListener. I usually create a server class to manage all the servery stuff.

Class Server
 Public ShutDown As Boolean
 Public Listen As TcpListener
 Public Sub StartListening(Port As Integer)
  Listen = New TcpListener(IPAddress.Any, Port)
  Listen.Start()
  ThreadPool.QueueUserWorkItem( _
   New WaitCallback(AddressOf Listener))
 End Sub
 Public Sub Listener()
  Do
   If Listen.Pending() Then
    Dim c As New ClientCon
    c.Client = Listen.AcceptTcpClient()
    c.Stream = c.Client.GetStream()
    c.Reader = New StreamReader(c.Stream)
    c.Writer = New StreamWriter(c.Stream)
    c.Writer.AutoFlush = True
    Cons.Add(c)
   End If
  Loop
 End Sub
End Class

Creating a new instance of that class and telling it to start listening will create a new thread that listens for client connections, accepts them, and puts them in the connection list.

Next post, we'll get some communication and keep-alives going.

Saturday, November 16, 2013

Robotics - The Qualifier, Take 1

Today was the first (of two) FTC qualifiers in which my team is enrolled. We woke up around 5 AM to drive for an hour and a half over to Mount Vernon, which contained the hosting school. For the first few hours, all we needed to do was walk around to the inspection stations, where volunteers looked at checklists and made sure our robots didn't have illegal component on them. I expected the software inspection to actually look at the code, but all they did was see that we were using a compatible firmware version on the NXT and that we had used the Program Chooser. Once all the inspections and judge interviews were complete, we walked around the maintenance area to see if other teams needed assistance - "gracious professionalism" as they say.

After a quick set of rules on what is allowed during the stages of tele-op mode, the matches began. Each team competed in six rounds, of which there were in total 36. Each round had two alliances, each composed of two teams, competing to score the most points. The team captain and I were drivers, he controlled mobility and I was at ops.

  1. We got to be in the first round of the day! Our partner didn't have an autonomous, so there were no collisions to worry about. However, when we went to raise the flag in the endgame, the motor simply did not run. I pressed all the buttons near there, including the reverse, but it failed. We lost.
  2. This time, our partner team did have an autonomous. Fortunately, they had an alternate version which didn't take them anywhere near us on the field. Between this and the last match, we made sure the flag raiser was working after recompiling. It worked great... and flew right out. So, we were again unable to raise the flag. It was close, but we lost.
  3. The autonomous situation was similar to that of our second match, which executed perfectly. Well, it actually collided with a member of the other alliance, but it didn't cause a problem. Later in the match, an axle in one of our wheels derailed, rendering us immobile and unable to raise the flag. We lost by a lot.
  4. Finally, we were put with a team that was very prepared. Both autonomous programs executed flawlessly, scoring a total of 80 points. The endgame plan was for us to raise the flag and our partner to pull up onto the bar. With around 40 seconds to go, one of our belts broke, rendering us unable to move blocks. As we approached the flag, that same belt broke into three pieces and fell off the robot, scattering fragments about. A few moments later, our robot tripped on one of those fragments and fell backwards, rendering it immobile. However, in a glorious sequence of events, our partner both raised the flag and performed a pull-up. Our first win was a total disaster!
  5. In this match, we were playing against the other team from our school. They had a great partner, but ours was not so well equipped. Things got even worse when our autonomous failed to execute. The disaster index continued to rise when the Samantha network got clogged, lagging all the robots at least a little but rendering ours uncontrollable. We scored essentially zero points, considering our partner had no autonomous anyway.
  6. After checking our Samantha and NXT connections, we were feeling a little better about our last match. Unfortunately, the controllers that we were supposed to pick up after the autonomous period ended were not placed correctly. So, our alliance's controllers were mixed up, resulting in chaos. Even once we got that sorted out, the lag and the lack of time remaining destroyed our chances. The other alliance won handily.
It was, in summary, a disaster. On the good side, we learned what's going to go on when we actually get serious for the February qualifier. Stay tuned for The Qualifier, Take 2!
During match three. The team captain is to the right of me.

The results as shown on the public display board.

Friday, November 15, 2013

Robotics - Down to the Wire

Similar to what I hear happened last year, we all stayed considerably longer than expected to finish the robot the night before a competition. This year, there were two factors that made it easier: we were all there and tomorrow's event isn't the last one. Tonight, the following things happened:

  • We tried to fix the autonomous program. It never worked particularly well, but it was being especially temperamental tonight. I ended up creating a simplified program that will score fewer points, but is hugely more reliable.
  • We actually got a flag raiser. It does its job, but requires both the driver and operations controller to be very precise about the approach. Despite its motor having emitted smoke for a while, there doesn't seem to be a problem.
  • The Samantha module made things difficult. I had to flash that thing not once, not twice, but three separate times during the meeting to keep the Wi-Fi link alive. Fortunately, at the actual competition, the inspectors will flash the module to their own network.
  • The height was a problem. Apparently, in our rush to make stuff work, we failed to notice that the robot was about a half-inch above the limit. To remedy this, a cam was put together by drilling holes through a place off to the side of the center of a wheel and attached to a motor. It was amazingly useful... until slamming into the guards destroyed the gear box. Our tests, however, demonstrated that we can still get blocks into the baskets.
It's not working as well as we had hoped, but it is working! After this qualifier, we will have a few months to refine our design and hopefully do a lot better the next time!

Thursday, November 14, 2013

Robotics - Autonomous Issues

With the robot's physical properties complete, all we have left to do before the competition on Saturday is to finish the autonomous routine. Despite my existing code being pretty good, what it actually did was pretty miserable. We spent an entire hour trying to get the first stage (drive up to the infrared beacon and dump the block into the container) working without much success. There is a strange bug in the code or intrinsics that causes unpredictable things to happen when both motors are moving backwards. It looks like tomorrow will be a late night.

Wednesday, November 13, 2013

Robotics - Belt Fixed

One of the semi-recent redesigns on the robot had the problem of the belts catching on the support beams below them. Today, we used the Dremel to cut off the portions of metal that were causing the issue. I also finished moving the code into the appropriate template and adjusting the autonomous period program. We're pretty much ready with the robot; we just need to practice driving and get the autonomous timers right.

Tuesday, November 12, 2013

Robotics - Templates and Finalization

I just discovered that, for the robot's code to be acceptable and legal, it needs to be based on templates that FTC gives out with RobotC. I had already made sure my code had the same function as these, but I hadn't actually used them. So, I spent the second half of the meeting copy-pasting code into the appropriate sections of the template. Since I figured the judges might like to read the code easily, I also inserted linebreaks and my own comments (eliding the original 10-line comment blocks that tell me nothing). The build team has the robot almost done, just a little bit of adjustment needs to be made to the belts. Once that's ready, we can start auditioning drivers.

Monday, November 11, 2013

Robotics - Crunch Time

It has just hit us that the FTC qualifier we are entered in is this Saturday: five days away. Our robot is still in a state of uncertainty. The design keeps changing to accommodate new problems, most recently our lack of another motor controller. Essentially, all we really need to get competition-ready is a method of getting the blocks off the ground and into our belt shaft. I'm working on getting the autonomous in a presentable state, which is going reasonably well. It would be going even better if I could test it: A recent redesign left no place for the battery array.

Sunday, November 10, 2013

Looking Back: SupaChat Server

As I develop the snap-in for SupaChat Server I mentioned last post, I'm finding a lot of issues with the software. Let's talk about it!

  • SupaChat Server was started by me in sixth grade after my computers teacher told me to "do something with variables." It grew organically with minimal direction of what I wanted do actually have it do. I had created an incredibly lame "chat" application that worked by writing lines to a shared file before. SCS was my first time actually making networking work.
  • It quickly became a serious effort. After a year or so, it grew into a pretty large thing. I even created a lobby for multiple server instances to meet potential clients in. Obviously, that part never ran, but the code worked.
  • There's no multithreading or queuing. When a new client connects, the server gives it 5 seconds for each auth field and a few more for optional encryption information. During that time, execution is blocking, waiting for the client to respond. Therefore, while connections are being processed, no other information is being relayed.
  • That said, everything worked surprisingly well. All the commands worked and the UI didn't even get too slow.
  • I didn't know about the principle of keeping processing and UI separate. In the data module creatively named "Code", many references are made to things in frmMain, especially to update the user list. However, I do feel kind of proud of that thousand-line file; it got me into Black Hawk College's computer science program in eighth grade.
  • Encryption was an afterthought. SCEC works perfectly fine, and I guess is secure if the attacker didn't hear the beginning, but it relies on people not knowing how the server chooses the key. (Hint: it's based on a very suspicious line in the introduction.)

Saturday, November 9, 2013

The Beowulf SupaChat RPG

For an upcoming creative project on Beowulf (for lit class), I decided to create a text-based RPG featuring events similar to those found in the book. Since network infrastructure and all that stuff is a pain, I am trying to use the service snap-in feature of my old SupaChat Server. It's been three years since I did anything with that; as I look at its code, I see so much that could go horribly wrong, mostly the complete lack of multithreading. So far, the program can connect to an SCS, snap itself in as a service, and come in like a wrecking ball to new groups and adminify itself for RPG handling there.

Friday, November 8, 2013

Robotics - Dremel

Dremels are cool things. They have substitutable parts, are easy to handle, and have a good owner's manual. During an exceptionally length early-out Friday robotics meeting, we used one such device to cut a piece of aluminum. We actually broke at least three of the cutting heads, but it comes with many packages; evidently, breakage is pretty common. That piece was used as the back of our conveyor assembly. Once that was all fixed into place, I did some adjustments and testing to the new two-controller system.

Wednesday, November 6, 2013

Robotics - T-Shirt Time

We're still waiting on drills and other equipment necessary to continue the redesign of the robot, so today's meeting was used to finalize the t-shirts. They're very similar to that of last year's team: an apple and the pi symbol. They're set on a light gray background with the names of all the members on the back. There's just 10 days left before the first state qualifier.

Monday, November 4, 2013

Robotics - Double Controller, So Intense

As an important FTC qualifier draws near and the build team starts totally redoing our design, I'm finally implementing the second controller that is necessary to have good control. The general convention is to have one controller for moving the robot and use the other for operations. All I had to do is move the code for controlling the conveyor belts to the variables for the new controller. Since I didn't have much to do while the build team dismantled the robot, I created a new mode of controlling the conveyors using the top hat.

Sunday, November 3, 2013

Robotics - Autonomous Testing

The autonomous period development is going reasonably well. The robot can use the infrared sensor without special drivers, which I was unable to install correctly. However, it can still sense the general direction of the beacon perfectly fine. We have been using that to start our autonomous programming. So far, the robot can find where the beacon is, turn, and then make a decent attempt at driving up to the pendulum. At that last step, it gets a little confused due to my slightly indiscriminate handling of direction. It also has issues turning such that the sensor (which is mounted on the side of the robot for drive-by scanning (very gangster)) is perpendicular to the beacon. We expect most of these problems to be resolved when we actually get a real field installed in our testing lab. In related news, the conveyor belt has had all the rubber inserts installed and can pick up blocks with success.

Friday, November 1, 2013

Logofrag - Adding Frags

Well, I modulized a little bit more functionality used by the thread view of Logofrag. I scrapped the idea of having the user write one word in each text box and select both sides' punctuation for adding a frag. Instead, I'm going to let the entrants write freely and then press a "preview" button that will make sure no illegal characters are being used, check that the frag meets the length requirements, and figure out what is punctuation and what isn't. Once the user makes sure that Logofrag didn't destroy the formatting in the verification, the newly made visible Submit button is used to actually add the fragment. Also, I discovered that it might be easier for me to keep a User object in the Session instead of an ID; it's slightly annoying to have to constantly query the database to get a user's actual information.

Wednesday, October 30, 2013

Robotics - Infrared Sensor

While some other people tried to get the other conveyor belt on (without enough links), I tried to correct the lack of sensitivity on the controls. Since the joystick puts in values up to 128, but the motors take values up to 100, I figured that it could be more sensitive if I scale the inputs instead of clamping them. That took quite a while to get right. At first, the scale function produced zero for a negative input. I fixed that by changing some of the variables to floats. Then, it was insanely more sensitive going forward than backward. That was fixed by compacting the function to one line. Finally, the scale function produced positive outputs even from negative inputs. Evidently, I didn't think that the nature of division would keep the sign and had added an inverter factor; removing that part made it work correctly. We then started to investigate the infrared sensor, which will be useful during the autonomous period. It's been attached (somewhat) and I have begun reading white papers on how to properly address it in code.

Monday, October 28, 2013

Robotics - Conveyors

Though we're short a few of those little plastic links, the robotics team has constructed and attached both conveyor belts to the robot. I created the team's ninth test program to implement them in code. They work very well except for the fact that the teeth (necessary to hold onto the blocks) get stuck between the conveyor, which is too low, and the ground. In other news, I did successfully fix the strange wheel-activating bug. Evidently, it really is necessary to access the variable of the "joystick" object, not just the stray variables created in JoystickDriver.c. With the wheels working again, we tested my simple arcade drive and found out that it really does not make any sense. For one thing, left and right are reversed when going backwards. For another, it does not stop when the analog sticks are released.

Sunday, October 27, 2013

Robotics - Issues

Yesterday morning, we had a robotics meeting. Unfortunately, since it started at 8:00 AM, there were very few people there. In fact, there were only three people from my team, myself included. We almost immediately ran into issues with the controller, despite having fixed it last time. At first, the motors were activating without any controller input, but then they stopped activating at all. It took most of the meeting to determine that I had crossed some uninsulated wires, causing the fuse to blow. However, when it blew, it did not do it successfully, allowing just a little bit of electricity to arc over. We're not sure what caused the motors to activate, but we're pretty sure a new fuse will fix the problem. In other news, a failed firmware download rendered the NXT unusable. I did find a way to fix it on the Internet, which I will perform tomorrow.

Friday, October 25, 2013

Logofrag - Thread View

After an insane amount of coding, I believe I have finished the basic thread view. I'm not actually sure how well it displays the frags (since I have not yet made a page to add them), but it does correctly create the thread information section and judge the capabilities of the user. Before creating the detail view page, I'm going to do the frag-adding one. I also fixed the CSS, finally making the margins make sense.

Thursday, October 24, 2013

Robotics - Fixed Everything

Today was an extremely productive meeting day of the robotics team! It started with three members, myself included, walking down to a nearby hardware store to purchase some string. Once everyone arrived, we started fiddling with some gears on the robot in preparation for allowing the conveyor belt to be swung around. While that happened, I did more research on using controllers through a laptop. After a few more attempts at actually running it (some of them failing due to not turning on the battery pack), it succeeded! Controllers hooked up through the RobotC dev environment could control the robot's motors! The problem was that I had not opened the Joystick Control window, which is essential for relaying the instructions. After calming down from that accomplishment, we then noticed that only one of the motor control switches was receiving power. It did not take long, upon inspection, to notice that we had actually not connected the battery to the secondary switch. Once that was done, the controller could also run the conveyor belt! Still having the better part of an hour left, the team's captain wanted to try to install the Samantha module (a device for connecting controllers to the NXT wirelessly). After scrounging a flash drive and a few short cables, the Samantha module was configured and communicating with the Cisco router on my development desk. Apparently, last year's team had never managed to correctly install the Samantha module, so they were very excited that it worked perfectly. The last few minutes of the meeting were used to show off our immense progress to the other team in the building.

Wednesday, October 23, 2013

Robotics - Infuriating Controllers

The robotics team finally found the charger for the battery pack, so we used today's meeting to test my controller-operated mobility code. The first few tries failed due to the battery being wired incorrectly (backwards). After that, the wheels started spinning despite not having been activated by the controller. That went on for another few tries until I did some checking with the debug window and discovered that the X/Y roller things had small non-zero even when at rest. To fix that, I added an epsilon function that would return zero if the input was too insignificant. While continuing to check out the controller debug window, I found that the buttons were not mapped how I thought. It took about 20 minutes to determine that the controller was in Xbox mode, not desktop mode. Once that was fixed, the rest of the meeting was comprised of my being very upset at the robot inexplicably continuing to activate motors without my consent.

Tuesday, October 22, 2013

VB .NET - Lambdas

I have recently discovered that lambdas are amazing things. They take a little bit of getting used to, but once mastered, correct use of them will save programmer time and increase program efficiency. A lambda, essentially, is a function or subroutine written in one line that can be passed as an argument, usually in a LINQ method. When a method expects an argument of type Func or Sub (like IEnumerable.ForEach), it's time for a lambda. Start a lambda by writing Function or Sub and an argument in parentheses without type - the object that's going to be put in as the input of the lambda method. Then, simply write the return value. The simplest lambda is the identity lambda: Function(n) n. It takes in object n and returns it. For a Sub, you obviously won't have a return value, so just write what action it performs. Sub(n) MsgBox(n.ToString) accepts object n and writes its string representation in a message box. If you are using more complicated methods, use an AddressOf pointer to indicate that you want to pass the objects through a declared method.

Monday, October 21, 2013

Robotics - Conveyor Chain

LEGO is amazingly fast at shipping components. The conveyor belt kit my robotics team ordered on Thursday arrived today. It's made up of a lot of snap-in links that are designed to accept plastic "teeth" at appropriate intervals. These things are exceedingly difficult to snap in, so it took the entire team about an hour to finish creating the chain. While the build team applied the belt to the gears, I created a much better Robot-C program to support movement from controllers.

Sunday, October 20, 2013

Windows 8.1

If you haven't already heard, Windows 8.1 is out! If you already have Windows 8, you can get it for free from Microsoft in the Windows Store. The upgrade leaves files and user settings alone, so there's nothing to worry about. Installation was exceedingly simple; all I had to do was press the download button and it started going to town. After about half an hour, my computer rebooted and spent another half hour in the BIOS doing all manner of interesting things. Then I encountered a problem. It froze at "Getting devices ready". However, unplugging my USB devices for a few seconds fixed the problem. The rest of the installation went smoothly. It was fun getting to do some of the initial set-up again. I can't really see any differences besides the Start button, a different metro background, and that "Computer" in File Explorer was changed to "This PC".

Wednesday, October 16, 2013

Robotics - Development Time

I might have already written a little about this somewhere but I figured I'd give a more detailed account.

My school has two FTC robotics teams this year. I've been assigned to the veteran team despite being a rookie - apparently expectations are high. For the past month, we've been considering options for the robot's design and creating some basic structure. Basically, every year in FTC, there's a different arena in which the robot needs to perform tasks. This year, the main thing is pushing blocks around and putting them into containers. I'm not that great of an engineer, but I have already started understanding how to program in RobotC, the C-like language designed for the NXT module. So far, I've created three test programs to try out the API and get used to the limitations. As soon as we get a battery charger, I'll be able to prepare some mobility programming.

Tuesday, October 15, 2013

Advanced Programming with Twisted Oak Studios

Twisted Oak Studios is a game development consultation firm that also does all manner of other high-level and complicated programming things that I do not understand. Over the past few weeks, I've read every blog article they've ever published. I've learned a lot, especially about functional programming ideas. I highly recommend that you read all the articles on their blog.

Sunday, October 13, 2013

Logofrag - XSS Alert Page

One of the critical functions of Logofrag is viewing threads. So, I started actually writing the code-behind to render the thread page today. Since I remembered that I was going to display a warning if angle brackets or ampersands were allowed in fragments (because possible XSS vulnerability), that was the first thing I implemented. There is now a very nice alert when accessing such a thread.

Saturday, October 12, 2013

Explaining DVD Region

Everyone knows that DRM (Digital Rights Management) is a real pain. One of the artifacts of this is DVD regions. One might see error messages about these when you put a disc in a player and see an error message that disallows the disc to play. As I understand it, certain discs are intended to be played only in certain parts of the world, probably because other countries have different copyright laws than the producer. DVD players are probably legally required to make overriding this difficult, so changing the playing region is often a very technical thing to do. In fact, a lot of players limit the amount of times their playing region can be changes. Fortunately, all Windows computers that have DVD support expose an API element for switching the region.

Friday, October 11, 2013

CSS-Only Hover Menu

I was thinking about using mouseover information boxes on Logofrag fragments, similar to RES does for usernames. After some searching, I came up with an article called "Creating a pure CSS drop-down menu" that wonderfully explains how this can work without any sort of JavaScript. Unfortunately, it requires that all the mouseover text be sent to the client to render the web page in the first place.

Sunday, October 6, 2013

Essay: Classifying Programming Languages

I wrote a classification essay for writing class entitled Classifying Programming Languages.  It's in MLA format; signal phrases are used because the teacher said so.  Download (DOCX), 15KB.

Wednesday, October 2, 2013

Logofrag - Fixed the Session

As I predicted, work on Logofrag is going along very slowly (something to do with schoolwork being so time-consuming and Etho being so entertaining).  I did some reading of the MSDN ASP.NET docs and discovered that, unlike Request.QueryString, Session items are Nothing by default.  I had been doing all kinds of stuff to see if it existed, make sure it was an integer, and parse it appropriately.  That was useless because I could just shove an Int32 into it and then retrieve that exact same value later.  So, I went through the small codebase and removed the string-parsing logic from accesses to the logged-in user ID.  Progress!

Sunday, September 29, 2013

Logofrag - Thread ACLs

I did commit to dropping the thread properties editing functionality.  It was being strange and difficult to work on, so it simply will not be a thing.  Instead, I moved ACL control to its own page, which will be accessible from a moderator control panel in the thread.  I did a little bit of checking around the database and determined that it's best to simply try to occupy permission ID #1 first and if it's taken, use the maximum plus one.  Eventually, the table will waste lots of IDs, but I'm thinking of implementing a "pack database" button for administrators.  The thread ACL control works very nicely.  Tick the boxes next to an ACL entry to remove it and type a name in the text box under the list to add it.

Friday, September 27, 2013

Minecraft - Water Destroys End Portals

I recently and accidentally discovered that pouring a bucket of water onto the side of a block occupied by an End portal will destroy that part of the portal.  Fortunately, only source blocks can do this, but it was very terrifying to see one ninth of my access to the End erased.  I filed a bug report on Mojira, which will have the latest on this issue.

Thursday, September 26, 2013

Logofrag - Abandon Edit Ship

Debugging the edit-thread functionality has become infuriating.  As such, I have decided to split it into its own page, possibly dropping support for all attributes except ACLs.  It doesn't really make sense to allow people to write exceedingly long fragments after the thread had already been going with short ones.  Modifying the permissions will have to be possible.  Once this is finally out of the way, I can develop useful things like thread view, fragment adding, and user profile pages.

Wednesday, September 25, 2013

Logofrag - Edit Rage

I did even more head pounding and determined that the approach I created last post is not useful in Logofrag.  I have tried tons of ways over the past three days to allow thread properties to be edited by the moderators, but it won't work properly.  I just now got it back to a state in which thread creation works and made editing not crash the server.  Editing does, however, duplicate the ACL entries and has no effect on other properties.  I am getting very frustrated with this project, but I'm sure it will only take another day or two before I break past this issue and actually start doing things.

Tuesday, September 24, 2013

LINQ - Get First Unused ID

I just spent two hours pounding my head against the proverbial wall trying to get some Logofrag stuff to work correctly.  After messing around with all manner of methods, I found an amazing StackOverflow answer that put all the pieces in place.  This is how I finally was able to find the first unused permission ID:

Dim idsQuery = From right In data.ThreadRights Select right.RightID

Return (From n In idsQuery Where (Not idList.Select(Function(x) x).Contains(n + 1)) Order By n Select n + 1).First

I had never before used lambdas, so that's another thing I learned.  They're very easy, just say whether it's a function or sub, give the arguments it takes, and write the return value.

Monday, September 23, 2013

Keep Calm and Resume Next

No, please never actually write "On Error Resume Next."  But do enjoy this parody I made of the "Keep Calm and Carry On" posters!


Don't you love QuickBasic?

Sunday, September 22, 2013

Logofrag - Threads

LINQ/SQL is more of a pain that I had originally thought.  It requires me to figure out the next available primary key and won't allow me to access foreign key relationships as collections without them.  I did manage to slog through coding-behind the thread moderator interface.  Users can now create new threads and possibly reopen the properties of old ones (I haven't tested that yet).  After repairing all the database things, I added a "permission denied" page that is shown when users attempt to use query string manipulation to access things they can't.

Saturday, September 21, 2013

Visual Basic .NET - Binary Operations

In Visual Basic, I sometimes start missing Java's nice bit operators, especially when I really need to pack boolean data into a single number.  Fortunately, VB has this; it's just less intuitive.  The operator for logical functions is indistinguishable from that of bit functions.  So, I can just do this:

For x = 0 To 7
    ChecklistPunctuation.Items(x).Selected = ((t.Punctuation And 2 ^ x) <> 0)
Next

Less fortunately, VB does not have shift operators.  You can however make do with integer division, multiplication, and exponents of two.  To shift a collection of bits N to the left, do this:

shifted = (bitcol \ (2 ^ N))

Maybe it's true that the language wasn't intended to be used in advanced/professional environments, but it certainly has been tortured into providing pretty much any functionality you could want.

Friday, September 20, 2013

Logofrag - Index and Creation

Logofrag development is going along very easily!  I like these kind of projects because there's not going to be any bang-head-against-wall frustration, but it will be an interesting challenge to complete.  Today, I wrote the code-behind to create a table of threads sorted by time updated, 50 per page.  I've actually never done anything with pages before, but it was pretty easy.  I also started the front-end of the page to create a new thread, which is one of the essential functions.  The database is being changed as I create pages -- the ability of Visual Studio to drop and recreate tables while making it seem like a normal change is amazing.

Thursday, September 19, 2013

Do not Suspend or Abort Threads

Jim Mischel recently published an article called "Do not suspend or abort threads."  He's a really good programmer, but his blog doesn't seem to be too popular, so I figured I'd give him a few more views!  Also, drowning in schoolwork.

Tuesday, September 17, 2013

LINQ Does Not Compile

Today I learned that LINQ to SQL statements are not compiled as normal .NET code is.  Instead, it's somehow transformed into a normal SQL statement by finding a comparator that operates on the conditions you gave and checking to see if it has the right argument types.  So, don't just go and write any boolean-producing expression as the Where part of a query; it's better to collect all the parts of it in a line before and use simple variables instead.  Remember, the SQL server isn't passing every data row back to your query for inspection; LINQ just writes all the fancy query stuff for you.

Monday, September 16, 2013

Logofrag - The Database

Since I have a lot of schoolwork, Logofrag won't get developed very quickly.  However, I have created the database - using SQL this time.  I learned my lesson about custom data formats for web applications; they are way more of a hassle than they're worth.  LINQ is going to make it amazingly easy to manipulate user data inside the strange world of SQL.  Besides getting the database ready, I also prepared the master page that will provide the consistent style across the site.  I'm going for a clean, streamlined, old-school look.


Sunday, September 15, 2013

.NET Repair Kit

Eventually, your .NET Framework installation will need updating.  .NET updates, especially those security-critical ones, have been known to endlessly fail and get stuck in the Windows Update queue.  This happened to a computer I was working on today, so I looked up how to fix the problem.  I found a very helpful post on Microsoft Answers that contained a link to a collection of utilities that fixes the problem.  It does so by completely uninstalling all versions of the Framework, then reinstalling them.  I put those four programs into one ZIP archive, which I recommend you keep on hand in case this problem happens to you.