Saturday, January 31, 2015

FMod - Horrifying Code

Today, I was surveying the GalaxyGraphics code that will be extended for Gash to deal with CGA and VGA. I immediately noticed that it is a huge unreadable mess. There is stuff like this repeated all throughout the file, slightly modified sometimes:
Yep, that's a 5-deep for loop. There are all manner of crazy variables and bit twiddling (which really should have been done in C#).

I think I'll be rewriting this file/class to use these nice function calls that we have in .NET instead of copy/pasting difficult code. I may also take this opportunity to make the time-consuming stuff (decompression) not happen until the resource is called for.

Friday, January 30, 2015

Gash: The Superior xGAGRAPH Editor

There have been murmurings in the Keen community of bugs, limitations, and general shortcomings of KeenGraph. KeenGraph is the more modern replacement for the original ModKeen, and it is a very good tool. Sadly, it is written in QuickBASIC and is therefore difficult to maintain and extend. The main issue I find is that there is no way to give it custom chunk offsets - every time somebody mods another game, the program must be updated or forked to add configuration for that game's EGA arrangement. KeenGraph also does not support CGA or VGA graphics. (The main graphics file can be called EGAGRAPH, CGAGRAPH, or VGAGRAPH depending on the adapter supported.)

So, I plan on soon starting a replacement called Gash - xGAGRAPH Shell. I will address the following issues with KeenGraph:

  • Language. Gash will be written in .NET to take advantage of existing FleexCore2 (FMod) functionality. This will greatly help debuggability and extensibility.
  • Output format. KeenGraph only exports BMP images, which do not support transparency. Masking is done with a designated "transparent" color. Translucent colors are produced using a strange color-shifting system that I haven't been able to use successfully. Gash will support the export and import of PNG images, interpreting a transparent pixel to be an invisible black pixel (transparent) and a translucent pixel of any color to be that color unmasked.
  • Tolerance. I personally enjoy the Paint.NET editor very much, but it butchers the 16-color bitmaps into something... not 16-colored. This causes corruption when the images are imported by ModKeen or KeenGraph. Gash will use the .NET image loading routines to accept any bit depth. If slightly wrong colors are used (I'm still not sure whether EGA white is supposed to be $FFFFFF or $FCFCFC), it will look through the palette for the closest match, use it if it is found, and warn if it's really far off.
  • xGA format. KeenGraph only deals with graphic-planar EGA, as far as I can tell. Gash will support CGA and VGA as well, and row- and byte-planar EGA if any Keen-ish games actually use it.
  • Configurability. KeenGraph does not support the use of custom chunk offsets. This is a very simple thing to do with FleexCore2, so Gash will support it.
Work on this may start tomorrow. I hope to have this done will all these features by Keen Day 2015.

Thursday, January 29, 2015

FMod - v2.3.3

I performed further testing of the Dreams audio changes. I noticed that the patch generator was not adding the MAPDICT patch command - it was checking the old HuffCompressedMaps flag rather than the new (v2.0) MapType field. Additionally, I noticed continued problems with the Project Settings dialog. Some careful rereading of the code determined that it was operating on the same instance of AbiatharFileConfig that was held by the main form - it was writing changes immediately to the actual dependency file. So, if the user made changes and then clicked Cancel, no reload would occur, but changes would be written to disk at the next save. I made it duplicate the core configuration so as to not modify the main instance.

These changes and previous ones were released on the PCKF as v2.3.3.

Wednesday, January 28, 2015

FMod - Dreams Audio

During my study hall today, I made a big push toward Abiathar v2.3.3. I added code to the AdaptVersion routines on file configuration and templates configuration to copy over the new audio flag that disables level song assignment while allowing other audio management. I added the audio file patches for Keen Dreams and made AdaptVersion copy them into existing files. (This kind of thing almost makes me want to go back to the disastrous "profile" system from pre-1.4.)

Default audio files were added for Keen Dreams. Music Mappings now disables the left pane if song assignment is disabled, but IMFs can still be imported (if ImfStart and ImfEnd are modified appropriately - Keen Dreams doesn't have audio slots for IMF songs). Import/export works just as it does for other episodes. I also fixed the bug that causes the default song name to come up blank when importing an IMF. The fix was the addition of a single comma.

Some more testing is required, but v2.3.3 is almost ready.

Tuesday, January 27, 2015

Robotics - Looking Back

For team 7727, the 2014-15 FTC robotics season (Cascade Effect) has ended. We didn't do all that well, and I would like to take a moment to consider why it was so.

First, we didn't have very many parts to start out with. It looked like we had a lot of inventory because there was so much junk in the mess that was everywhere, but the number of useful parts was quite low. We also didn't have (and never got) all the parts of the field, so we never had a complete game set on which to practice.

Speaking of the field, its construction was something of a disaster. It took way too long (almost two months to become complete-ish) and we made a lot of mistakes. Those could have been avoided had we read the instructions instead of, say, drilling holes through the kickstand pipes and riveting them to the inside of the center assembly when there were small pipes with pre-drilled holes for that purpose. Near the end, there was the whole debacle of the ramp; we never did get that fixed. (Tape for the win!)

Another serious problem was that people couldn't come to meetings. Most of the builders were at some sort of sports thing during a bunch of robotics practices and some people skipped some meetings. I probably had the best attendance record of anybody, but I can only program and it takes more than code to make a robot. (I did compose and compile the entire engineering notebook, though.)

Returning to the problem with the lack of parts, we waited way too long to get critical pieces. This was not helped by the school administration busting into the robotics program this year; they required purchase orders before we could get stuff with our budget. These took days to process. The linear bearings we needed for the lift - a super important part of the robot - were 3D-printed, but it took almost a month from when we started needing them to when we got them. The AEA's printer turned out to be a waste of time and distraction.

Speaking of school administration and bureaucracy, the team rosters got all shuffled around a month or so into the season. Originally, they were chosen by a panel of teachers (who probably didn't know much about how the people interact or what their skills are) to make roughly equal teams. The coach reshuffled them to form a veteran team - my team - and a newbie team. This turned out to be a nice arrangement, but it really messed up our plans/relationships/expectations for a while after it happened.

With the lack of builders present at meetings, the robot was constructed very slowly. We had barely any time to test-drive it, let alone develop an autonomous routine. The lack of drive testing caused us to have unexpected problems - like breaking apart and/or getting stuck - during competitions. Though I had written some autonomous routines, our questionably-constructed field made them act differently at home than at meets. Of course, they weren't tested much in the first place because the robot was almost always on the build table being tinkered with, apparently inefficiently.

Maybe we'll do better next year. The coach said he would make a lot of changes. I hope those changes don't involve more bureaucracy or "team meetings", because those will do more to create problems rather than solving them.

Monday, January 26, 2015

Rickety Computer Name Resolution on Domains

Sometimes, Windows domains just aren't able to resolve the names of computers to IP addresses via NetBIOS. (This usually happens when the DNS server gets confused or out of sync with DHCP.) To fix this, I find installing the WINS role on a domain server helps. It maintains a central list so computers don't have to rely on the normal DNS system or SMB master browsers.

Sunday, January 25, 2015

FMod - Some Issues

A few days ago, I had a conversation on IRC with an Abiathar user who was experiencing some problems. Apparently, the Project Settings dialog is quite broken in that moving to the Containing Folder step sets the dialog to the mode that initializes data to default values when a page is moved to. (That mode should be only used at the start of the New Project Wizard, which is actually the same dialog invoked differently.) Also, the function that checks whether a path is inside the residing directory does not handle blank paths, so if a filename box is left blank, Abiathar will crash when Next is pressed. This has been fixed, but not released publicly.

Also, it turns out that .NET refuses to reflectively load on-disk assemblies that have the NTFS Alternate Data Stream that says they came from the Internet. All major browsers leave that mark on downloaded files, and some ZIP extractors propagate it to the files in the archive when it is extracted. So, unless "Unblock" is hit on the Properties page, Abiathar will fail to load the ImfPreview extension. I can't do anything about this besides warn people.

Finally, I noticed that the default name (involving the chunk number) is no longer filled in when importing IMFs. I'll fix that and then release v2.3.3.

Saturday, January 24, 2015

Robotics [MEET] - End

Today was the big FTC robotics qualifier! I had to get up really early and collect all the supplies that I was worried the team coach would forget to bring - and he did indeed forget an outlet strip and joysticks. We failed our first hardware inspection because we didn't have a dedicated flag holder (any old hole in the channels worked at previous meets) so we had to add some C brackets to pass. The other inspections were passed with ease. The interview with the judges went decently, but I feel that we didn't appear confident and energetic.

Back in the work area, we attached a servo to the guard flap so it could be raised and lowered so as to not get in the way of tubes when we push them. The bar that had previously been used for that purpose was removed. However, the servo we used was bad, so we did not attach that assembly to the robot.

In our first match, we ran the autonomous that attempts to drop a ball in a tube after coming down off the ramp. We didn't come down quite straight and instead slammed into the wall of the opposing parking zone, dropping the balls outside the field. In tele-op, we picked up some balls, but the lift got stuck on a cable and the tubes were trapped in the corner of the field. We managed to park in the parking zone, but our alliance partner tipped over the 90cm tube, which is a big penalty. We somehow won anyway, giving a good start to the day.

In the work area, we borrowed a good servo from another team and attached the guard flap. I adjusted the autonomous program to deal with that flap appropriately.

The RobotC compiler decided to add instructions that initialize other servos on the robot to positions that make the robot larger than the 18-inch cube and let the balls flow out of the hopper. That's unacceptable, so we had to run the simple autonomous that just drives down off the ramp. It slammed a tube hard against the wall, but did its job. In tele-op, we hit the kickstand and pushed one tube up the ramp. A wheel slipped into the area between the ramp and wall, trapping us on the ramp. Our alliance partner tried to push another tube up the ramp, but ran out of time and instead went into the parking zone. We lost because the opposing alliance scored balls in tubes.

While on lunch break, we applied some more hot glue to the flap that stops the large balls from flying out when the sorter is set to eject small balls. I forced the autonomous program to keep all the servos pointing inside the robot at placement.

Our third match partner team had a much better ramp autonomous, so we just stayed on the ground and played music. In tele-op, we hit the kickstand and pushed the 30cm tube up the ramp. Our alliance partner got stuck on the fallen kickstand and was unable to move from in front of the ramp. We tried to get around them but could not. Instead, the NXT fell off and also the guard flap apparently broke off somewhere along the way. We lost.

Seeing that the guard flap was not doing us much good, we replaced it with a claw to grip the tubes so we could pull them up ramps. It actually had to be removed while placing the robot for the fourth match because the servo's default position pushed it too far back against the lift and would burn out if we left it for a while.

In that match, we pushed both the 30cm and 60cm tubes up the ramp, but the 60cm one fell off, which is a big penalty. It did, however, fall into the parking zone, so we did get a few of those points back. Our alliance partner tried to place balls in the 90cm tube, but missed and for lack of time parked in the parking zone. This match was a loss because of that big penalty.

I adjusted the controls for the tube gripper and fixed the problem with the servo default angle. The gripper was remounted.

In our fifth and final match, we gave the ball-in-tube program one last shot. It was very close, but it missed the opening of the tube by the slightest bit. We got balls stuck under the robot, pushing our wheels up, rendering us completely immobile. Our partners got an appendage of their robot stuck in an opposing robot, rendering them immobile. This was a less-than-thrilling end to the matches and, of course, a loss.

After a disastrous 1-out-of-5 day, we stuck around for the awards. We didn't get anything, but we were "finalists" for the Innovate award and PTC Design award. It's something.

This is the end of the 2014-15 FTC season for team 7727.

Friday, January 23, 2015

Robotics - Our Time Is Tomorrow

I spent a study hall today compiling the Super Ultimate Complete Final Deluxe Edition 2015 R2 of the engineering notebook. All our tools, extra supplies, and of course the robot have been packed into our coach's van for transportation to the meet tomorrow.

The previous three meets were basically just practice. We had to attend them because FTC requires each team to attend at least three meets in the initial season to advance to state competitions. Tomorrow's meet is the real deal - there will be judges' interviews, decent-sized audiences, policies/procedures, and elimination matches.

We have all the components we need to succeed, but all the systems of our robot each have their own subtle issues. The lift, for example, has a decent chance of spitting out nuts and washers when run. The intake belt occasionally jams. The wheels sometimes stop working or go extremely slowly. Autonomous is just a complete disaster.

If nothing horrible happens with our built systems, we should do really well. Of course, at least something will fail, so hopefully we get good alliance partners.

Thursday, January 22, 2015

Robotics - Questionable

At today's robotics meeting, we had a bunch of trouble! Engineers worked on an extension to the front of the robot, and it works reasonably well; the trouble was in the driving.

First, the robot wasn't driving straight - its gears were slightly misaligned. That was easy enough to fix, but it is still moving mysteriously slowly. When we tried raising the lift, the entire thing was rattling constantly and it ejected some nuts and washers from the guts of the lift. After we repaired that, the fishing line used to operate the lift snapped. There was also a generous output of white smoke from the motor.

Everything seems to be working to some extent, but we have discovered that our robot is built of questionable quality. The lift is the greatest offender in that regard; it keeps slipping down and getting jammed. After the builders finish installing their metal flap on the front (that falls down after the robot moves, preventing balls from getting stuck under the robot), we should have fewer issues with the lift.

The engineers also added a small sheet of metal to the ball hopper and lift assembly to prevent the hopper from rotating and getting stuck above the ball conduit.

Wednesday, January 21, 2015

Robotics - Eject Flapper

There was a robotics meeting yesterday, but I was sick and could not attend. It seemed that all they did was finagle the plastic flaps on the intake belt, add a little more tape, and adjust the U-shaped piece of the ball conduit.

Today, I added toggle controls for a new servo that has been inset in the part of the U-shaped metal piece immediately behind the intake belt. It can be flapped open to allow balls to go out the back rather than getting captured into the ball hopper.

While test-driving it, the ball hopper started getting out of alignment and turning to the left. After a couple of runs of that happening, the entire lift assembly produced a distinct "crack" sound and went down. Apparently, some of the fasteners broke. When the engineer attempted to service it, the lift fully detached from the robot.

After that was repaired, we are out of the large screws necessary to hold this lift together. Hopefully it won't break again.

Monday, January 19, 2015

OEM Function Keys, and Their Horribleness

I have been using a school-issued low-end Lenovo ThinkPad for about four months now, and it's a pretty good machine considering the $300 price tag. There is, however, one issue with the laptop that annoys me to no end:

They made all the function keys do some weird OEM thing, and to access the real function of the key, I have to hold the Fn key in the lower left of my keyboard.

Easily accessible volume controls are nice, but I would much rather have access to the rename key (F2), find-next key (F3), or an important part of the application-terminating sequence (F4). Every function key is brazenly overwritten with some obscure function like enabling or disabling the integrated camera or microphone.

I strike the F5 key with exceedingly high frequency. I do not appreciate my attempt to refresh the page producing the bundleware camera management thing. Sure, it's not too much of a stretch for my hand to hold down that Fn key for most functions, but it just requires more contortion and wasted time. Also, I guess I'm just hosed if I ever need to open web developer tools quickly (F12); my hand doesn't stretch that far.

OEMs: Please just stop. I do not appreciate your bundleware thrown up in my face. All I want is what I expect on any normal machine.

Sunday, January 18, 2015

Stopping Basic sethc.exe Local Admin Seizure

The StickyKeys trick is one of the most, if not the most, popular means of seizing local admin privileges on a Windows machine. It uses another boot medium to replace sethc.exe with cmd.exe and then activates StickyKeys on the logon screen to produce a command prompt running as System.

Of course, physical access is total access, and I can think of all manner of other interesting ways to bust into the local machine (adding a service to run at startup and as System would be pretty easy), but for the wanna-be hackers who are reading from a script, the failure of the StickyKeys trick would be a serious roadblock.

Local Security Policy can be used to set startup scripts, which execute before the logon screen is displayed. One of these scripts could be used to launch an application that checks whether sethc.exe (and the other accessibility programs available on the logon screen) have been modified. The watching application could then either replace the modified programs with the real version or throw up a big "Surprise! Nice try."

Saturday, January 17, 2015

FMod - v2.3.2

I wrote up the changelog for Abiathar v2.3.2 and published it via the auto-updater and made a post on the PCKF. It actually caught the attention of a Linux/C programmer, the developer of the OmniSpeak project, a reverse-engineer of several DOS games. He was creating an "enhanced" version of Keen Dreams using its recently released source code. This version loads the map resources Galaxy-style and minimizes the crazy compression that is so rampant in Keen Dreams. Abiathar does not have a means of converting Dreams levels to Galaxy levels, but that's a fairly simple task using FleexCore2 (FMod.dll):

Dim d = DreamsLevels.FromFiles("KDREAMS.MAP", "MAPHEAD.KDR", "MAPDICT.KDR")
Dim g As New GalaxyLevels()
For Each kv In d.Levels
 g.Add(kv.Key, kv.Value) 
Next 
g.ToFiles("GAMEMAPS.CK7", "MAPHEAD.CK7")

Friday, January 16, 2015

Robotics - All Alone

Since I was sick yesterday, I was unable to attend its robotics meeting. I did discover after looking around the room today that they:

  • Added more and longer flaps to the intake belt
  • Started attaching the roof on the U-tube for ball routing
  • Cobbled together metal pieces to repair the U-tube
  • Made a huge mess on the floor
Today, I was all alone - the only person from my team in attendance. I helped the other team with their programming, picked up some trash on the floor, vacuumed ("Jim, I'm a programmer, not a maid!"), and tinkered with Windows PowerShell.

So, not much was accomplished today. This is what you get when no builders attend and the programmer is left all alone.

Thursday, January 15, 2015

FMod - Relative Paths

I was home sick today, so I had a good chance to make some improvements to Abiathar. I remembered somebody noticed that Abiathar requires all resources to be in the same directory. This is done so that file-only "paths" can be used so that dependency files can be worked on with multiple computers, like with Dropbox.

Unfortunately, that policy also makes it very difficult to work with the normal KeenGraph setup that was preferred by TOM because KeenGraph recommends placing all bitmaps in a subdirectory to keep the main directory clean. This is fine if you set Abiathar to load from EGA resources, but difficult to keep in sync in you load from bitmaps.

So, I reworked all the browse-for-file code to allow resources to be in the current directory or subdirectories (any depth) thereof. The Browse buttons all now figure out the relative path for the requested resource, cutting off the absolute-ness of the path. So, paths like "bmp\5TIL0000.BMP" are now OK.

To help people ease into Abiathar from TOM (and calm down the very long and detailed New Project Wizard), I added an option in the start page of the NPW to get prompted for four simple resources: gamemaps, maphead, background tileset bitmap, foreground tileset bitmap. (I'm working on support for Keen Dreams.) It usually finds the maphead all by itself after prompting for the gamemaps. It currently only does automatic checks for ModKeen-style bitmaps, so KeenGraph users have to manually select their graphics. It is certainly a lot simpler than the full NPW, but it also doesn't support special features like tileinfo. (They can always be added in Edit | Project Settings.)

These features will be released as v2.3.2 after I finish them and do more complete tests.

Wednesday, January 14, 2015

Robotics - Adjusted Intake

Upon arriving at today's robotics meeting, we discovered that the intake motor is mysteriously working again. It also continues to manifest the strange symptom of reversing directions after a few seconds of being powered on. The builders started by putting balls through the intake, but all the big balls got jammed.

While they pondered that issue, I started working on the ramp again. This time, I decided to put it together in a non-escomatage, so I scrounged up some C brackets and long screws and started attaching the square piece to the long side. It's really hard to wrangle a wrench, the nuts, and the ramp without it all falling apart, and I am missing a screw, so it's kind of difficult.

The engineer added more treads to the conveyor belt (making it longer), remounted it at a steeper angle, and changed the plastic flaps out for metal. It can now take in balls very well, but we now have to find a way to make them roll down into the ball hopper.

Tuesday, January 13, 2015

Robotics - Driving Practice

Very few people were able to attend and stay long at this robotics meeting (there was a basketball game/practice thing going on), so not much progress was made. We tinkered with the ball intake device a little more and changed its gearing to 1:1. It's still pretty slow, even at maximum power, so we might just have to deal with the super speed of the original configuration. The U-shaped metal piece providing the route from the intake to the hopper has been temporarily removed so we can more conveniently mess with the intake conveyor.

After everybody else left, I got to drive the robot around with the new omniwheels that arrived today. They make turning a lot smoother and driving a lot easier. There were some connectivity issues, possibly related to battery lowness. One of the drive wheels keeps slipping away from its motor. Near the end of the meeting, the intake motor mysteriously stopped working, in addition to frequently losing its motor wire connection.

Monday, January 12, 2015

Robotics - Metallic

In this first robotics meeting after our third meet, we spent some time replacing the lift motor that my programming error burned out. After that, the main engineer/builder continued the metallization of the cardboard engineering that had been done in a rush before the third meet.

The U-shaped piece that routes the balls from the intake device to the hopper has been reconstructed in metal with hand bending and tinsnips. It still needs a cover on the top to prevent balls from just flying away after being sucked up, but when we manually held a cover on, the balls frequently were successfully dropped into the hopper.

The gears on the intake motor were reversed for increased power. Unfortunately, it now goes so slow that small balls slip back out. We may have to put it back or use a 1:1 gear ratio.

Meanwhile, the other team is having severe issues with their lift. They snapped the fishing line several times and shattered two 3D-printed linear bearings. More of those will be printed this weekend.

Sunday, January 11, 2015

FMod - v2.3.1 and ImfPreview

I finally got around to writing up and posting v2.3.1 on the PCKF today. It doesn't include any new visible changes from last time I mentioned Abiathar on here (just some tweaks to the extension API).

I did, however, also finish and release something else. The same community member requesting the changes of v2.3.1 also wanted a way to preview the IMF songs in Music Mappings. I do not know anything at all about audio playing or conversion, but somebody had made an IMF-to-WAV converter. Unfortunately, it's licensed under the GPL, so had I used it in Abiathar, I would have to place the entire program under the GPL, which is not going to happen. Ever. So I made use of my own extension API to create an Abiathar extension called ImfPreview which could be placed under the GPL.

ImfPreview contains Imf2Wav as a datafile and spits it out when asked to play an IMF. It invokes the program, pointing it to a temporary IMF file on disk, waits for it to finish, and then takes the converted WAV file and plays it. As an Abiathar extension, it uses reflection to find the instance of the Music Mappings form, grabs its instance of the audio being edited, and injects a bunch of event handlers to add functionality and clean up after itself.

With ImfPreview installed, simply right-clicking a song in the right-hand Music Mappings list plays it. All temporary files are removed when Abiathar is closed.

It actually turns out that I don't have to place ImfPreview under the GPL because of the way I interface with Imf2Wav. (It's not the normal pointers-and-structures style of linking covered by the GPL.) In fact, GPL'ing ImfPreview - which has a linker dependency on Abiathar, which is not and never will be GPL'd - would require me to do a bunch of legal stuff that I don't want to deal with. So, the final result is that both Abiathar and ImfPreview are under the Berne Convention default license and ImfPreview is open source. I'll keep ImfPreview's functionality as an extension just in case I'm wrong about what constitutes executable linking.

You can download ImfPreview (includes source, Imf2Wav, Imf2Wav's source, and a copy of the GPLv2). All that's necessary to put next to Abiathar is ImfPreview.aex.

Saturday, January 10, 2015

Robotics [MEET] - Difficult Driving

Today was the third meet of this FTC season that we attended. We were considerably more ready for this one than previous meets because we finally have a means of getting balls up to the tubes. After I left last night, an engineer replaced the cardboard box ball hopper with one made of aluminum. Before things started, I changed the code a little to make the newly repositioned servo go to the right places when the buttons are pressed.

We passed software inspection easily, but the hardware inspection failed because one of our axles was too long, making the wheel stick out of the sizing cube. Our school's other team needed some help getting through software inspection (they didn't know how to get to the settings in the NXT), so I somehow ended up signing on the "Team Representative" lines for both teams. I wonder if the FTC people noticed.

I and the other driver for my team decided to switch driving roles - I thought somebody else would be better for the main movement controls given my less-than-stellar performances in the previous meets. In our first match, we started in the parking zone and ran the autonomous program that tries to use IR to find and kick the kickstand. It did not work, and just rammed into the side of the ramp.

(Side note: The FTC people chose to use the ramp we assembled in the competition field. I wonder if they noticed that it was held together entirely with tape. The rivets that appear to be holding it together are broken and don't connect anything. Evidently, the team mentor didn't tell them about the quality of our engineering.)

After the autonomous period in the first match ended, we did go over to the kickstand and knock it down. Unfortunately, a wheel gear slipped, and we were again rendered unable to turn. We pushed up the lift to test whether it worked, and it went up, but the servo cable was not long enough and therefore disconnected. The driver sort of managed to get us partially into the parking zone after I brought the lift back down, but I don't think it counted for points. Our alliance partner tried to put balls in tubes, but their controller stuck at an inopportune time and flipped them over. This match was a complete disaster and, of course, a loss.

In the second match, we started on the ramp and used the autonomous program that just goes down off of it. In tele-op, we knocked down the kickstand and collected another ball. When we tried to drop them in the tube, however, they completely missed - there were parts of our robot that pushed the tube away when we got close. We did push one tube up our ramp and almost got up ourselves. Our alliance member got several penalties - we also left one of the three tubes in the opposing parking zone - but did manage to park in our parking zone. This match was also a loss, probably thanks to all the penalties.

We had some time in between the second and third matches to adjust our ball intake and the code. They turned out to not help much, though. In that third match, we started on the ramp and debuted the completely untested program that is supposed to come down from the ramp and drop two balls in the 60cm tube. It got close, but the leaning of the lift made the balls miss the tube. Also, I forgot to add an instruction to stop the lift motor, so when it got to the top, it just kept pulling the string and started smoking. (This never happens in pure software!) In tele-op, the driver got a small ball stuck under our lower frame, which made moving really difficult. She did manage to shake it free, but by then there was only time to get one tube up the ramp. We actually tipped that tube over on the ramp, but it wasn't technically "tipped over" because it was at less than a 90 degree angle, so we got points for it. The opposing alliance got several penalties, so we won!

In the fourth match, we tried that ball-dropping autonomous program again, now with a stopping instruction! The lift didn't actually raise - my mistake had burned out the motor. (In pure software we would just restore from backup.) The edge of the ball hopper also clipped the floor near the bottom of the ramp, turning us off course. The robot autonomously T-boned an opposing bot quite intensely. Fortunately, there was no damage to either robot, and the first thing we did in tele-op was accidentally push a tube into the opposing parking zone. We tried to push the 30cm and 60cm tubes up the ramp, but had insufficient traction. Fortunately, our alliance partner was able to half-fill the 90cm tube and get enough points to win the match for us!

In the fifth and final match of the day, we went back to the simple down-off-ramp autonomous program. It had the same edge-in-ground turning problem as before, and left us with one wheel hanging and unable to move. Our alliance partner helpfully pushed us back onto the ground, but slipped our gear and knocked both the NXT and Samantha module off their mounts. We managed to park in the parking zone while our partner team filled the center goal. With that large amount of points, we won.

Three out of five isn't bad, especially considering all the mishaps that our robot experienced. The new driver said she now understands why driving is so hard. We really need to get the omniwheels on; with normal wheels, turning is slow and jerky but straight movement is fast.

We'll replace the lift motor next meeting.

Friday, January 9, 2015

Robotics - Final Prep

I got the third incarnation of the Engineering Notebook prepared in one of my study halls today.

Tonight was an extra-long practice, the last before our third and possibly final meet. The lift mechanism, already assembled, was augmented with another slide with a screw hole in it. That was used to re-mount the device in a stronger manner to the robot frame. (It no longer threatens to fall over when extended.)

The engineer did something to the motor and the fishing line (possibly a gear-up, I didn't see) to make the device extend and contract much faster. It actually cut the line and a wire during testing, but the important components have been carefully adjusted (read: trapped with zip ties) to avoid things like that in the future. The line cut was a result of a mistake in threading.

The first challenge was to make it fit inside the 18 inch sizing cube. That required a good deal of filing, finagling, and probably some Dremeling tomorrow (before the matches start). More importantly, we had to figure out a way to put the ball hopper box on the last slide so that the balls could be dropped into the tallest tube. It did get attached via screws, but it still needs a bit of fine-tuning so as to actually drop the balls into the tube.

Tests were performed on the ball hopper servo; it does indeed open and drop the balls. I wrote a rough draft of an autonomous program to come down from the ramp and drop an autonomous ball into the second tube. It has not been tested and probably will miss completely; the timings hard-coded into the program are guesses.

The other team finally started having their own programmer. I gave him my function libraries and the code I had written for his robot before they completely rebuilt it. He successfully reconfigured the motors and has it driving, albeit with strange half-reversed controls.

If we can get our stuff together tomorrow morning, we should do pretty well. The other team also has a lift in place, but they seem to be running into other problems. I will do my best to help them, but sadly I can only code.

Thursday, January 8, 2015

Robotics - Major Lift Success

We discovered upon arriving at the robotics meeting today that the ramp we had partially assembled had fallen apart over the break. (It sort of went "splat" and went flat on the ground.) It also broke the rivets that took so long to put in and bent the brackets out of shape. We were able to put the entire thing back together (and attach the sides) with lots of tape and a few more rivets.

Another slide was added to the lift mechanism. After going down to the local hardware store to pick up some fishing line, we were able to thread the mechanism in such a way that pulling the line would raise and telescope the lift. It was also successfully mounted on the robot, but does need a little bit more work before it can be stable. I put the controls for the lift on the second pad.

We just need to attach the ball hopper to the lift mechanism and figure out a way to attach the servo cable in such a way that it doesn't get severed by the mechanism. We may also need to gear up the lift's motor so it can get up to the top in sub-geological time.

Wednesday, January 7, 2015

FMod - Audio & Patch Adjustments

At the request of an important modder in the community, I made several minor adjustments to Abiathar today. These will soon be released as v2.3.1.

First, I added a Rename button to the song list in the Music Mappings dialog. Previously, it was necessary to re-import (or Replace) the entire song file and enter the new title. Making this change also required making the song list wider and the form asymmetrical.

Then, I added a checkbox option to the Patches dialog to prevent overwriting play.bat every time patches are emitted. Apparently, the only convenient method of changing the color of the Terminator-style text that happens at game startup uses batch stuff rather than patch stuff.

I added some CKPatch comments to the emitted patch file so curious people can know what all the lines do and edit them manually if necessary.

Finally, after running some of my own experiments, I adjusted the extension loading code to get the AEX files from the current directory rather than a subdirectory, since it would be a waste to have one copy of Interop.dll in the Abiathar.exe directory and one in the AbiatharExt directory.

Monday, January 5, 2015

Interactive Logon as SYSTEM

It is sort of possible to log onto a computer interactively as the superpowerful Local System account, better known as NT AUTHORITY\SYSTEM. You can even have the Start menu display "SYSTEM" as the username - Windows will give the account is own real profile, with libraries and everything. Fair warning, though, you will experience some strange stuff if you try to use it for everyday activities.

First, you'll need the excellent PsExec tool. Open an administrator command prompt and type the following line from a location where the PsExec file is reachable:

psexec -s -i taskmgr.exe

You will get an instance of Task Manager running as SYSTEM. Use it to kill all explorer.exe processes running as your normal account. Then, run a new instance of explorer.exe from Task Manager.

If you're running Windows 7, you'll see the sequence that occurs when a user logs on for the first time. If you're running Windows 8, you'll get a frozen taskbar that can't do anything. (This doesn't work all that well on Windows 8).

When you click on the Start button, you will notice that Explorer is indeed running as SYSTEM. You can go to your Documents, which may or may not show the files from your normal account. All processes you launch from the Start menu or with Windows+R will run as SYSTEM with all the rights and privileges thereof. Your home folder is now:

C:\Windows\system32\config\systemprofile

You will notice quickly that right-clicking almost any surface created by Explorer does not spawn a context menu. In my experience, everything seemed to go slower running as SYSTEM, but your mileage may vary.

Sunday, January 4, 2015

Please Don't Use Robots.txt

Webmasters can place a file called "robots.txt" in the root of their website to prevent automated web crawlers from accessing it. Access can be controlled by user agent and path. See Wikipedia's robots.txt for an example.

You may have also heard of the Internet Archive, a nonprofit organization dedicated to saving the Internet from link rot and content takedown. Sadly, and to the chagrin of several users, many robots.txt directives block the Internet Archiver. Also, when the archiver notices that a site has put up a robots.txt that prevents access to it, it retroactively denies public access to existing archives.

So, if a site exists for many years, is archived by the Wayback Machine, goes out of business or otherwise loses its domain name and content, and then is replaced by some squatter site that has a blocking robots.txt, all that real content is gone forever. (The Archive doesn't delete it from their servers, but they do deny public access.)

It's entirely possible for them to make the archiver ignore robots.txt (and many want them to) - there's nothing that can force a client to not read a website besides an IP block at the routing level - but doing so would likely create offense and shock in the webmastering world.

Therefore, I would like to ask every webmaster to allow "ia_archiver" and "alexa" to crawl their sites. The archiver robot does not access pages at high speed; it is generally a responsible robot. Nothing lasts forever, but it is very likely that the Internet Archive has better technological infrastructure than you. By allowing your content to be archived, you preserve humanity's knowledge for the future.

Friday, January 2, 2015

Replacing Images with a Chrome Extension

I decided to start learning about the development of extensions for Google Chrome, and one simple yet nontrivial test of the extension API is to replace images in the page. This post demonstrates how to do just that.

First, a manifest for the extension must be created and named manifest.json. (You should probably create a dedicated directory to store this file in, since we'll be putting more files with it soon.) It is a JSON-formatted configuration file that tells Chrome some critical pieces of information about your extension. This manifest.json standing alone is a valid extension:

{
"manifest_version": 2,
"name": "Chrome Extension Test",
"version": "0"
}

The manifest_version field is a constant, a signature that tells Chrome how to interpret the manifest. The name field is the title that will display for your extension on the Extensions page. The version field must consist of 1 to 4 numbers between 0 and 65535, separated by dots.

Extensions can inject JavaScript files into pages. This simple script (I named it "imgrepl.js", you can name it anything but you should place it alongside manifest.json) loops through every image on the page and replaces it with one of the files in the "img" directory:

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
imgs[i].src = chrome.extension.getURL("img/img" + 
 getRandomInt(0, 5) + ".jpg");
}

For this to work, you must create a directory named "img" in your extension's directory and place image files titled "img0.jpg" to "img4.jpg" in that directory. You can include more image files by changing the bold-italic number 5 in the above script.

Then, this script and the images must be declared in the manifest. When declared as a Content Script, a JavaScript file (or even a CSS file) will be injected into the specified pages. The injection should be done and the code executed when the document finishes loading (since that's when the image tags will have been added to the DOM). The images in the "img" directory need to be registered as Web-Accessible Resources so that the script can access them. The following file is the updated manifest.json:

{
"manifest_version": 2,
"name": "Chrome Extension Test",
"version": "0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["imgrepl.js"],
"runat": "document_end"
}
],
"web_accessible_resources": [
"img/*.jpg"
]
}

The <all_urls> value for "matches" tells Chrome to inject the JavaScript file into all webpages. If you use non-JPG images, make sure to declare them in "web_accessible_resources".

In Chrome, open the Extensions page (under "More tools" in the settings menu). Check "Developer mode", then click "Load unpacked extension". Navigate to the directory containing manifest.json and hit OK to load the extension. When you navigate to a page that loads pictures with the <img> tag, you will see them replaced by your images.

Thursday, January 1, 2015

Removing Context Menu Entries from the Windows Desktop

Some right-click menu entries (like the ever-pointless NVidia Control Panel) only appear when you right-click the desktop. These are particularly difficult to remove because most menu management tools don't see them because they don't check the right part of the registry. To get rid of these, you need to go to a slightly different part of the registry:

HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers

Delete the subkeys of that to remove shell extensions that load just for the desktop.