Sunday, November 30, 2014

The Bare Roots Server Resets

The decision was made - not by me, actually unilaterally by the server owner - that the world of the Bare Roots server, a YouTuber-only Minecraft server of which I am a member, will be reset. This means that the current world, along with all progress in it, will be blown away and replaced with a brand new map from a different random seed. This is after just six months of content production on the current map.

I can't say I'm happy about the reset, but I'm not angry or sad. I've been away (actually I vanished completely from our group) from the server for the past two months, and I welcome the chance to get back in sync with everyone as we start building our world anew. The server owner said that this reset is also an attempt to jump-start activity in the server - I'm not the only one who's been away. Of course, map resets are not a sustainable or particularly effective means of infusing the server with activity, historically speaking, but hey, it's a try.

Attempts will be made to bring in some new characters. Three have left and one is considering; I suppose we're all busy with real life. I've heard that there will be some "gimmicks" - gameplay modifications - in the new world, but no specifics are out yet.

I recorded my final episode on this map today, just the nineteenth in the series. Hopefully, next season will last longer and I'll be able to produce more interesting content.

Saturday, November 29, 2014

FMod - Certificates Issued

Today, I was busy studying for my online courses. I did, however, issue Abiathar VeriMaps Extended Distinction certificates (that's a mouthful) to a few members of the community who contributed to Abiathar, beta testers and icon artists. The certification process is really easy: I just fire up the VeriMaps Certificate Generator console program I wrote a couple days ago, type the name of the person and their distinction (e.g. "creator of Abiathar" for me), move the public-key ACERT file to the appropriate section of my public Dropbox, and send the private-key ASIGN file's contents to the recipient via forum PM.

This system seems to have reignited some interest in modding; some people messaged me back saying that they're going to try to make use of the certificate.

Friday, November 28, 2014

FMod - v2.2

I did some more testing of the new Abiathar v2.2 features, especially VeriMaps. It works perfectly on all of Abiathar's level formats (except TED5 MapTemp/MapTHead, where it is disabled because there isn't a convenient no-op zone to put the signature). I generated a certificate for Anonymous and put it and its public verification certificate in my public Dropbox so people can experiment with VeriMaps. I also tweaked the upgrade code so that depsfiles with no default set won't get upgraded, as there is no audio support for them anyway. I also made it so the VeriMaps Signature option does not appear for people without a VeriMaps signing certificate.

I published v2.2 on the PCKF and Keen:Modding, plus the command-line VeriMaps inspection utility. I am still awaiting replies and feedback.

Thursday, November 27, 2014

FMod - Cryptographic Signature

I'm on Thanksgiving break now, and in my breaks between being thankful, I made a serious push toward the release of Abiathar v2.2. The really hard parts - the actual manipulation of music and sound - have been done for a few weeks. Today, I finished up the smooth-upgrade routine for this version, which copies the new portions of the dependency file from defaults.aconf. (It was a lot easier than I expected.)

So, I did something kind of unusual. I decided to add a means of crypto-signing the levels, which writes an encrypted hash of the main level data to the no-op zone of the gamemaps file. That way, the game can load the file without getting confused and Abiathar can do whatever it wants. The certificates for level signing will be distributed to noteworthy people in the community. Matching public keys will be placed in my public Dropbox so that the hashes can be verified.

The purpose of this setup is to let people know who modified a level set last - whether it has been modified from its original version, say, by a mirror host. It is not copy protection or edit protection; anybody is free to open a signed dependency file and save it. If they modify it, however, the signature will become invalid - or the signature of the modifier, which is easy to detect. Therefore, it can't be used to see whether somebody had the original idea for a level, just who modified it last, which can prove that it was not modified from the state intended by the last author.

I call it VeriMaps, and it's nicely integrated into Abiathar now. It looks for a VeriMaps private key file in the current directory and will use it to sign saved levels once a menu option is checked. (Hashing and signing are somewhat expensive operations.) The signature state is always displayed in the status bar. It indicates whether signing is in use, who the signature purports to be from, and whether it is authentic. (Authenticity is checked by downloading the appropriate public key from my Dropbox, all automatically.)

Finally, I thoroughly tested the audio management on all three supported episodes. It worked great on Keen 4 and 5, but I got a patch offset wrong for Keen 6. After fixing that, everything seems good! v2.2 will hopefully come out tomorrow.

Tuesday, November 25, 2014

Collecting the Plaintext Password of an Already Logged-on Windows User

In a previous post, I explained how to set up a scheduled task to nab a logging-on user's password. I said that you could kick them off their session if you wanted to use that technique when they log on again, but getting their password if they're already logged in is probably easier.

To start, you'll need WCE and PsExec. Open an elevated command prompt with permissions on the target computer (typically domain admin). Navigate to the directory containing WCE and PsExec, then type this command:

psexec \\target -s -c -f wce -w

Replace "target" with the name of the remote computer containing the user's session.

The WCE output, including the plaintext passwords of all logged-on users, will be delivered to your console in a second. That was easy!

Monday, November 24, 2014

Robotics - Post-Meet Adjustments

Using what we learned from our experience at the first meet, we started to refine our robot for the next meet, which is in just two weeks. We wrote some agenda items on the whiteboard so that we have some goals to work towards.

First, we switched the gearing so that the wheels go immensely faster than they did before. The difference is amazing, and we can do a sort-of drift effect. With the amplified speed, we discovered another hardware problem: the right wheel wasn't moving all the time. After tightening its axle hub, everything was good.

To test the driving, we had to take our main battery off the charger and re-flash the Samantha module. The former part of that posed a problem: the battery connector is immensely difficult to disconnect. When we did that, it shorted and blew the fuse. Once we replaced that, the Samantha was easily flashed and everything was good.

We also rearranged the NXT and Samantha mounts to be more easily accessible and to make room for the eventual ball hopper.

While they did all this tinkering, I made a shopping list for things we need. It includes:

  • USB A-B cable
  • Allen wrenches
  • Tetrix Flat Max metal pieces
  • Replacement fuses

Saturday, November 22, 2014

Collecting the Plaintext Password of a Logging-on Windows User

I made a passing mention to WCE a little while back, and today I found a fun use for it. Suppose you need the password for a domain account. For example, you're a domain administrator who needs to investigate a problem user quickly: breaking the SAM/NTLM hash would take a while; resetting the password would destroy encrypted files and alert the user.

If you have administrative access to a workstation on which the target user will log on, you can use the aforementioned Windows Credentials Editor to steal the plaintext password, at least on Windows 7. (Windows 8 seems to have disabled the Digest Authentication module that leaks the password.) You'll probably need to disable or add an exception to the antivirus software, or alternatively use a PE packer - WCE is regarded in some places as a hacking tool. (Makes sense.)

Using your form of admin power, be it local or domain (use the ADMIN$ or C$ share), drop the WCE executable and a batch file containing the following somewhere on the target computer:

wce -w > pwd.txt

Open MMC and add the Task Scheduler snap-in pointed at the target computer. Add a scheduled task with the following settings:

  • General tab
    • Click "Change User or Group" and select SYSTEM
    • Check "Run with highest privileges"
    • Check "Hidden" if you want to be extra sneaky
  • Triggers tab
    • Add a new trigger
      • Pull down "Begin the task" and choose "At log on"
      • Choose "Specific user", then "Change User" specifying the target account
  • Actions tab
    • Add a new action
      • Ensure "Start a program" is selected
      • "Browse" to select the batch file
  • Conditions tab
    • Uncheck "Start the task only if the computer is on AC power"
  • Settings tab
    • Uncheck "Allow task to be run on demand"
    • Uncheck "If the running task does not end when requested, force it to stop"
Save the task. When the target user next logs on, their password (and that of any other logged-on user) will be dumped to pwd.txt. If you're impatient, you can kick them off, hoping that they don't suspect anything and that they'll log right back on.

EDIT (11/25): Alternatively, you can use PsExec to grab it from an existing session immediately and silently. See the new post.

Robotics [MEET] - Piano Man

Today was the first meet of the 2014-15 FTC season. This was a qualifier meet, so it was an opportunity to advance to state (for those that did well enough). Now, I held no delusions of adequacy or expectations to do well at all, but I was looking forward to seeing what others had come up with.

I made the final revisions to the engineering notebook in study hall. I then printed it out, stuffed the pages into individual page guards, and bound them in a three-ring binder. I had to tape the cover on because there were large smudges in the cover guard. The document looked pretty good all bound together, but it turned out we didn't need it at this meet - there was no judges' interview. I am glad I did it, though, or I would have procrastinated until the next meet and there would have been even more to write.

After the normal school day, we loaded the robot, our tools, and ourselves into some faculty vehicles and drove over to another high school where the meet was held. I'd say there were about 20 teams present.

Once we got our stuff unpacked and the robot on the table, I began programming the devices that had been added after I left yesterday's meeting. The other team (6723) had added a new motor and servo as part of their ball input mechanism. They also had a continuous rotation servo, which just spun continuously because I couldn't figure out how to make it do anything else. (I didn't have Internet access, and it was spinning the right way. I think our motto for this year so far should be "it's good enough.")

While I adjusted the programming, the builders continued tinkering with the ball intake device, eventually making it support both large and small balls. They also (after some matches) added a shield to mitigate trapping due to balls under the frame.

We passed software and hardware inspection easily. When it came time for the field test, though, we discovered that our battery was critically low. Many kind teams offered to loan us their battery or the use of their charger, but we just happened to have a really weird and unique connector for our battery that literally nobody had ever seen before. Though we had another battery, its fuse was blown. After much fumbling about looking for appropriate pliers, we put the working fuse from the empty battery into the full battery. It worked, and we passed field inspection.

Previously in study hall, I had created two autonomous programs (sort of three if you count the version for team 6723): one to do nothing (if we start in the parking zone) and one to drive forward for a few seconds (if we start on the ramp). In both cases, we end up doing nothing for a good amount of time. So, I thought of something for it to do while waiting: play the piano. Using the formula for frequency of the Nth note on a piano (which I happened to have open on a Wikipedia page on my laptop before I left an Internet-connected network), I created a routine to press random keys on a virtual piano for random (short) length of time. It sounded really cool, and thoroughly entertained the other teams during the matches.

Speaking of those matches, our general strategy was to use the appropriate autonomous program, drive around defensively during the tele-op phase, and push tubes onto and park the robot on the ramp. It turns out that most of the other teams there (or at least the ones we got paired up with) were in similar situations. We avoided kicking down the kickstands - it would release balls, which trip us up and are scoring elements for the other team - and tried to prevent the opposing alliance from kicking them down.

There were several hilarious moments:

  • Completely failing to score any points and also receiving a major penalty for pushing one of our tubes into the opposing parking zone. We ended the game with a score of negative 30 and, needless to say, we lost.
  • Losing control of one of the wheels due to a motor popping out of its mount, entirely disconnecting the gears. We were completely unable to turn or go up the ramp for the rest of the match.
  • Experiencing the complete wireless disconnection of the alliance partner who was supposed to do all the actual achievement. We played music with the four buttons of my controller that were originally intended to be software gear changes. (We were also trapped by small balls stuck under our frame.)
  • Shooting a small ball across the entire field. Even though we couldn't actually put it in a tube, we figured we might as well test the mechanism in production.
We came away with 2 wins out of 5, which is considerably better than I was expecting. It wasn't a total fail, and we learned what we need to focus on - I think that constitutes a success.

Thursday, November 20, 2014

Robotics - Pre-Meet

Today was the last day before the first meet of the season. We started by fixing the ball intake device’s mount so that it can actually pick up balls. It still jams occasionally, but is usually functional, especially with small balls.

A large amount of time was taken up by fixing the cable management. One wire had gotten tangled in a gear, resulting in torn insulation and general electrical unsafety. Additionally, the motor controllers had been plugged into the wrong NXT port, which was hard to discover because those ports were under the robot and hard to service. Some additional zip ties were applied to contain the many wires.

The robot can successfully drive up the ramp despite not having four-wheel drive.


Since there is no kickstand-hitting autonomous program, the infrared sensor is useless and will probably be removed tomorrow.

We made something of an effort this part of the season, but the robot does not have much functionality. We will be able to drive down the ramp in autonomous and up it in the endgame, but we can’t do anything in the normal tele-op period (we have no ball lift). Tomorrow’s meet will be an opportunity to see designs and implementation of such a device.

Wednesday, November 19, 2014

Robotics - Tinker

Today was one of the two days left before the first robotics meet in which I expected major changes and progress to happen. Unfortunately, that was not so.

We did re-mount the NXT in such a way that it fits inside the sizing cube. The cables were rearranged to be safer and not get caught in the wheels. The infrared detector has been hooked up, but not programmed yet.

There were a bunch of people trying to adjust the ball intake device so that it can fit and move the large balls, but I do not believe they were successful. The creator of that device should be present tomorrow, so we might get it properly adjusted.

We continued trying to attach small pieces of metal to the end of extruded channels to cap them (to use as telescoping pieces in a lift), this time by soldering. It did not stick, so we're probably going back to tape, or maybe just abandoning the lift. It hit us today that unless something miraculous happens tomorrow, we're not going to have anything to show at the meet besides the ability to drive around. That might just have to be how it is - it's only the first meet of the season.

Tuesday, November 18, 2014

Robotics - Too Little Too Late

Despite the extra-long meeting today to help us prepare for the meet on Friday, very little happened. (Note to everyone: we might start making progress if people actually came to and stayed at the meetings.) We're waiting on something or other for our robot (still the 3D-printed part?), so the very few people present from my team helped the other team disassemble a questionably-constructed lift mechanism and strategically apply electrical tape to cap off channels.

I started research into an autonomous routine, and discovered something incredibly annoying. RobotC's compiler does not accept "#pragma config" entries in header files; they must be in the main C file. Therefore, I can't move the motors and sensors setup into its own header file for convenient reuse and one-stop modification. (Some external preprocessing might have to happen.)

We started attaching the infrared detector to the robot, but the height of the beacon (21 inches, 3 above the maximum height of the robot) will make autonomous programming more difficult. While considering the challenge, I helped the other team test an alternative lift, which seemed to be successful.

Monday, November 17, 2014

Robotics - Panic Panic Panic

There wasn't actually a robotics meeting today.

Here are some things our team has:
  • Partially built robot
    • Currently in violation of electric safety rules
    • Doesn't have an autonomous routine
    • Can't actually do anything beyond driving around
  • Mostly empty engineering notebook
    • Doesn't have actual content
    • Is a plain Word document
  • A competition in four days
    • Yes, four days
Panic.

Panic.

PANIC!

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

...alright, everybody calm down. I'm starting on the engineering notebook tonight. Since I've published basically all you need in an engineering notebook on this blog, filling in the content will mainly consist of copypasta and interspersing the pictures I took on my video camera. I'll do it over this week.

It will be OK. Breathe, everyone.

Sunday, November 16, 2014

PsExec Doesn't Pass the Hash

There's a rumor going around the Internet, present in several wanna-be hacking articles that PsExec (the Sysinternals tool to run processes remotely) can use an NTLM hash to authenticate to the remote computer. This is not true of the standalone tool, but the PsExec module in Metasploit can (just set SMBPass to the hash).

If you want to pass-the-hash without Metasploit, you'll need to add WCE (Windows Credentials Editor) to your toolbox. You can then use that to set your session's credentials to those of a matching account on the target computer. Once that is done, PsExec without any authentication parameters will present those credentials to the target.

Unfortunately, that doesn't matter at all, thanks to a part of UAC. Unless the account is a domain account, in which case you probably wouldn't use an NTLM hash, users logging on remotely cannot use any administrative privileges they may have. It's like they're permanently trapped in UAC isolation. This can be disabled without affecting normal UAC, but only after changing an admin-only registry setting on the target computer, which hamstrings the entire attack.

Good job, Microsoft!

Saturday, November 15, 2014

Robotics - Ours Moves Too

Next Friday is the first robotics meet of the season in which our teams will compete. We took our last opportunity to have a Saturday practice, and we made some progress.

The engineers continued mounting the ball intake belt. That took a while, but after it, they mounted the NXT and Samantha module. Cable management is a disaster, but it is currently being swept under the rug with zip ties. With all the wheels finally put on a motor and connected to the NXT, I did the programming for a basic driving routine. This was incredibly easy thanks to the tele-op header file I had made for the other team - the main .c file was only five lines of code, plus the "#pragma config" lines for the motors and sensors.

Speaking of motors and sensors configuration in the Robot-C files, I should soon move that chunk of code to a header file. That way, we can change it in one place and affect both the tele-op program and the future autonomous routine. I did already re-arrange the header files in the file system to make this workable. I also wrote up a coding conventions document which will hopefully be followed by the other programmer.

The ball intake belt works fine, but it was mounted too close to the ground to pick up the large balls. That should be easy to adjust next meeting.

The other team also has their ball input mechanism working, plus a place to store the balls. (They almost have a way to get the balls into the tubes.) They are currently waiting for the continuous-rotation servos they ordered to arrive.

Friday, November 14, 2014

FMod - Request for Complaints

After reading "This Is All Your App Is: a Collection of Tiny Details", I realized that Abiathar - as a very complex program - likely has some sub-optimal points in the UI. Therefore, I called upon the Keen modding community to complain to me about every detail so that I can make it perfect.

The result is this K:M thread. Let's improve Abiathar!

Thursday, November 13, 2014

Robotics - Attach It Better

People actually came to today's robotics meeting (shocking!), including our best engineer. It turns out that my attachment of the ball intake assembly was actually upside-down and generally shoddy, so the real builders spent today making an actual attachment.

They also replaced the bar going across the robot (that gives it stability) with a single piece of metal. Previously, it had been several short pieces bolted together. Also, they made a better battery mount and rearranged the electronics hub area.

I did some rearranging of the code, placing the bulk of the tele-op code in a header file. I added all kinds of pre-processing conditionals to select at compile-time whether it would use four-wheel drive, but all based on the same file. That one file can be used for all tele-op programs (including the other team's) because it - in the driving loop - invokes a callback function in the including file, which handles robot- or routine-specific controls.

Wednesday, November 12, 2014

Robotics - Literally Nobody

Today, there was only one other robotics person at the meeting today, and he was on the other team. He was at least a builder, so he actually was able to do some things. The other team's robot is actually going pretty well: it moves and almost has a game-specific mechanism hooked up.

I helped replace the other robot's back wheels with omni-wheels and got them hooked up to motors for four-wheel drive. While he tinkered with their ball input device, I got to work coding the four-wheel drive and improving the software gearing.

My lack of experience with C caused some issues here. It took me about a half an hour to debug a for-loop, and it turned out that my initial understanding of loops was correct. The problem was that the Robot-C joystick driver starts numbering buttons at 1, not 0 like everything else in C. After I fixed that, testing power multipliers for the "gears" was easy.

There is now a header file for dealing with four-wheel drive so that my team can easily integrate it if we choose to go with such a drive arrangement. I added that and my improvements to the software gearing to the GitHub.

Tuesday, November 11, 2014

Robotics - Attach It

The robotics team continues to be short on attendance and supplies. We're still waiting to 3D-print some important piece, but we did our best to attach the ball input belt to the robot base. Since it's diagonal, we found some L brackets and bent them to produce the appropriate angle. It turned out that [1] it's hard to bend things with pliers and stop them from just arcing and [2] we didn't actually need to destroy those L brackets. 

I suggested that we take advantage of the metal channels with 8 holes around each attachment point and simply rotate one by 45 degrees and screw it in. That would have worked, but the corner of the channel hit the channel below it. running parallel to the floor. We then discovered some short flat pieces (that were bent up for some reason), which I hammered into straightness. The attachment was then a success. It was a challenge aligning the other side, but we (down to 2 people at this point in the meeting) got it standing up and stable enough.

Monday, November 10, 2014

Robotics - Have Design

On Saturday, some members of the robotics team - not including me - went to the Putnam (local museum) machine shop to work on the robot's mission-critical parts. From what I hear, they designed and 3D-printed some things, but the printer (or possibly the CAD operator) experienced some issues and produced unusable parts. They did, however, successfully produce a design sketch for our robot.

We're still waiting on some parts, but we did do some tinkering with the robot base. The battery and motor controllers have been mounted to the new design's base and wired up. I'm waiting for the builders to mount the NXT so I can start programming the basic autonomous routine.

I tested the software-geared drive program on the other team's robot, and it worked pretty OK, but they ran out of battery. While I waited for things to happen, I continued to show the new programming assistant (who is very good with CAD) Robot-C programming concepts, using the complicated geared drive program as a real-world example.

Sunday, November 9, 2014

Windows App Paths

Some people might know about this already, but it's a cool detail of Windows that I found fascinating. Pretty much everybody knows you can type program file names into the Run dialog and have them appear, and you can add directories to the PATH environment variable to make the Run dialog search those places if you don't supply a path.

But, some applications can launch even if their executable is not on the PATH. This is through a feature called App Paths. It is a registry key that maps executable file names (non-qualified) to full paths and provides their initial directory.

There are two instances of it, one under HKLM and another under HKCU, for everyone and the current user, respectively. You can find it at HK??\Software\Microsoft\Windows\CurrentVersion\AppPaths. Each subkey is the name of a program you can type at the Run dialog.

The default value of each key is the full path to the executable. (It doesn't even have to have the same file name as the unqualified name!) The Path value provides the initial directory. There seem to be some other properties that can be set, like UseURL and BlockOnTSNonInstallMode, but I'm not entirely sure what they do.

Saturday, November 8, 2014

FMod - All the Sound

It has come to my attention that there is actually a demand for the ability to import and export all the Keen:Galaxy sounds, not just the music. In fact, the final episode of the unofficial TUIT trilogy has all-new AdLib sounds.

So, I made a good effort today to add that functionality to Abiathar. Now, Abiathar isn't intended (at this stage) to be an amazing sound editor; just dumping the sound files out and sucking them back is all I need to do. The UI is, therefore, simple. The Audio Files menu item is now a submenu with items of its own: Resources, Export, and Import. (Resources produces the Audio Files dialog.) Those new entries simply create the save-file and open-file dialogs, respectively. Those dialogs set the list file, which binds all the sound files together (holds references to their filenames and chunk IDs). The individual sound files are spewed out in the directory of the sound list file, which can be placed anywhere.

It works well: I successfully round-tripped the Keen 4 audio resources. All the metadata of the sounds (e.g. priority, OPL instrument settings) are stored in the list file on the line representing the appropriate sound. It turns out that this is not how KeenWave did it - KeenWave just takes the chunks and dumps them out without any processing, header and all. I will add a config option to produce this behavior, probably making it the default.

Since Abiathar's patch generator is becoming increasingly important, serious modders might start using it. Therefore, there should be a convenient way to add user-defined patches that Abiathar doesn't have to understand. For that, I created the Patches dialog, which presents a text box bound to a string array in the project file, integrated by the patch generator into the outputted patch file. There is a notice above the field informing the user the Abiathar handles the header/footer, map header, tileinfo, graphics files, audio files, and music mappings.

Wednesday, November 5, 2014

Robotics - Ball Input

We were reminded at today's robotics meeting that there are less than two weeks left before the first qualifying match we want to attend - and we don't even have a driving robot yet. Today, we continued our efforts to remedy that.

After the pep talk, I opened up the RobotC IDE and started teaching a new member of the team (previously on a different, non-school team) robot programming. She has never done any CS or development work, but she seems to be getting it. I think the idea of having her on the team is for her to be my assistant, but I don't really need any assistance. I'll try to continue teaching her things throughout the season.

Since having a Samantha module is very important to making the robot move, I dug out the one that wasn't working and tried again. For some reason, it worked today with the same flash drive I had tried before. Whatever the problem was, it's fixed, and we have remote communication with the robot. I wrote a tiny test program (while teaching the new recruit) that runs the first motor.

That was used to test the engineering team's almost-production-ready prototype for the ball input chute. It consists of a belt with rotating spokes in a tube. They were tinkering with it for most of the practice, and it seems to work very well now. Setting up the drive motors will be trivial; the remaining challenges are to get a good autonomous program and to actually put the balls in the high tubes.

Tuesday, November 4, 2014

Crushers - v2.5

Crushers 2.5 is here! I made all the changes I discussed in a post a few days ago and a few more. Essentially all bugs have been fixed. I think the most distinguishing feature of this update is the adaptation to widescreen - this is the first game of mine to have that update.

Download Crushers 2.5 (EXE: 4.3 MB)

Monday, November 3, 2014

Robotics - Cleaned Up

Though I wasn't at the robotics meeting on Saturday, it seems the teams were fairly productive. When I arrived, I found that the parts room had been cleared of all the miscellaneous junk everywhere; everything is now actually in a place that makes sense, near similar things. A robot frame had been constructed with a motor or two. More interestingly, though, there was an almost-production-grade prototype for ball input device.

Today, people worked on the battery mount. (At least, that was what happened in the short time I could be at the meeting. I had to go do another thing for a good deal of the time.) This is important because we have historically had issues with the battery getting jostled and disconnected. I made some adjustments to the software gearing code, but did not get a chance to test them.

Sunday, November 2, 2014

FMod - Song Success

After finding and crushing some silly off-by-one bugs, Abiathar's Music Mappings dialog loads successfully. I finished coding the buttons that actually do the work of importing IMFs and fixed a bug in the song deletion routine that caused it to sometimes not clean up all the unused ephemeral slots.



There were some problems with saving the imported song name (mojibake), but I fixed that by switching to a UTF-8 encoding and prepending the actual header byte instead of putting it inside the GetBytes call.

I also made the Audio Resources dialog a persistent configuration dialog instead of a set-up wizard. (It can load the existing configuration instead of just wiping it out.) There is now an option to dissociate the audio files from the dependency file.


With those in place, it was time to actually test the mappings. I threw random songs into Keen 4 levels, exported the patches, and it worked! I could successfully choose which song goes into which level. Then I tried adding new songs (exported by KeenWave from Keen 6). That didn't go so well - the patch file seemed to be generated correctly, but I just got silence. I got the same effect when I overwrote existing chunks with the imported songs.

It turns out that KeenWave exports Type 1 IMF files; Abiathar by default expects Type 0. So, it had been importing the files shifted by two bytes, writing (usually) zero to various undefined OPL registers. I changed the default to expect Type 1 files after doing research and determining that the commonly used MIDI to IMF converter also produces Type 1 files.

With that change made, I tested the addition of new songs again. It worked! This makes Abiathar the first program (not just level editor) to automate the process of adding new songs. v2.2 will hopefully be out in a week or so.

Saturday, November 1, 2014

FMod - Music Mapping

With a rare bit of spare time on my hands today, I went back to Abiathar to continue my work on the now long-in-progress v2.2 update that will add music import and assignment support to Abiathar.

When I had last left off, I had an audio file configuration/dumping wizard and a poorly-designed Sound Manager form. I still don't have any idea how I want to deal with non-song sounds, so I ignored that (dead code currently) and moved on to music.

For that, I created the Music Mappings dialog. It consists of a list of levels, a list of songs, and some buttons to control which song goes to each level. I coded most of the buttons, but there are still strange issues involving the actual population of the dialog. Once I get the dialog actually rendering, I can show what I've done.