{"id":2885,"date":"2026-11-05T03:04:35","date_gmt":"2026-11-05T03:04:35","guid":{"rendered":"https:\/\/www.kernelcrash.com\/blog\/?p=2885"},"modified":"2026-11-05T03:04:35","modified_gmt":"2026-11-05T03:04:35","slug":"ai-and-retro-projects","status":"publish","type":"post","link":"https:\/\/www.kernelcrash.com\/blog\/ai-and-retro-projects\/2026\/11\/05\/","title":{"rendered":"AI and Retro Projects"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Like the rest of the world I am tinkering with AI.  I spend a lot of time going &#8220;Can it do this &#8230;&#8221;.  When I first started playing with AI a few years ago, my general concensus was &#8220;Good at modern languages, but rubbish at older retro stuff&#8221;. For example, asking any AI to write 6502 or Z80 assembler was most likely going to leave you disappointed. But that&#8217;s all changed now.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">While I have my own &#8216;AI workstation&#8217; for running local models, I realise the &#8216;frontier models&#8217; from Anthropic and OpenAI are significantly better and to help me experiment more I ended up getting the cheapest Anthropic subscription to contain costs. So a lot of this article is all referring to claude code on Sonnet 5 primarily because that&#8217;s what I had and I didn&#8217;t want to spend more money on more subscriptions just to compare. I suspect that the offerings from openAI and others are probably just as good as what I discovered with Sonnet 5.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So essentially I set out to do a number of experiments to see how good Sonnet 5 is at writing retro stuff (but I also asked a lot of hardware design questions along the way too). The TL;DR is &#8220;its very good&#8221;. In terms of 8 bit assembly language it is very good at writing z80 and 6502 assembly ( I didn&#8217;t test with any others). It makes mistakes like a human does such as register clobbering, but you can ask it to try to recheck for that style of bug which improves but does not eliminate the issue. The code it produces works, but its not the type of code that would &#8216;impress your mates back in the 80s&#8217;. Its functional. I found there were times too where I knew that something could be optimised down substantially and it felt like I was spending more time convincing Sonnet 5, than getting it to write code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Anyway, one of my first experiments was to port the game &#8220;Planet Defender&#8221; to MSX. So Planet Defender is an 8KB cartridge game for the <a href=\"https:\/\/en.wikipedia.org\/wiki\/VTech_CreatiVision\">Funvision\/Wizzard\/Creativision<\/a> machines from the early 1980s. Its a really nice smooth scrolling defender clone. Given that the video chip has no hardware scroling, I always thought it was quite awesome. The Funvision had a 2MHZ 6502A, a TMS9929 (ie. 9918\/9928 etc) video chip and a 76489 sound chip. It had the usual 16KB of VRAM for the video chip and only 1KB of RAM for the CPU (which was not that uncommon in this era). So the video chip is the same as used by <a href=\"https:\/\/en.wikipedia.org\/wiki\/MSX\">MSX<\/a>, but MSX had a Z80A CPU and used a AY-3-8910 sound chip. So I used claude code for this and basically my CLAUDE.md just said &#8220;Port the Funvision game planet defender to MSX&#8221;. So a few key things happened as it ported it<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Claude wrote itself a 6502 disassembler in python <\/li>\n\n\n\n<li>It spent quite a bit of time reverse engineering the 8KB planet defender cartridge. I also gave claude a dump of the 2KB Funvision BIOS ROM. I didn&#8217;t tell it where any key subroutines are. It just figured it all out itself.<\/li>\n\n\n\n<li>Per normal Claude broke things down in to phases and implemented it all bit by bit.<\/li>\n\n\n\n<li>To test each phase it made sure I had openmsx installed. It knew how to build a simple MSX cartridge, run it with openmsx and then take a screen shot of the output, then look at the screenshot to see if it matched what it expected. I also had the funnymu Funvision emulator installed so it could &#8216;see&#8217; what the original game looked like as well.<\/li>\n\n\n\n<li>It did the video and game play stuff first and the last steps were related to sound and the game over screen.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve uploaded the experiment to <a href=\"https:\/\/github.com\/kernelcrash\/msx-planet-defender\">msx-planet-defender<\/a> . It is much the same as the original Planet Defender.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In another experiment I asked Claude to write a BASIC interpreter for MSX from scratch. This used CBIOS as the underlying BIOS so it wasn&#8217;t a complete &#8216;from scratch&#8217; ROM for MSX. Again, this was very impressive and I would just add commands as I went. Effectively I ended up with a Tiny BASIC that was not much compatible with real MSX BASIC, but it could actually load a few different games from cassette images as BLOAD games dont actually care about BASIC and the RUN &#8220;CAS:&#8221; type games generally only have less than 10 lines of BASIC then a BLOAD command at the end, so they only needed to understand a subset of BASIC to actually work. So the Tiny BASIC was only taking up about 5K, so I asked Claude to add in an entire Z80 Assembler inside the BASIC interpreter, and it did. The interesting part is that as it added in different groups of instructions to the assembler it would work out small BASIC test programs to run with openmsx, sort of automatically type them in slowly, run them and snapshot the screen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In another experiment I asked Claude to write a simple Breakout clone in Z80 Machine Code. But to write the assembly code and &#8216;hand assemble it&#8217;. So hand assembly is not something anybody does these days, but in the early 1980s when kids had one computer, a casssette interface and no assembler, your only option was to write Z80 assembly programs on a paper notebook and then look up the hex opcodes for each line, then type those hex codes in. Basically I was asking Claude to do the same and &#8216;skip running an assembler to assemble it&#8217; &#8230; and it did. If you look at what it did, it effectively wrote the Z80 Assembly instructions as comments on lines that just included the hex codes. Effectively it was assembling the instructions without an assembler.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I then ventured in to hardware design. I quite like the Z80 based systems that used the CPU to generate video. The ZX-80 and Galaksija did this. There are different ways to do this but it often involves the Z80 being forced to see NOPs on its databus so that it can &#8216;walk through video addresses&#8217; or to use the refresh cycles in M1 cycles to generate video addresses. Again, Claude knew all about this stuff. And my first idea sort of looked like this<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>12MHz pixel clock<\/li>\n\n\n\n<li>divide by 2 to get a 6MHz CPU clock<\/li>\n\n\n\n<li>Use counters and flipflops to divide the 12MHz down to 15625Hz and to generate a 5.3us Hsync pulse<\/li>\n\n\n\n<li>Fire an interrupt every HSYNC. Have logic so that the first memory operation after the interrupt has forced wait states to make the CPU line up to a specific spot on the horizontal scan line.<\/li>\n\n\n\n<li>Then some strange code that would load the I and R registers and sort of walk through a series of 4 T state instructions to &#8216;walk out a video line&#8217;. So R would auto increment every 4 T states and so that meant I could do a 512 pixel across 2 colour screen for PAL style sync frequencies. That means 64 increments of R across the screen which means that R does not wrap round mid line. So basically the refresh cycle becomes the video address generator. I just had a 74ls166 shift register clocked at 12MHz and effectively I could get 512 pixel (64 character) wide scanlines.<\/li>\n\n\n\n<li>So the CPU is tied up for 200 scanlines, and then its just servicing the HSYNC interrrupt for the 112 lines of blank. There&#8217;s program logic to generate a VSYNC pulse as well. <\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">So that all worked on some breadboards, and Claude helped a lot at fleshing this design out. It did get stuck in a few places. The way the Z80 only updates the bottom 7 bits of R got confusing for a while, but it eventually all worked with some nudging and testing. Then I decided to do a benchmark to work out just how much slower the Z80 is due to all the line generation and interrupts. Effectively its busy doing video generation for 200 out of 312 lines so its not going to be great. It turned out to be roughly like a 2MHz Z80 in terms of throughput which was worse than I expected.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With that Z80 design I had as a goal to run Zork 1 on CP\/M. So basically get CP\/M ported to it and then run CP\/M &#8230; but because it was going to be quite slow I abandoned it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I came up with another idea. Instead of getting the Z80 to self generate video, I had some Atmega1284p chips. They are 5V logic and have 32 GPIO pins. They have counters and timers and usarts and so on. I thought if I could wire that into the Z80 bus I could get it to generate the video address, hsync and vsync. It could just stall the Z80 via _BUSRQ for 40us out of every 64us scanline and hopefully that would be faster overall than the interrupt design I had before. And ultimately get it to run CP\/M and Zork 1. I&#8217;ll leave that all for the next post.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve tried lots of other experiments. Many of them to do with financial related stuff. Using AI I can ask quite complicated questions and get decent answers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So what does this all mean? I genuinely enjoy thinking up hardware and weird software ideas, and AI can sort of &#8216;do a lot of it anyway&#8217;. It sort of takes the fun out of it. You sort of lose that &#8216;beating your head against a wall for days or weeks and then having an aha moment&#8217;. Does that mean I want to avoid using AI? No, not really.  But I can empathise with those that are confronted by it. Generally when you come across someone else&#8217;s software or hardware project you want to think its as a result of a person&#8217;s hard efforts, or a groups hard efforts. So it feels less authentic if its partially done by AI. But the flipside is that I can fast track a lot of ideas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For the Z80 CP\/M project I&#8217;ve effectively used it to &#8216;flesh out the software quickly&#8217;. So for that project I&#8217;m more interested in the hardware side, but I am able to relatively quickly build code to drive characters on the screen, read the keyboard and far more complicated things like port CP\/M and bitbang SD card access. It accelerates getting to a &#8216;more interesting point&#8217; in the project. A huge downside is that I often don&#8217;t even look at the code it produces. So did I write the code or did Claude write the code?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Of course this is meant as an experiment so I&#8217;m interested in the places where AI hasn&#8217;t worked so well. Another project I am advancing is effectively a respin of my msx-rom-emulator project, but instead of using a stm32f407, I use a rp2350b. This project has been very interesting so far as I originally just got it to &#8216;act as a simple 16KB cartridge emulator&#8217; using <a href=\"https:\/\/github.com\/niklasekstrom\/RPROM\">https:\/\/github.com\/niklasekstrom\/RPROM<\/a> as a &#8216;basis. Then I thought &#8220;It&#8217;d be cool if I could combine <a href=\"https:\/\/github.com\/kernelcrash\/AppleII-VGA\/tree\/tms9918a\">the tms9918a branch of my fork of the Apple II VGA <\/a>thing to get a VGA output at the same time the ROM is emulated. That was trivial for claude to port. This got rid of the 74LVC245 level shifters at the same time. Then Claude offered to implement read support for the tms9918. So the way this video emulation normally works is to only capture writes to the tms9918a. And any reads from it come from the real tms9918a on your MSX system circuit board. Because I was using my MSX breadboard computer to test all this, it was trivial to disable the real tms9918a &#8230; and so now I have an MSX breadboard system where I could actually remove the tms9918a and almost half the chips if I wanted to. The next part was to add the floppy controller emulation. This was much harder for Claude, and there were quite a few times where I just had to say &#8220;Stop, I will have a look at the code myself&#8221;. In these cases I would debug by making a series of educated guesses and eventually solve some issue. The style of programming my msx-rom-emulator is super time critical, so you have to be aware at all times about the time cost of what you&#8217;re trying to do. In some ways, Claude was very aware of this, but in others it made mistakes and you just see your 5hr limit blowing up in front of your eyes , so you say &#8216;STOP&#8217;. But we got there eventually. I guess this highlights a negative about tools like Claude. When its not doing the right thing I feel like I&#8217;m talking to a really egotistical junior programmer and I am wasting &#8216;my own brain tokens&#8217; trying to convince it to do something (and hence spending real tokens in the process). In a work context, having to deal with an egotistical junior programmer is probably normal, but for me this is a hobby, and its the last thing I want to do.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Like the rest of the world I am tinkering with AI. I spend a lot of time going &#8220;Can it do this &#8230;&#8221;. When I first started playing with AI a few years ago, my general concensus was &#8220;Good at modern languages, but rubbish at older retro stuff&#8221;. For example, asking any AI to write [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2885","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/posts\/2885","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/comments?post=2885"}],"version-history":[{"count":3,"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/posts\/2885\/revisions"}],"predecessor-version":[{"id":2923,"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/posts\/2885\/revisions\/2923"}],"wp:attachment":[{"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/media?parent=2885"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/categories?post=2885"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kernelcrash.com\/blog\/wp-json\/wp\/v2\/tags?post=2885"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}