2022-12-31 - 2022 Retrospective
2022 has definitely been a stressful year for me but I wouldn't necessarily say it's been a bad year. I think I have accomplished some things, which is good. They weren't all things I set out to accomplish but that's okay.
Lupo
I've been thinking about getting a second cat for a while. Robin, my other cat, is getting older and I didn't want to be in the position where I had no animals. So with that in mind I put in an application for a cat at the end of January and picked Lupo up on the 31st.
In his bio it mentioned that he made a wheezing sound but they weren't sure what the problem was. When I was talking to the person from the cat shelter I also found out he had some digestion issues. I was a little worried at that point about getting a "sick cat" but after I did a video call with his fosterer, I couldn't say no. He was just so full of life and happy. Running around and playing with toys.
Those first few months were very stressful. I worried I would wake up to find him not breathing or that Robin and him would never get along. Robin was very scared of him when he first arrived. The first day I let him out of hid room she just lay in her cat bed by the window. I figured that was a good sign, she was relaxed, but even after I put him away she wouldn't move. She was scared stiff. It was a struggle to find the right balance between letting him be out and exploring and giving Robin time to herself to relax. Then came the vet visits and the real worrying started
I took him to my local vet and got referred to an animal hospital to investigate what was going on with his breathing. I was hoping it would be something simple. A surgery to remove a growth or some medication to deal with an issue, and then he'd be perfectly normal. It turned out to not be that easy. The vet found that the tissues at the opening of his larynx had thickened and fused together so they weren't moving the way they should. This was a novel condition so there was no easy answer. Their recommendation was to remove some of the tissue in the hopes of giving him a larger hole to breathe through.
He went in for surgery at the end of June. At first everything seemed to go great. He came home the next day and we spent a day hanging out in his room and watching movies. On the Friday I woke up, gave him some wet food, and then went back to sleep. I went to check on him a little latter only to find that he hadn't eaten any food and was very lethargic. I had been a little worried about him laying around the day before but figured it was just the meds he was on. I rushed him to the vet and they put his temporary tracheotomy back in. The tissue in his larynx had swelled up and there was quite a bit of scar tissue that was limiting his air intake.
The vet gave him steroids to reduce the swelling and started scraping out the scar tissue. The hope was that he would stop producing it after a while but that turned out to not be the case. Next we tried to tie back one side of the tissue but that broke and re-closed itself. Finally we decided to abandon the larynx and give him a permanent tracheotomy. This led to another week of stress as we weren't sure if it was going to be viable. I actually had a plan to go and stay at a hotel near the hospital just in case I had to run over to say goodbye.
Luckily he pulled through. The surgeon was off his first week with the tracheotomy but was able to clean up the site when she got back and that seemed to help a lot. He came home on July 19th and has been home ever since. He spent most of three weeks at the vet. Every morning I got a call in the morning saying how he was doing. Then I'd wait for a call from the doctor to get a more in-depth report and discuss what was going to happen next. Then I went and visited him for a bit. Having a cat in the vet for three weeks isn't fun, especially when you aren't sure if he's going to make it. What makes it worse is I was worried he wasn't going to make it right up until he came home so I didn't even have time to recover from that before I had to start taking care of him.
The tracheotomy requires periodic checks to make sure it's clear and he can breath okay. He also gets saliva and food down his wind pipe so I have to watch him when he's eating and wipe away anything that comes out of his hole. Humidity seems to help him be able to get mucus and saliva out so he spends 35 minutes in the bathroom after each meal and then I give him a thorough cleaning and check. He sleeps in the second bedroom with the humidifier and hasn't had a problem so he can be left alone. Day to day it's not a lot of work but he could have a problem at any time so I'm still warry about leaving him by himself for a long time.
I think he's doing much better post-surgery. He seems calmer and to have more energy. I think pre-surgery his air intake was lower but more consistent. Now it can be much better than it was but it also fluctuates as he gets mucus or saliva in there which limits his air intake. Robin and him are getting much better but they still aren't comfortable with each other.
I still worry about him but it's likely to be several years before he has a major problem and he seems happy, so that's the most important thing.
Sickness
This has also been a year of sickness. First off I got a dental crown to replace the tooth that got infected and needed a root canal. That's not technically a sickness but it was annoying to have a weird stub tooth for a few weeks and then to get to a new bite.
The day after I took Lupo in for his initial exam at the animal hospital I got a Central Serous Retinopathy, which is when you get a bit of fluid in the back of your eye. It causes a weird bump in your retina which distorts your vision. That turned out to be stress related, stupid bodies, and luckily went away quickly.
Since September I've had 4 throat infections which have been extremely annoying. The infections knock me out of action for a bit but then the antibiotics make you not want to do anything. So that's been fun.
Mafia Story Comparison
I've only managed to make two of these videos this year but I'm pretty proud of them. I think I'm improving and getting better at making the videos and saying what I want to say. I have no desire to become a professional YouTuber but being able to make videos does give me another creative outlet which is nice. Plus I really want to show people the weird decisions the developers made with The Definitive Edition.
Boxed Software Collecting
This one has been a bit of a surprise to me. Last year I got interested in finding sound cards that worked with older versions of windows and DOS. This grew into a desire to get original boxes for those cards. In January I wondered if it was possible to get boxed copies of the old programs and operating systems I've been using. It turned out it was rather easy. Over the past year I have bought a bunch of boxed copies of old software in various conditions.
Ostensively this is so I have manuals to help me use these old programs but I also enjoy having the original boxes to display. I also like knowing that I have a physical version of all the disk images that I'm using.
Website
Early this year I finished converting all the pages to use database entries instead of flat-files. This should make adding new content easier in the future. I also added a series section to the archive page.
My actually postings have dropped off. Some of this was due to stress and some of it was because I couldn't leave Lupo and Robin alone upstairs without them fighting. Then the infections keep zapping my motivation.
*Edit*
And right now I fixed an issue where the archive page was using the UTC post date when splitting the posts into month and year.
Computer History Tour
In the last few years I bought an Altair 8800 clone computer and a few other reproduction and FPGA systems. My plan was to work my way through home computer history and try to lean as much as I can about it.
At the beginning of this year I finalized an 8080 assembly program to dump memory to the screen as .hex records. In November, I finished documenting this program and a front-panel adder program I wrote last year. This represents step 1 in my history tour, programming in assembly using the front-panel and monitor program on the Altair 8800.
Code Formatter
Documenting the Altair 8800 programs also required some revisions to the Code Formatter. It wasn't handling numbers very well and assembly uses a lot of hex and octal numbers.
The first step was documenting the existing program so that I understood how it worked. Next I did quite a bit of refactoring to move item specific logic out of the main program and into their specific classes as well as re-doing the number logic. Then I had to re-do the documentation to match the updated version. The work was mainly done in the C++ version but also got ported to the website version.
Breadboard Computer Project
This is a kit I bought a few years ago but only really got into this year. I actually have it mostly finished. I just have to add the switches and implement the interrupt logic. I also have a couple ideas for programs I can write for it.
I was hoping to finish it this year but I recently broke the legs off of one of the ROM chips and need to order some new ones. I was trying to install sockets to make removing and replacing the ROM easier but that didn't go to plan.
Disk Structure Investigation
This was a surprise project. I've been curious about how floppies and hard disks hold data for a while but never got around to really looking into it.
While expanding my software collection I came across a problem. The floppy emulator I use seems to only like 1440k floppy disk images. In most cases this is okay because you can just make a new image with the same files. The problem is bootable disks which expect data to be in specific places. I tried using the program I use to image disks, WinImage, to convert the images but they still didn't work.
This lead me to research floppy disk formats and to writing a console program to decode the data on the disk to figure out what the problem was. I think the issue is that WinImage writes 0s to blank sections of the image while actual floppies have a bunch of F6h bytes. That difference seems to be upsetting the computer, the emulator, the USB formatter for the emulator or all three.
It turned out that floppy disks weren't actually that complicated, so I added the ability to expand floppies to the program that I had written. This reads in the existing image, updates the BIOS parameter block values, adds new FAT, root directory entries and blank sectors, and then blanks out any unused sectors. After some initial problems I was able to successfully generate bootable floppy images. The main issue was making sure my math was correct.
Then I ran into a hard drive program. OS/2 2.11 is very persnickety about installing. I got it to install into a virtual machine but I can't get the installer to even start anywhere else. I tried copying the Virtual Hard Disk image to a Compact Flash card but that didn't work. I think the partition information in the Master Boot Record is wrong. So now I need to figure out how MBRs store partition information so that I can update the values on the CF to be correct.
This lead me to write a graphical version of the disk decode program. So far I just have it decoding the boot sector of floppy disk images but I think it should be fairly easy to expand it to display other parts of the image and hard disk images. Except I didn't have any good hard disk images. The program that I thought would do this for me adds an undocumented header to the files it generates so that's no good.
This lead me to start investigating how to read data from a physical disk which was an extremely deep rabbit hole. I finally figured out that writing an assembly program is likely the easiest way to do it but now I have the difficulty of writing an assembly program.
Currently the program can read and write a single sector.
Stats
- Blog posts – 5
- Writing pages added - 17
- Videos made – 2
- Books read – 13
- Programming textbook chapters completed – 17
- Programming project commits - 67
2022-10-29 - In IL: VB Classes, Modules and Structures
Last time we looked at Classes and structs in C#, now we will look at the Visual Basic .NET version of those concepts. This program has a variety of Class, Module and Structure definitions.
This program is basically the same as the C# one we looked at last time but with some terminology differences. For example we have Friend instead of internal, MustInherit instead of abstract, NotInheritable instead of sealed, and Structure instead of struct. If we look at the IL we see that these keywords are interpreted the same way.
As you can see FriendClass also gets marked as private the same way InternalClass was in the C# example and PublicClass still gets marked as public.
The nested classes all line up as well with NestedProtectedFriendClass being defined the same way as NestedProtectedInternalClass
The Interface definitions match.
As expected MustInheritClass and NotInheritableClass align with AbstractClass and SealedClass respectively
The derived and interface implementation classes also line up with their C# counterparts. Interestingly both IL and VB use the Implements keyword to indicate a class is implementing an interface but VB uses Inherits to indicate a derived class while IL uses extends.
The Structure definition matches the C# struct
The enums also line up although interestingly VB won't let you create an enum with no values defined
The only class defined in C# that we don’t have in VB is StaticClass. The VB version of static is Shared but you can’t use shared on a class. Instead VB has the concept of a Module.
Modules work much the same way as C# static classes except that they aren’t called classes and that they are automatically visible throughout the code-base. As you can see this is just a VB concept as modules also get compiled into IL classes. It’s interesting to note that while C# compiles static classes as abstract and sealed VB only compiles modules as sealed. To prevent modules being instantiated VB compiles them without a constructor.
As you can see the distinctions made by higher level languages are removed in exchange for the simplicity of IL. Everything is a class in the end.
Next time we’ll look at field definitions and start digging into how classes work.
2022-09-03 - DataTypes: Numbers
So far we’ve only used bits to store logical values, true and false, but there’s limited information that can be represented with just true and false. How do you encode that a building has 5 floors? A series of boolean values encoding if the building has floor 1, floor 2, floor 3… ? That’s manageable for a few floors but will get very complicated if you have hundreds of them. Luckily bits or binary-digits as the name suggests can be used to represent binary, base-2, numbers.
To start let’s look at decimal, base-10, numbers which is how we typically think of numbers. If I showed you the number 824 you’d probably think of it as eight-hundred and twenty-four. Each digit position represents a power of 10. You’ve got 1s, 10s, 100s, 1000s etc or using powers of 10 we have 1 = 100, 10 = 101, 100 = 102, 1000 = 103 etc. We can think of 824 then as 8 x 102 + 2 x 101 + 4 x 100. This is actually how all bases work, the difference is the number you are multiplying the digits by.
Binary numbers are base 2 which means they have 2 digits (0 and 1) and the digit positions are powers of 2. So the first position is 20 = 1, the second is 21 = 2, then we have 22 = 4, 23 = 8, 24 = 16 etc. To convert the binary number 100101 to decimal we can use the same process we used for 824 but with powers of 2 instead of powers of 10. This gives us 1 x 25 + 0 x 24 + 0 x 23 + 1 x 22 + 0 x 21 + 1 x 20 which is 32 + 4 + 1 or 37 in base-10. Basically you add up the power of 2 for any position that has a 1 in it. The more bits we have the larger the number we can represent. With a byte we can represent numbers for 0 to 255, with 2 bytes we can go up to 65535 and with 4 bytes we can go up to 4,294,967,295.
To convert from decimal to binary you divide the value by 2, keep track of the remainders you get until you end up with 0 and then put the remainders in reverse order. For example 37 / 2 is 18 with a remainder of 1. 18 / 2 is 9 with no remainder. 9 / 2 is 4 with a remainder of 1. 4 / 2 is 2 with no remainder. 2 / 2 = 1 with no remainder. 1 / 2 is 0 with a remainder of 1. Working backwards our remainders are 1, 0, 0, 1, 0, 1 which is the binary version of 37. Each divisions determines if we need a bit set at the current position starting from the right-most bit. The first division determines the zeroth bit, the next division determines the oneth bit etc.
There are two other bases that come up often in computing. Octal, or base 8, which uses the digits 0 to 7 and hexadecimal, or base 16, which uses the digits 0 to 9 and A to F (A = 10, B = 11, C = 12, D = 13, E = 14, F = 15). These bases are used because you can easily convert between them and binary by grouping bits. This gives use a more compact way to represent values without having to do complicated conversions. To convert from binary to octal we use groups of 3 bits and then write the value of those groups. The binary number 101100011010 split into groups of 3 bits would be 101|100|011|010 and if we take the values of those groups we get the octal number 5432. Hexadecimal works the same way but with groups of 4 bits. 101100011010 split into groups of 4 bits would be 1011|0001|1010 and if we take the values of those groups we get the hexadecimal number B1A. To convert back we simply expand the values back into 3 of 4 bit groups depending on our starting base. Converting from these bases to decimal works the same way as with binary but with powers of 8 and powers of 16 respectively.
All the arithmetic operations work the same with base 2 as they do with decimal numbers just with less digits. So instead of 1 + 1 equaling 2 we have 1 + 1 = 0 with a carry leftover to give us 10 which is the same as 2.
Next time we will look at how to represent negative numbers
2022-03-05 - An Incomplete History of Microprocessors
At the dawn of the computer age not only were they massive but their components were massive as well. Large collections of vacuum tubes or discrete transistors all wired together. A processor could fill a cabinet all by itself. The invention of integrated circuits allowed for all these components to be placed inside a single chip that could fit in your hand. Microprocessors are integrated circuits designed to process information and execute instructions. The shrinking of the processor lead in turn to the shrinking of the computer which allowed them to be used in homes and schools. Instead of needing a dedicated room computers could now fit on a desk. This list focuses on microprocessors used in consumer devices from the 70s and 80s.
1971 - Intel 4004
4-bit registers and data bus, 12-bit address bus (2048 bytes)
The 4004 was the first commercially produced microprocessor. Originally designed for calculators it soon became clear that it could be used to build a complete, if limited, computer
1974 – Intel 8080
8-bit registers and data bus, 16-bit address bus (64 kiB)
The 8008 was intel’s first 8-bit processor but it was the 8080 that really kicked off the microcomputer revolution. Computers like the Altair 8800 and the IMSAI 8080 were huge successes and lead to the standardization of the S-100 bus and CP/M as the first commercially available operating system.
1974 - Motorola 6800
8-bit registers and data bus, 16-bit address bus (64 kiB)
The 6800 found some use in early home computers like the Southwest Technical Products 6800 and the Altair 680 but it never caught on the way the 8080 did.
1975 - MOS Technology 6502
8-bit registers and data bus, 16-bit address bus (64 kiB)
Designed by former Motorola employees based on the 6800, the 6502 would go on to become one of the big players in the 8-bit micro generation. Used in computers like the Apple, the Apple II, the Commodore PET, the Atari 8-Bit family, and the BBC micro.
1976 - Texas Instruments TMS9900
16-bit registers, data bus and address bus (64 kiB)
Designed for use in TI own computer line-up the TMS9900 was one of the first 16-bit processors.
1976 - Zilog Z80
8-bit registers and data bus, 16-bit address bus (64 kiB)
Designed by former Intel employees and based in the 8080 the Z80 would become the other big microprocessor of the 8-bit era. It was used in computers like the TRS-80, Sinclair ZX80/ZX81/Spectrum and other business oriented computers. Being compatible with the 8080 it also ran CP/M.
1978 - Motorola 6809
16-bit registers, 8-bit data bus, 16-bit address bus (64 kiB)
The 6809 was similar to the 6800 but added some 16-bit features which gave it a step up over the other 8-bit processors of the time. It’s main use was in the TRS-80 Color Computer.
1979 – Intel 8088
16-bit registers, 8-bit data bus, 20-bit address bus (1 MiB)
The 8088 was used in the first-generation of IBM Personal Computers and is the grand-uncle of the modern x86 architectures which currently dominate the home computer market. It’s brother the 8086 had a full 16-bit data bus and was therefore faster but the 8088, with its smaller data bus, allowed for cheaper motherboards.
1979 - Motorola 68000
32-bit registers, 16-bit data bus, 24-bit address bus (16 MiB)
Although one of the first 32-bit processors the 68000 would become one of the main players in the 16-bit era of microcomputers with computers like the Apple Macintosh, Atari ST and Commodore Amiga.
1982 – MOS Technology 6510
8-bit registers and data bus, 16-bit address bus (64 kiB)
A modified version of the 6502 with I/O pins. The 6510 was used primarily in the extremely successful Commodore 64
1984 – Motorola 68020
32-bit registers, data bus and address bus (4 GiB)
A fully 32-bit version of the 68000 which found usage in revisions to the Apple Macintosh and Commodore Amiga lines.
1985 – Intel 80386
32-bit registers, data bus and address bus (4 GiB)
The first 32-bit implementation of the Intel x86 architecture that would become the mainstay of the PC world.