I designed my own 8-bit computer just to play PONG

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so remember back to my last video where i said so remember back to my first video where i said that i was too cool for 3d engines or languages classes and garbage collection name spaces and things you don't really need and then i said yeah well i've thought some more about it since then and you know i've humbled a bit and decided i'm just too good for operating systems at this point too well since building my own operating system i've had even more time to consider and come to the conclusion that my own os simply isn't good enough the only way i will allow my code to run now is on the pinnacle of all creation my own creation a completely custom built computer now you might be asking what exactly does this mean are we going to hop on pc part picker and throw together an absolute beast of a pc with an amd ryzen 9 5900x a geforce rtx 380 ti 128 gigs of ram and a power supply that gets like 50 miles per gallon not quite we're gonna be going a little more old school no no even older school nope even older there we go the computer that i'll be designing is roughly equivalent to the computing power in this bad boy the pdp-8 straight out of 1965. oh yeah and it's going to run pong not any sort of important science they work or something that was done on a pdpa so it'll sort of kind of be this pdp-8 crossed with an intel 8008 crossed with an old-school pong machine crossed with whatever poor design decisions i make along the way so with all that out of the way let's get started the first step along any mini computer designer's journey is to determine the architecture of the machine basically defining how the whole thing works and in our case that means specking out this 1960s grade workhorse of a machine with a data width of 8 bits and a 16 bit address bus for an unbelievable maximum of 64 kilobytes of memory this also means we have to decide exactly what the computer needs to be able to do or the instruction set now this isn't going to be anything like your old 386 you have out collecting dust in the garage nah we don't have time for such a complex architecture for the jdh8 we're rolling with only 16 unique instructions a few to move data around in registers in memory those being the load word store word and move word instructions a couple for device communication inbite or nb and outbyte or outb then we have our two standard stack manipulation operations push and pop and the rest for arithmetic operations including add add with carry bitwise and or and nor compare and subtract with borrow the final two were this special load address or lda instruction which takes two bytes into the hnl registers and finally the all important jump if not zero or jnz instruction that makes this baby turn complete [Music] we've also got eight whole general purpose 8-bit registers to play with that store temporary data for the computer including the f register for arithmetic blacks the h l registers for an indirect 16 bit memory address and then a b c dnz for the rest of our data next up we've got the memory layout so from hex 0 to hex ffff or the end of our 64k of address space we have 16 kilobytes of read-only memory or rom from hex zero to hex eight thousand eight kilobytes of banked memory which can be swapped in and out by the memory bank register this is kind of an old-school treat that lets us access more than 64 kilobytes of memory then eight kilobytes of general purpose dedicated ram this is just your standard stuff read write nothing special and at the top of said ram we have three important memory mapped 16 bit registers the memory bank or mb register which tracks occur in memory bank the stack pointer or sp register which tracks the current stack location and the program counter or pc register which tracks the location of the current instruction and can be modified by the jump if not zero instruction also specified here in the design dock is to have the status register mapped as a device which contains information about the current state of the computer like whether it's on and or halted you can also see me right a lot about interrupts in the design dock here but little did i know at this point that i would later scrap the idea because interrupt just made things too complicated anyway though that's the whole thing now you might be thinking that this computer can't actually do a lot with just those 16 instructions and that would be correct but we could start combining more of these basic operations into larger operations to express all of the computational logic we could want at least as well as any old intel processor and as part of this combining you can see me here writing some macros basically letting us later on express some of these complex operations as one instruction instead of a series of instructions but anyways once the design dock is in order and we have some of the basic macros down the first piece of software to really write is the emulator basically one big simulator for this custom computer oh and of course it's gonna be written in our old friend mr c here and this is actually where the architecture really shines if a computer can only do 16 things well it's kind of easy to just slap all of those operations in a switch statement wrap that in some kind of infinite loop and let the emulator run free now normally in my videos i would put a demo in here but what do we really have to demo there's no software written for this thing to emulate as this is a totally custom computer any software that runs on this architecture has to be written totally from scratch including the software that takes our software to make it into software that can run on our custom hardware this is also known as an assembler and it's the next thing we need to build see to test start our emulator i could just hand compile some assembly code into hexadecimal poke it into memory point the emulator to it and tell it to run but this process doesn't really scale especially if we want pong running on this thing eventually so time to write the assembler now i've never actually written an assembler before so i was kind of at a loss for where to start but there's one thing i know about how compilers work which are generally much more complicated than assemblers but based on the same principles first you take your code then you do some lexical analysis then you parse it then you generate code so the first step here is to write a lexer which takes our assembly code tokenizes it and converts it to a non-string representation now most programming forms would probably tell you if you asked hey how do i write a lexer that this lexington is a solved problem and you should probably use a lexical analyzer generator not cool in my book though we are rolling our own so here you can see the first parts of the lex are going down and i also rapidly came to regret this decision turns out if it's been a while since you've done a lot of string manipulation and c you tend to make dumb mistakes quite often sometimes once it costs you a few seconds and sometimes a few hours but anyway once the elixir was spitting out the right tokens i could move on to parsing or understanding the semantics of the code normally a compiler would have a fancy recursive descent parser also done by a parser generator but again i was rolling my own and thankfully we don't need anything too complicated basically all the parser needs to do here is read directives like define org include and data directives keep track of labels and expand macros oh and i also got to solve the classic programming homework problem of implementing a calculator in here basically in the assembler anything you throw between two parentheses gets treated like a mathematical operation and calculated out as such one caveat though i was a little too lazy to implement any operator precedence so programmer beware these two expressions mean very different things on the assembler and remember those macros that i wrote a few minutes ago in the design dock no way we were gonna get far writing any software without those so the next test up was to work in support for those in the assembler macro is basically defined by its label its arguments which are prefixed by this percent sign and that can be a register an immediate an address or a register or immediate and then it basically just contains all of this macro text which is what gets pasted into where the macro is invoked so getting these into the assembler means basically just taking the macro definition pasting in the arguments and then pasting that into the final assembly code this way even though our program can contain more complex operations and macros everything ends up as those 16 simple instructions in the end after the bulk of the work here was done conveniently ignoring testing and bug fixing along the way it was time to get all of the 16 possible operations in there and write the code that actually takes the final macro expanded assembly code and generates the binary data that gets loaded into the computer and executed this just follows along with the instruction encoding defined in the design dock and is pretty straightforward so once those operations were in there it was finally time to test now i'm not usually one for tests if you can tell by the complete lack there of my previous projects but the complexity of this project kind of warranted some testing i think so i threw together a quick program that will take a set of assembly programs assemble them run the output of the assembler through the emulator and then go check to make sure that the output is correct this way we have full end-to-end testing of both the emulator and the assembler at the same time so i went through wrote some tests found some bugs fixed some bugs wrote some more tests found some more bugs picked some more bugs you get how it goes standard software developer things here really after not too long though i had a beautiful passing test suite for both the assembler and the emulator oh and it was also around here that i dug deep into my brain pulled down my knowledge of vim script and wrote a quick syntax highlighting file for the custom assembly language much better on the eyes this way i think and with that we have our architecture our emulator our assembler and most importantly our syntax highlighting so what's next on our journey to computational independence is well there's only one thing we can do the circuit so hold on to your usb cables and get ready to watch hours go by in seconds don't jeez i know that was like a minute a video but god damn you guys are lucky you didn't see that stuff in real time like 20 plus hours of circuit building and the worst part the program i was using there logisim doesn't have a dark theme so by the end of these few days my eyes were practically melted out of my skull but anyway you can see in the background here the first version of the circuit i got working it's constructed entirely out of logic gates which do basic boolean logics such as and or nor etc it uses registers for storing temporary data buffs for managing the data and address buses and ram and rom chips for bulk data storage and yeah it definitely looks a little confusing but it is sectioned nicely off into a few easier to understand pieces that all perform a distinct function for the computer so for a quick little tour first we have the registers which are those 8 bit a b c d l h z and f values that i mentioned earlier the auxiliary registers like the program counter stack pointer and memory bank register yeah the circuitry here is a little messy since these registers are addressed through memory and don't behave like regular registers then we have the address logic up here to determine whether we should be addressing ram or rom and the ram and rom chips over here then the registers containing the current operation the computer is performing then the status register and the current i o port register and some messy circuitry which controls how many bytes to load for the current instruction over here on the right and over here we have the alu or arithmetic logic unit which does well as it says on the box all the arithmetic operations in the computer like adding subtracting bitwise operations then there's some more random logic kind of scattered throughout and finally the micro microcode which drives all the control lines for the computer this is really the brain of the machine the microcode is basically a smaller instruction set where each word or two bytes of microcode corresponds to having some of these control lines lower high for the computer and the control lines control well everything which register to select whether or not to write to memory if the computer should load some value to or from the alu every part of the computer is connected with these control lines also finally yes electrical engineers i know logism is probably bad but i have literally zero formal education and digital electronics and really didn't want to learn how to use professional software let alone vhdl or some other unholy witchcraft language like that so please keep that in mind before you write a comment flaming me for using some outdated educational tool for this project anyway though i thought after this first build the circuit was a little messy so i went through and cleaned it up tested it out found some bugs picked some bugs then tested it out some more and rewired it one more time and gave it the final test the program here one of the test programs i wrote for the emulator and assembler computes the 8th fibonacci number 21 or 15 in hexadecimal so i'm just going to pop some virtual leds on the data bus here so we can get a good look into what's going on and if we see that number x15 pop up here in the d register and everything is working in this circuit and the computer is functional let's just let the clock run and perfect sweet i did use the magic of editing to skip over a lot of bug fixing here but let's just be happy it worked eventually and you didn't have to suffer through hours of watching me try to debug and rewire this thing because that wouldn't have made her a very interesting video so now finally to finish what we came here for and write some pong well actually first let's try to get a screen attached to this thing no point in running pong if you can't see it [Music] and well this is where i realized that using logisim was a bad idea the simulator kind of just can't keep up with driving this screen so to the emulator and how about one more montage for the road time to give this whole software suite a real run for its money and get it to run a real program so so after a couple more days of programming including countless bug fixes in the assembler emulator and circuit with a little over 700 lines of assembly code this is what we got pong written in a custom assembly language assembled by a custom assembler running on a custom processor well wait emulator ah man i've come all this way but what for a custom computer architecture yeah but dear god it still runs on the intel processor on my mac this isn't enough it's it's time to go fully off-grid let me just search a few things up here and get some of these circuits it's time to build this thing for real thanks for watching and come back next time to watch my descendant of madness as i physically assemble this thing in the next and hopefully final step on my journey to complete electronic independence
Info
Channel: jdh
Views: 241,115
Rating: 4.9796023 out of 5
Keywords: c++, programming, coding, gamedev, code, operating system, OS, assembly, CPU, circuit, 6502
Id: 7A1SzIIKMho
Channel Id: undefined
Length: 17min 18sec (1038 seconds)
Published: Sun Jun 13 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.