Thursday, July 28, 2022

Necrobiotics My Spinnerets...

If you don't like spiders, don't read this. ;)


Lots of buzz over the relatively recent release that some researchers are using dead spiders as grippers. There's literally nothing ground breaking here - they inflate the spiders' legs, causing them to extend, then release the pressure and they contract. That's how spiders walk in the first place.

They spend some time trying to justify it - oh, it's biodegradable, they can sometimes lift more mass than the mass of the dead spider, etc etc. Even invented a term - necrobiotics.

But it's all kind of bunk, isn't it? First off, there isn't a massive issue with grippers filling up landfills as disposable parts. So who cares that they are biodegradable? In fact, let's talk about that part!

I didn't see any mention of the number of useful cycles, but a typical gripper is going to rate this in the tens of thousands, if not hundreds of thousands. Lifespan of a typical gripper will be measured in years.

The spider starts decaying the moment they kill it (and yes, they kill the spiders they use for this experiment). The duration during which they are going to be useful, before the bladder is damaged or the creature simply becomes too dry to operate - that's going to be measured in hours. Which means at least every day, to keep your machine operating, you need to capture a spider, kill it without damaging it, carefully inject the actuator into the correct bladder, seal the hole, and then put your machine back together. Maybe you can get quick at that, but it seems like a lot of effort!

They talk about using them for pick and place machines, which need to rapidly and accurately pick up, position and place thousands of parts an hour. It's hard to believe that using dead spiders is going to revolutionize the already-very-simple-and-reliable grippers that are used for this. (Suction, if I understand correctly...) And there's no indication about how long the extremely tiny and fragile hairs used to actually make things stick to their feet will last without life to renew them.

That last point got me thinking. Clearly, the answer is not zombie spiders, but borg spiders. If we can implant a small computer that is capable of controlling the spider, we may have something. No, not as a pick and place, that's stupid. But for other things. Reconnaissance, for instance. I dunno what else. Targeted pest control, maybe. ;)

My thinking there is that the computer is able to drive the spider, as well as receive sensor feedback. But most importantly, it's able to turn off the interface and restore the spider to natural operation. The advantage of this is that, presumably, with appropriate rest breaks, the spider will naturally feed itself, and its biological processes will naturally repair the normal wear and tear of operation.

Morally, of course, this falls on the dark side of science. One might imagine that during periods of computer control, the spider would be experiencing a living hell. We might well be able to determine whether or not spiders have any sentience - any sense of self. If they did, I can only imagine the horrors they would try to cope with when the computer turns off.

I'm (fortunately) far too busy to create borg arachnids. Partially because spiders creep me right the hell out. And besides, for a pick and place, clearly ants are a far better choice. ;)


Wednesday, February 23, 2022

You're Doing it Wrong - Allocations

 One of the things that frequently amuses me/drives me into a rage is the modern mentality that any old design pattern is bad, so don't learn it. Then code breaks, we old timers nod and say "yes, that sounds about right", and get back "why is programming so hard? I'm going to fix it so it's easy!"


The article I'm reading right now is about a fellow who documents his battle to understand a kernel level crash that ultimately boiled down to a race causing a use-after-free. For those who don't know, this is exactly what it sounds like. You allocated some memory, then you freed it, then you accessed that pointer after the free. This is very bad and causes everything from security exploits to system crashes, because after a free the system is allowed to do anything it likes with that memory location, including re-allocating it, or marking it illegal because the address space is needed elsewhere.


Use-after-free is controlled by having a clear memory policy. This is a design concept wherein you have a set policy that defines unambiguously who owns a block of allocated memory at any given time. Some systems may have multiple owners - in this case you need a management system such as smart pointers. Some systems may pass ownership from one function to the next - in this case it's usually wise for the code which is losing ownership to forget that pointer as soon as possible. For instance, you can null it out - then you /can't/ accidentally use it. There is literally no reason to remember an address once it has been freed - null that pointer. 


This also helps a lot with memory /leaks/. If you know who owns a block of memory, then that implies quite strongly who is responsible for /deleting/ that block when it's no longer required.


This is all a design concept - nothing happens in code until you decide it. And once decided, no exceptions. Exceptions cause bugs. And besides, if you need exceptions, that means your design doesn't fit the application and needs to be rethought. My personal observation is that my design isn't right till the third time I implement it. Less than that, and I get nervous. It's like having your code build and run the first time - you should be thinking 'Oh no. What did I miss?' ;)


Stable, reliable code beats buggy code that's 0.001% faster on Tuesdays. EVERY. SINGLE. TIME. You'll thank yourself when those good night sleeps start taking the place of early morning panic calls and late night debug sessions.


Although I do agree with how the fellow ended it. I'm not naming him cause my rant isn't really his fault, and ended up a little off topic, but kudos, bud.


"Just go to sleep, because everything is broken anyways :)"


Thursday, December 16, 2021

End of Year Blog Time

 Looks like I didn't do this last year... but the year before you got a 10 year retrospective, so I'm not too worried. ;)

(Oh, looks like I did it on Twitter last year. 

https://twitter.com/Tursilion/status/1345228785629556736

Oh well, I already started this here...)

It's hard to believe it's only been a year since I settled in up here -- and it's also hard to believe it's only been a year. I actually applied for a number of jobs, and it surprised me how much I dislike interviewing. ;) I guess, in fairness, I only had three jobs in the US that whole time, two of which I knew what I was doing, and one which was so amazing I'd do anything. (Also an honorable mention that I would have taken, they were awesome but fell into the 'knew what I was doing' bit...)

Anyway, THIS year... well, applied for a handful of jobs. One was pretty exciting - they were a manufacturing robot company and I could have kept using my skills, but they declined. I felt like maybe I offended them with some of my questions about the hardware... got to remember not to question the design until AFTER hired... ;) 

e-stop button

Amazon chased me for a while - through the year in fact. But I never ended up agreeing to the full interview process. Maybe someday. They were smart when I interviewed down south...

I ended up working on a gas detection camera instead - and that was a whole new world for me. ;) In the end, my own contribution was entirely on the Linux software side, but it was a neat little world that I completely was not aware of.

graphic of methane spray viewed in infrared
Still had a few companies try to tempt me back down south, and it was pretty close. But... nah. Open to certain other countries though...! ;)

All I can say is my taxes are going to be fascinating this year... :p

But this usually isn't about boring old work. Unfortunately, it was a really quiet year for me. The pandemic forced a lot of things to be help back, and since I took work I didn't get /any/ of the personal progress I was hoping for. 

'keep your nose to the grindstone' with old time photo

I got my car side window smashed for the first time ever. They didn't take anything, just rifled through and left it all on the seat. They stole my neighbor's car, and there's some suspicion they were looking for spare keys. Still cost me $500. I was surprised, though, I park within inches of a concrete wall, yet that's the side they smashed the window and crawled into the car on. I can't even fit there - I can't imagine how skinny the thief was.

What made it doubly annoying was only two nights earlier, they had gone through my car again. Apparently that night I left it unlocked by accident. Again, took nothing, just left it on the seat. They already knew there was nothing there, why smash my window? I was really annoyed cause I had considered putting a webcam on my car dash, but I couldn't figure out how to power it.

I sadly don't have the pictures anymore - there was nothing in them I wanted to keep.

I actually talked to Natsume about licensing Double Dragon, to try for another retro port. They were friendly but eventually declined. Doing ports legally is kind of neat but it IS hard to get people to talk to you. ;)

Got my COVID shots, of course -- ended up with 3 of them! I got AZ first, and when that was declared no good for travel, I was able to get two moderna shots to cover that. All three shots made me feel lousy for a day, yes. But now I'll never know if I actually had it when I was in Asia. ;)

I got a lovely final gift from Tokyo Disneyland - one of those laser printed 3D engravings inside a glass cube of the rose from Beauty and the Beast, with my name and thanks for helping with the attraction. I am looking forward to finally being able to fly back to Tokyo and visit the park as a guest, someday. :)

Beauty and the Beast rose in 3d crystal block from Tokyo Disneyland

I've continued working with the Second Life wrestling group, though Second Life had several bouts of the usual internet drama. We seem to have survived them, and for a little while I even refereed
a second federation, using a grump gryphon character I had created for earlier stories.

Oscar the Gryphon at Titan Wrestling

We also did a big charity event called Slam-O-Ween, part of a week long series of events on SL for Breast Cancer. I dressed my raccoon ref up as Elvira for that one. We raised 3/4s of a million "Lindens" over the entire event (about $3500 US), with our silly little animal wrestling accounting for a double-digit percentage of that.

Sila the Raccoon as Elvira at Slam-O-Ween

I also ended up aging up my old TLK Muck wizard hyena pup, and now he's a wrestler too. ;) I got permission from the person who created a lot of the original lore that he ended up in, and am using it as his gimmick. ;) I'll be honest, there was a significant time investment here... but I was lucky enough to get help from a skin designer and even from a talented singer/songwriter and friend for her music.

Danur Hyena at Sunday Night Frontline

Danur - Rithandren Ranger. Danur's title for his intro video.


I did some minor updates to Classic99, and I did some minor updates to my ponyscript, some updates to my VGM player, but precious little else, honestly. I let myself get overwhelmed again - and so quickly. The ONE task on my TODO list was Classic99 V4, and I'm going to try to meet that by the end of the year by the letter of the law, if not the spirit. (That is, my goal is 'boots', not 'useful'. ;) )

Blank blue screen, all Classic99 v4 can show right now.


Oh! I did sidetrack and make a tribute to Thunder Force III on the TI - converting all the music with my VGM toolchains and creating some of the intro graphics to resemble it!

Thunder Force 3 title page rendered on the TI

I did take one trip out to Ottawa, right before Omicron became the new buzzword, and it was nice! But it felt so weird to be flying after so long. ;) I didn't take any pictures at all...

I also let Cool Herders DS leak out to an archive site, just to see if that gets a single person to play it and comment on it. (Nope. Not yet. I actually thought this version was fun... ;) ). That's over here: 

https://www.gamesthatwerent.com/2021/11/cool-herders/

And of course someone immediately posted it with invalid license terms over to Archive.org... well meaning perhaps, but bad form. Still... here's that:

https://archive.org/details/cool-herders-beta-90-percent

Plans are in place for next year to be more productive - if the new job doesn't crush me. They both promise my weekends will be fine and that the work will be super challenging. This will be interesting. ;)

So yeah, that was 2021!


Tuesday, September 7, 2021

Finally Breaking Through Is Always Nice!

I've been fighting a small problem for the last two days, and I finally just figured it out. It's such a relief to finally have it make sense that I decided to write it up before I even coded the fix, which it was still fresh. It was a small issue, but in a very large project, which made debugging difficult.

Back in the beginning of this whole pandemic I published version 2 of my VGM compression toolset, this one much more flexible and able to import many more formats. Last month someone finally used it. Yes, retro development is sure rewarding! Anyway...

This guy ported all the tunes from the NES version of Smurfs over to the TI, and released individual programs with my Quickplayer, which wraps a tune with a standalone player and lets you add some text. It was sweet, but awkward... and since he asked if anyone could make a cartridge, I wrote a tool that would take a folder full of program images, and build a loader cart with a menu.

This was a good start, but I decided that I also wanted to take all the visualizers I've done over the years (four of them), and make them available in the Quickplayer too. I adapted all of them to fit in the 8k low memory block on the TI, and ported them to Coleco as well. Then I coded a couple of flags that could be externally set that could be used to find a selection program for chaining (with random play as my intent.) It took some fiddling, but that all came together eventually.

So before diving into the issues that the random player gave me, let's recap...

First, we have the music player libraries themselves.

They are wrapped around a song in a standalone player program -- there are FIVE player programs (four with visualizers, and one just text like I originally released). Plus the program that does the actual wrapping and generates the final code.

Then we have a tool that packages these programs up, and auto-generates a loader program for them (so, the tool, and the loader program).

And we have a menu that selects which loader will be executed. So we're up to 9 programs, and then I wrote the randomizer.

I expected this part to be easy, because I had carefully compartmentalized everything. To explain a bit, the TI file system loads program files in individual 8kb chunks. In addition, the TI's memory map splits the RAM - an 8k block at 0x2000 is where I store the player, and a 24k block at 0xA000 gets the music data. So, the player was always in a separate copy block to the data.

The autogenerated code thus always looks a lot like this:

>  60B6  0200  li   R0,>6004 Ball
   60BA  0201  li   R1,>6000              
   60BE  0202  li   R2,>2000              
   60C2  0203  li   R3,>0cb4              
   60C6  06A0  bl   @>619c      (Copy data)          

   60CA  0200  li   R0,>6006    Data      
   60CE  0201  li   R1,>6000              
   60D2  0202  li   R2,>a000              
   60D6  0203  li   R3,>058a              
   60DA  06A0  bl   @>619c                

   60DE  06A0  bl   @>600c      Trampoline to start          
   60E2  2000  data >2000 Start address

There's a bit of an extra wrinkle in there. The TI cartridge memory space is only 8k, so we're also paging 8k banks. So, R0 is loaded with a page reference, R1 is a source address, R2 is a destination address, and R3 is the number of words to copy. 619C is a subroutine that banks the page in and does the copy. The first destination address is also the start address, and so it's also stored in the data at the end.

This all worked pretty well, so when I did the randomizer, I decided to have it pull the copy data for the first part, which is always the program, do the copy itself, and then randomly jump to the data copy for a different one. This would allow the music and visualizers to mix and match, so to speak.

It tended to work... sometimes. It was very random. Of course, I did introduce two random numbers. I was able to try hard coded values through the debugger and generate combinations that worked and combinations that didn't.

If you have already worked out why, damn you. You should have told me yesterday and saved me some time! ;)

If not, my next clue was that when it didn't work, it was jumping to incorrect addresses - addresses that tended to correlate with different programs than the one that appeared to be loaded in RAM. But out of all five player programs, I only used two start addresses, >2000 and >2100. So there was always a chance of it working.

A sensible fellow would have sorted it at this point, but it took me just a little longer!

I took a lot of notes about start and load addresses, observed patterns, stepped through the code, and probably the fifth time I stepped through a broken start it suddenly clicked.

This is your last chance to tell me what it was! ;)

So yeah. The program is copied in the FIRST block, and the FIRST block contains the start address. JUMPING to the data copy in the last block means that we would use the start address contained at the end there -- which may or may not be for the code we actually loaded, since we are playing mix and match.

To clarify, here's the loader for Piano:

   616E  0200  li   R0,>600e   Piano <-- no page increment 
   6172  0201  li   R1,>6b0e              
   6176  0202  li   R2,>2100              
   617A  0203  li   R3,>0883              
   617E  06A0  bl   @>619c                

   6182  0200  li   R0,>6010   Data         
   6186  0201  li   R1,>6000              
   618A  0202  li   R2,>a000              
   618E  0203  li   R3,>058a              
   6192  06A0  bl   @>619c                

   6196  06A0  bl   @>600c     Tramp      
   619A  2100  data >2100      Start address

Note the different start address!! So, if we copy the Ball program, then jump to the data copy for Piano, we'll end up starting in the middle of the Piano code!

Of course.. the "right" way to do this wouldn't be hacking around your own code... you'd store the player programs in one place, and the music in another... but I wanted to be able to work with programs anyone generated -- plus I expected it to be faster to do. ;) (It probably wasn't!)

The lesson is - beware of red herrings. Validate your assumptions. And for goodness sake, pay attention when you're doing hacky things like running your own code out of order, even if it was on purpose!

Monday, June 14, 2021

Technical Debt is...

 Every time you ignore an error message and say "I'll worry about that if I see it again", you've added technical debt.

Every time you don't check a function's error return and say "We'll add that after it's all working", you've added technical debt.

Every time a function doesn't work, and you just add a comment that says "This doesn't work" instead of investigating why, you've added technical debt.

Every time you fail to test a function at all, and don't check if it's actually working, you've added technical debt.

Saw all of this tonight... ;)

A lot of people think that technical debt is a function of long term code, of systems that have become weighted down with hacks and patches. Some people think it's a deliberate choice, and therefore you can come back around and clean it up easily enough.

But you can't. It's all lost. You've no idea when that error will pop up again, but it will probably be in front of a customer when you think everything's working. The system will malfunction on Thursdays but you completely forgot that the main interface library that you used had an error return "FAIL_ITS_THURSDAY" that you didn't add a handler for -- now you have to launch a full debug process to find what's wrong (and since you didn't start troubleshooting till Friday, it'll take you a week.) You can't figure out why the system isn't processing fractals because you forgot that the fractal generate function has a tiny little comment that says "// This doesn't work, come back to it later (mb)" - hope you can find it!

Technical debt costs twice what you paid to put it into the system in the first place. And worse, it's often passed on to someone who wasn't there for the original design, so they've never heard of the library that hates Thursdays, only ones that hate Mondays. They'll need three times as long to find the issue. The customer doesn't care that you meant to come back to investigate that error code, they only care that it didn't work. And everyone at E3 was waiting to see your cool new fractal generator, not a grey box that pulses slightly.

Why would you want to deliberately pay all that? Most of the time, the developer of these debts could have fixed them in minutes. Pay the minutes, don't get so caught up in the excitement that you pay the debts later.