In dit artikel helpen we je op weg bij het programmeren van een CHIP-8-emulator. We leggen kort uit wat CHIP-8 is en hoe het is ontwikkeld, en geven aan wat je nodig hebt om ermee aan de slag te gaan zodat je zelf een start kunt maken in de wereld van emulators. Daarvoor is wel noodzakelijk dat je over programmeerkennis beschikt.
CHIP-8 is een geïnterpreteerde programmeertaal en virtuele machine die in de jaren 70 werd ontwikkeld door de onderzoeker Joseph Weisbecker. De taal werd geïntroduceerd om op een toegankelijke manier programma's en spellen voor de computer te kunnen maken. Waar voorheen machinetaal voor de specifiek gebruikte hardware nodig was, konden vanaf de introductie van CHIP-8 programma's en spellen voor meerdere systemen worden ontwikkeld, met behulp van relatief eenvoudige instructies. In eerste instantie werd er ondersteuning mee geboden voor de Cosmac VIP en Telmac 1800. Daarna volgde ondersteuning voor diverse andere systemen.
Vanaf de jaren 80 werden vernieuwde interpreters voor grafische rekenmachines uitgebracht. Dat begon met de CHIP-48 voor de grafische rekenmachine HP-48. Aan de hand hiervan werden afgeleide interpreters opgesteld, waaronder de SuperChip. Deze SuperChip maakte gebruik van een grotere instructieset en hogere resolutie, terwijl hij compatibel was met de originele CHIP-8-software.
CHIP-8 wordt tegenwoordig regelmatig gebruikt om de principes van een emulator uit te leggen. Door de relatief kleine instructieset en beperkte specificaties biedt de ontwikkeling van een CHIP-8-emulator in korte tijd de benodigde kennis om grotere emulators te ontwikkelen. Dit maakt CHIP-8 een goede opstap naar emulators voor geavanceerdere spelcomputers, waarbij aan producten van bijvoorbeeld Atari, Sega, Nintendo, PlayStation of Xbox kan worden gedacht.
De lange levensduur van CHIP-8 heeft er onder andere voor gezorgd dat een grote bibliotheek aan spellen (roms) online beschikbaar is. Dat zorgt voor voldoende materiaal om een zelfontwikkelde emulator te testen. Bovendien kan hierdoor snel de impressie van een zelfgebouwde spelcomputer worden bereikt.
IBM-logo in programma (rom) voor CHIP-8
Specificaties
Om een emulator te schrijven, is het van belang dat de details omtrent de hardware bekend zijn. In het geval van CHIP-8 is dit geen fysieke, maar virtuele hardware. Het principe blijft echter hetzelfde; in de software moeten zaken zoals registers, geheugen, display en keypad worden opgenomen, zodanig dat de hardware exact overeenkomt met het origineel. Als referentie is gebruikgemaakt van Cowgods Chip-8 Technical Reference. De specificaties voor de virtuele machine CHIP-8 zijn in dit hoofdstuk opgenomen.
Geheugen
Deze virtuele machine beschikt over 4.096 bytes aan werkgeheugen, vanaf adres 0x000 (0) tot 0xFFF (4096). Het geheugen is toegankelijk vanaf 0x200; de eerste 512 bytes worden in beslag genomen door relevante data voor de interpreter. Hieronder valt onder andere een karakterset. De volgende geheugenadressen zijn relevant:
Adres
Toepassing
0x000
Start interpreter-data
0x1FF
Einde interpreter-data
0x200
Start van programma
0xFFF
Einde van programma
Registers
De virtuele machine CHIP-8 beschikt over verschillende registers. Registergeheugen is geïntegreerd geheugen dat gebruikt wordt in een processor, om waarden op te slaan waar de processor direct toegang toe moet hebben om instructies te kunnen voltooien. De volgende registers zijn van toepassing:
Naam
Adres
Toepassing
Datatype
V
V[0] tot en met V[F]
Dataregister
Array (16 * 8-bit)
SS
SS[0] tot en met SS[F]
Stack Segment
Array (16 * 16-bit)
I
0
Indexregister
16-bit
DT
0
Delay Timer
8-bit
ST
0
Sound Timer
8-bit
PC
0
Program Counter
16-bit
SP
0
Stack Pointer
8-bit
Alle datatypes zijn unsigned; het zijn natuurlijke getallen die lopen vanaf 0 tot aan de grootte gerelateerd aan het aangegeven datatype.
Display
CHIP-8 maakt gebruikt van een monochroom display met een breedte van 64 pixels en een hoogte van 32 pixels. Daarbij is van belang dat de linkerbovenhoek de coördinaat (0,0) heeft en de rechteronderhoek de coördinaat (63,31). De hoeken van het display kunnen daarom op de volgende manier worden gerepresenteerd:
Display
Coördinaat links (x)
Coördinaat rechts (x)
Coördinaat boven (y)
(0,0)
(63,0)
Coördinaat onder (y)
(0,31)
(63,31)
Deze coördinaten zijn van belang voor de koppeling tussen de virtuele hardware en de programmatuur om de pixels weer te geven op een venster of display naar keuze.
Keypad
CHIP-8 biedt ondersteuning voor een hexadecimaal toetsenbord met zestien knoppen. De volgende indeling is van toepassing:
1
2
3
C
4
5
6
D
7
8
9
E
A
0
B
F
Karakterset
CHIP-8 beschikt standaard over zestien voorgeprogrammeerde tekens (0 tot en met F). Deze karakterset wordt gebruikt door verschillende programma's. Ieder karakter heeft een grootte van vijf bytes. De karakterset moet worden ingeladen op geheugenadres 0x000 tot en met 0x04F, wat gebaseerd is op het aantal karakters en de grootte per karakter (sprite).
De karakters worden getekend door per byte te definiëren welke bits aan- of uitstaan. De karakterset die geïmplementeerd moet worden, is hieronder zichtbaar:
De instructieset van een processor is een verzameling van alle mogelijke machinecodes die door die processor kunnen worden verwerkt. Voor een emulator is het essentieel dat de instructieset correct is opgenomen zodat programma's goed functioneren.
Uitlezen van de instructie
Iedere instructie heeft een omvang van 2 bytes. De bytevolgorde die hierbij van toepassing is, betreft Big-endian. Dit is een term die aangeeft dat de meest significante bit als eerste staat genoteerd, waarbij wordt afgeteld in significantie gerelateerd aan het aantal bits.
Meest significante byte (msb)
Minst significante byte (lsb)
Positie
Eerste byte van instructie
Tweede byte van instructie
Voorbeeld
0 0 0 0 0 0 0 0
1 1 1 0 1 1 1 0
Een correcte representatie van de instructie vereist een 16bit-datatype.
Instructie (16-bit)
0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 0
Operatiecode en operanden
Een instructie kan worden opgesplitst in twee delen. De operatiecode (opcode) geeft aan welke bewerking moet worden uitgevoerd, terwijl de operanden de invoerwaarden voor een instructie definiëren. Een operand kan data bevatten, maar ook een geheugenadres.
De operanden zijn relevant voor de uiteindelijke verwerking van de instructieset. De volgende operanden zijn van toepassing bij CHIP-8:
Naam
Instructie waarde
nnn
Minst significante 12 bits
n
Minst significante 4 bits (nibble)
x
Minst significante 4 bits van de meest significante 8 bits (byte)
y
Meest significante 4 bits van de minst significante 8 bits (byte)
kk
Minst significante 8 bits (byte)
Instructieset
De originele implementatie van CHIP-8 bevat 36 verschillende instructies. Hieronder vallen onder andere wiskundige operaties, keuzestructuren, grafische instructies en declaraties. Deze instructies zijn hieronder uiteengezet met de operatiecode en operanden, mnemonic, definitie en uitleg.
Operatiecode en operanden
Mnemonic
Definitie
Uitleg
00E0
CLS
Leegmaken van het display.
Alle bits van het display worden toegekend op de waarde '0'.
00EE
RET
Terugkeren van een subroutine.
De Program Counter ('PC') wordt naar het adres bovenaan het Stack Segment ('SS') gezet. De Stack Pointer ('SP') wordt verlaagd met 1.
1nnn
JP nnn
Spring naar locatie nnn.
De Program Counter ('PC') wordt gezet naar de operand 'nnn'.
2nnn
CALL nnn
Subroutine-aanroep op nnn.
De Stack Pointer ('SP') wordt verhoogd met 1. De huidige Program Counter ('PC') wordt op het Stack Segment ('SS') gezet.
3xkk
SE V[x], kk
Overslaan van de volgende instructie, indien V[x] gelijk is aan kk.
De waarde van het register 'V[x]' wordt vergeleken met de operand 'kk'. Indien ze overeenkomen, wordt de Program Counter ('PC') verhoogd met 2.
4xkk
SNE V[x], kk
Overslaan van de volgende instructie indien V[x] ongelijk is aan kk.
De waarde van het register 'V[x]' wordt vergeleken met de operand 'kk'. Indien ze niet overeenkomen, wordt de Program Counter ('PC') verhoogd met 2.
5xy0
SE V[x], V[y]
Overslaan van de volgende instructie indien V[x] gelijk is aan V[y].
De waarde van het register 'V[x]' wordt vergeleken met de waarde van het register 'V[y]'. Indien ze overeenkomen, wordt de Program Counter ('PC') verhoogd met 2.
6xkk
LD V[x], kk
Toekennen van V[x] = kk.
De waarde van de operand 'kk' wordt toegekend aan het register 'V[x]'.
7xkk
ADD V[x], kk
Toekennen van V[x] = V[x] + kk.
De waarde van de operand 'kk' wordt opgeteld bij de waarde van het register 'V[x]' en toegekend aan het register 'V[x]'.
8xy0
LD V[x], V[y]
Toekennen van V[x] = V[y].
De waarde van het register 'V[y]' wordt toegekend aan het register 'V[x]'.
8xy1
OR V[x], V[y]
Toekennen van V[x] = V[x] ∨ V[y].
De waarde van 'V[x] OR V[y]' wordt toegekend aan het register 'V[x]'.
8xy2
AND V[x], V[y]
Toekennen van V[x] = V[x] ∧ V[y].
De waarde van 'V[x] AND V[y]' wordt toegekend aan het register 'V[x]'.
8xy3
XOR V[x], V[y]
Toekennen van V[x] = V[x] ^ V[y].
De waarde van 'V[x] OR V[y]' wordt toegekend aan het register 'V[y]'.
8xy4
ADD V[x], V[y]
Toekennen van V[x] = V[x] + V[y]. V[F] = Carry.
De waarde van 'V[x] + V[y]' wordtbepaald. Indien het resultaat groter is dan '255', zal het register 'V[F]' op '1' worden gezet; anders op '0'. De minst significante byte van de optelling wordt toegekend aan het register 'V[F]'.
8xy5
SUB V[x], V[y]
Toekennen van V[x] = V[x] - V[y]. V[F] = ¬Borrow.
Indien de waarde van het register 'V[x]' groter is dan de waarde van het register 'V[y]', zal het register 'V[F]' op '1' worden gezet; anders op '0'. De waarde van'V[x] - V[y]' wordt toegekend aan het register 'V[x]'.
8xy6
SHR V[x]
Toekennen van V[x] = V[x] >> 1. V[F] = LSB == 1.
Indien de minst significante bit van het register 'V[x]' gelijk is aan '1', zal het register 'V[F]' op '1' worden gezet; anders op '0'. De waarde van 'V[x] / 2' wordt toegekend aan het register 'V[x]'.
8xy7
SUBN V[x], V[y]
Toekennen van V[x] = V[y] - V[x]. V[F] = ¬Borrow.
Indien de waarde van het register 'V[y]' groter is dan de waarde van het register 'V[x]', zal het register 'V[F]' op '1' worden gezet; anders op '0'. De waarde van 'V[y] - V[x]' wordt toegekend aan het register 'V[x]'.
8xyE
SHL V[x]
Toekennen van V[x] = V[x] << 1. V[F] = LSB == 1.
Indien de meest significante bit van het register 'V[x]' gelijk is aan '1', zal het register 'V[F]' op '1' worden gezet; anders op '0'. De waarde van 'V[x] * 2' wordt toegekend aan het register 'V[x]'.
9xy0
SNE V[x], V[y]
Overslaan van de volgende instructie indien V[x] ongelijk is aan V[y].
De waarde van het register 'V[x]' wordt vergeleken met de waarde van het register 'V[y]'. Indien deze niet overeenkomen, wordt de Program Counter ('PC') verhoogd met 2.
Annn
LD I, nnn
Toekennen van I = nnn.
De waarde van de operand 'nnn' wordt toegekend aan het register 'I'.
Bnnn
JP V[0], nnn
Spring naar locatie nnn + V[0].
De waarde van 'V[0]+nnn' wordt toegekend aan de Program Counter ('PC').
Cxkk
RND V[x], kk
Toekennen van V[x] = RND ∧ kk.
De interpreter genereert een willekeurig getal van 0 tot en met 255, genaamd 'RND'.
De waarde 'RND AND kk' wordt toegekend aan het register 'V[x]'.
Dxyn
DRW V[x], V[y], n
Weergeven van sprite op geheugenlocatie I op coördinaat (V[x], V[y]), V[F] = Overschreven vlag
De interpreter leest 'n' bytes uit het geheugen, beginnend bij het adres opgeslagen in register 'I'. Sprites worden middels de XOR-operatie weergegeven op het display. Indien pixels zijn verwijderd, zal het register 'V[F]' op '1' worden gezet; anders op '0'. Indien de x- en/of y-coördinaat van een pixel buiten het scherm valt, begint hij weer aan de andere kant.
Ex9E
SKP V[x]
Overslaan van de volgende instructie, indien V[x] gelijk is aan een ingedrukte toets.
Indien een knop van het hexadecimale keypad met de waarde uit het register 'V[x]' is ingedrukt, wordt de Program Counter ('PC') verhoogd met 2.
ExA1
SKNP V[x]
Overslaan van de volgende instructie indien V[x] ongelijk is aan een ingedrukte toets.
Indien geen knop van het hexadecimale keypad met de waarde uit het register 'V[x]' is ingedrukt, wordt de Program Counter ('PC') verhoogd met 2.
Fx07
LD V[x], DT
Toekennen van V[x] = DT.
De waarde van de delay timer ('DT') wordt toegekend aan het register 'V[x]'.
Fx0A
LD V[x], K
Toekennen van V[x] = toetsinvoer (blokkeert).
Er wordt gewacht op invoer van het toetsenbord (blokkeert). Bij invoer wordt de waarde toegekend aan het register 'V[x]'.
Fx15
LD DT, V[x]
Toekennen van DT = V[x].
De waarde van het register 'V[x]' wordt toegekend aan de Delay Timer ('DT').
Fx18
LD ST, V[x]
Toekennen van ST = V[x].
De waarde van het register 'V[x]' wordt toegekend aan de Sound Timer ('ST').
Fx1E
ADD I, V[x]
Toekennen van I = I + V[x].
De waarde van 'I + V[x]' wordt toegekend aan het register 'I'.
Fx29
LD F, V[x]
Toekennen van sprite-locatie voor V[x] aan I.
De hexadecimale sprite die correspondeert met de waarde van het register 'V[x]' wordt toegekend aan het register 'I'.
Fx33
LD B, V[x]
Toekennen van V[I], V[I+1] en V[I+2] als binair gecodeerde decimaal.
De honderdtallen van de waarde van het register 'V[x]' worden geplaatst in 'V[I]'. De tientallen van de waarde van het register 'V[x]' worden geplaatst in 'V[I+1]'. De eenheden van de waarde van het register 'V[x]' worden geplaatst in 'V[I+2]'.
Fx55
LD I, V[x]
Toekennen van V[i] aan geheugen Memory[I+i].
De waarden van de registers 'V[0]' tot en met 'V[x]' worden gekopieerd naar het geheugen 'Memory', beginnend bij operand 'I'.
Fx65
LD V[x], [I]
Toekennen van Memory[I+i] aan V[i].
De waarden van de registers 'Memory[I]' tot en met 'Memory[I+x]' worden gekopieerd naar het register 'V', beginnend bij 'V[0]'.
Programmeren
Voorafgaand aan dit artikel is een CHIP-8-emulator geschreven in C# in combinatie met het WPF-framework. De belangrijkste onderdelen van de code zullen in dit hoofdstuk worden toegelicht. De complete code kan worden gevonden op GitHub, onder CHIP-8-Manager. Het is ook mogelijk om alleen met het programma zelf te experimenteren. Het kan worden gedownload onder de gepubliceerde versies.
Je kunt ervoor kiezen om eerst zelf aan de slag te gaan met het schrijven van code, voordat je de voorbeelduitwerking in dit hoofdstuk raadpleegt.
Geheugen
CHIP-8 beschikt over 4KB, of 4.096 bytes, aan geheugen. Programma's (roms) worden in het geheugen geladen, zoals omschreven in het hoofdstuk Specificaties. Deze programma's bestaan uit verschillende instructies die door CHIP-8 moeten worden uitgevoerd. Aangezien iedere instructie over een lengte van twee bytes beschikt, is het handig om een functie te schrijven waarmee ze worden opgehaald uit het geheugen. Dat kan door bij het individueel uitlezen onderscheid te maken tussen de meest significante byte (msb) en minst significante byte (lsb). Deze twee bytes kunnen samen als returnwaarde worden opgenomen in een functie. Deze returnwaarde vereist een datatype van ten minste twee bytes (unsigned), anders kunnen niet alle bits worden opgenomen in het resultaat. Op basis van de index die als parameter wordt meegegeven, kan de betreffende instructie worden uitgelezen.
Registers
De verschillende registers zoals die zijn uiteengezet onder het hoofdstuk Specificaties kunnen worden ondergebracht in één klasse. De volgende registers kunnen worden ingevoerd:
Dataregister (V)
Indexregister (I)
Stack Segment (SS)
Delay Timer (DT)
Sound Timer (ST)
Program Counter (PC)
Stack Pointer (SP)
Binnen de referentie voor de instructieset komt met regelmaat het verlagen en verhogen van de Stack Pointer terug. Een alternatief om deze operatie veel terug te laten komen, is om een push en pop-functie te schrijven, waarbij de Stack Pointer eenmalig wordt verlaagd en verhoogd. Gelijktijdig kan in de functie een waarde op de stack worden bijgewerkt of worden geretourneerd.
Display
CHIP-8 maakt gebruikt van een monochroom display met een breedte van 64 pixels en een hoogte van 32 pixels. Daarbij is van belang dat voor de linkerbovenhoek de coördinaat (0,0) van toepassing is, terwijl voor de rechtsonderste hoek de coördinaat (63,31) geldt. Vanwege het monochrome display kan voor iedere x- en y-positie worden aangegeven of de pixel aan- of uitstaat. Er hoeft dus geen rekening te worden gehouden met verschillende kleuren op het scherm.
Binnen de displayklasse is een functie opgenomen voor het tekenen van een karakter (sprite). Als een sprite uit het scherm valt, dus wanneer de x- en/of y-coördinaat van een pixel buiten het bereik van die as valt, begint hij weer aan de andere kant.
Verder is er een aantal hulpfuncties toegevoegd die de aansturing vereenvoudigen. Zo is er een functie om het display te legen en om een specifieke pixel aan of uit te zetten.
Keypad
CHIP-8 biedt ondersteuning voor een hexadecimaal toetsenbord met zestien knoppen. Een voor de hand liggende implementatie is om op basis van de index te registreren of een toets wel of niet is ingedrukt. Middels een achterliggende implementatie voor een fysiek of virtueel toetsenbord, afhankelijk van het besturingssysteem en UI-framework, kan de betreffende toets worden geregistreerd als 'ingedrukt' of 'losgelaten'.
Veel emulatoren bieden de mogelijkheid van een virtueel toetsenbord dat zichtbaar is op het scherm, naast de mogelijkheid om fysieke toetsen te gebruiken. Deze fysieke toetsen komen in veel gevallen overeen met een afdeling op het toetsenbord. De indeling is qua vorm gelijk aan die van de inrichting van het keypad-design. Op die manier kan de besturing als intuïtiever worden ervaren dan met een letterlijke hexadecimale configuratie van 0 tot en met F.
Karakterset
De karakterset is overgenomen zoals omschreven bij de specificaties, met uitzondering van de extra letter 'K'. Deze letter is toegevoegd zodat 'OK' kan worden weergegeven in het standaard programma.
De letters zijn opgebouwd door te definiëren welke pixels (bits) aan- of uitstaan. Ieder karakter heeft een grootte van vijf bytes. Officieel zijn totaal zestien karakters gedefinieerd, maar het geheugen is groot genoeg om er nog extra toe te voegen.
Operatiecode en operanden
Zoals omschreven in het hoofdstuk 'Instructieset' zijn vijf operanden benodigd om de instructies uit te kunnen voeren. Deze vijf operanden kunnen bijvoorbeeld op deze manier worden geïnterpreteerd.
Instructieset
De klasse CoreData brengt de instructieset en essentiële data samen. Daaronder vallen het geheugen, register, toetsenbord en display. Deze klasse implementeert ook de instructieset en vormt de basis voor de emulator.
Koppeling
De volgende stap is het schrijven van code om het geheel aan te sturen. Daar komt ook een implementatie voor video, audio en toetsenbordinvoer bij kijken. Deze implementatie is afhankelijk van het besturingssysteem en kan worden vereenvoudigd door het gebruik van diverse softwarebibliotheken. De broncode kan worden bekeken om te zien hoe dit middels C# en het WPF-framework is gedaan.
Testen
Een lastig aspect bij het programmeren van een CHIP-8-emulator kan de verificatie zijn. In sommige gevallen zijn fouten niet direct zichtbaar. Door veel roms uit te proberen, kunnen fouten worden opgespoord. Bovendien zijn er testprogramma's beschikbaar die exact aangeven of instructies correct zijn geïmplementeerd.
Conclusie
De CHIP-8-emulator is gelimiteerd en de software vaak onpraktisch. CHIP-8 wordt dan ook vooral gebruikt voor entertainment en educatieve doeleinden.
Voor dat laatste is de software prima geschikt, want het creëren van een CHIP-8-emulator is een ideale manier om ervaring te krijgen met de werking van emulators. Daarnaast is het een geschikt project om te oefenen met bitwise-bewerkingen en het begrijpen van de basis van een computer. Het bouwen van een CHIP-8-emulator is dan ook een veelgebruikte eerste stap om vervolgens meer uitdagende projecten aan te pakken, zoals het programmeren van een emulator voor een spelcomputer.
In dit artikel hebben we een eerste start beschreven om met emulators aan de slag te gaan. Online is er veel materiaal te vinden waarvan je kunt leren en mee verder kunt experimenteren. Wellicht heb jij al een emulator geschreven of ga je daar in de toekomst mee aan de slag. Laat het ons en je medetweakers weten in de comments onder dit artikel.
Grappig om dit artikel te lezen. Zo'n 9 maanden geleden was ik op zoek naar een niet al te ingewikkeld project om mijn eerste emulator (in de awk scripttaal) te maken en kwam toevalligerwijs ook uit op CHIP-8
Als je iets van programmeren af weet, is het zeker goed te doen om je eerste emulator te schrijven. Voor de geïnteresseerden: https://github.com/patsie75/awk-chip8
Zeker! Een vriend van mij heeft ook een mooie geschreven een tijd geleden. Zie hier de github. Dat was het eerste wat bij me opkwam. Leuk om ook dit soort artikelen te lezen op tweakers!
Vi gebruiker hier. Ik heb vaak over awk gelezen maar weinig nog mee gedaan.
Ik vond het ook jammer dat het artikel naar Windows / C# verwees. Ben veel meer fan van Unix. De filosofie van de pipeline van simpele programma's zoals cut, grep, sed, awk etc. is geweldig en je kan er prima wiskunde en informatica mee duidelijk maken.
Wat ik nooit eerder begrepen heb is waarvoor de shift operatie was maar door MIT 6.006 (introduction to algorithms, open course ware, gratis) weet je bvb. dat shift voor binair delen en vermenigvuldigen wordt gebruikt. Dat maakt heap sorteren en binaire bomen zo efficiënt.
Weet ik maar Unix, shell, C & tools zijn toch wel de low level gereedschappen die toch veel langer worden gebruikt. Het zal wel aan de spelletjes natuur van het beestje liggen...
[Reactie gewijzigd door n0np3r50n op 22 juli 2024 15:40]
Aanrader in hetzelfde straatje. Het Nand2Tetris project. Hierbij bouw je zelf (virtueel) een computer door te beginnen met simpelweg de logische NAND poort. In een 12-tal projecten werk je jezelf omhoog van logische schakelingen in de basis, naar het bouwen van complexe schakelingen, chips en uiteindelijk een (turing-compleet) hardware platform.
Daarna bouw je ook de software-stack door een assembler, virtuele machine, compiler en OS te bouwen. Uiteindelijk kun je op je eigen gebouwde platform een game (zoals Tetris) programmeren. Mega-leerzaam en (met wat doorzettingsvermogen) best toegankelijk.
Een deel van het materiaal is gratis beschikbaar, voor de 2e helft moet je het boek aanschaffen. Online zijn verschillende cursussen te vinden die het boeltje ondersteunen met colleges/uitleg (via Udemy e.d.)
Ik geen informatica op de middelbare school en ik zet uitblinkers hier mee aan de slag
Hulde hiervoor! Het hoort niet bij je werk, maar ik denk wel dat je een leerling hiermee enorm helpt.
Mijn informaticadocent kwam niet verder dan: "Doe de het hele boek nog maar een keer afwerken", waarna ik toen maar een Re-Volt LAN server ging opzetten en anderen afhield van hun werk. Ik heb aan die middagen gamen wel goede herinneringen, maar was waarschijnlijk veel meer gebaat bij extra leerstof.
[Reactie gewijzigd door DaFeliX op 22 juli 2024 15:40]
Grappig om hier iets over CHIP-8 te lezen. Het is al een tijdje één van mijn hobbies, en je hoort er doorgaans niet zoveel over. Een paar aanvullingen en kleine waarschuwingen voor de geïnteresseerde:
Er zijn veel meer varianten van CHIP-8 geweest. En de CHIP-8 smaakjes uit de grafische-rekenmachine tijd zijn helaas niet 100% compatible met de originele versie, wat maakt dat veel programma's niet goed of helemaal niet draaien op een emulator die daar geen rekening mee houdt. Voor een overzicht van de verschillende versies en wat ze anders maakt, zie: https://chip-8.github.io/extensions/
Als je zelf een emulator aan het schrijven bent is een goede test inderdaad on-ontbeerlijk. Daarom heb ik een tijdje terug een uitgebreidere test geschreven, die je ook kan vertellen of je je goed aan de verschillen tussen versies houdt: https://github.com/Timendus/chip8-test-suite. Ik ben wel nieuwsgierig of de emulator van de schrijver door deze tests komt! 😉
Hoewel CHIP-8 een platform uit de jaren '70 is, vindt er jaarlijks in oktober (volgende maand!) een Gamejam plaats om programmaatjes voor het platform (of één van de varianten) te schrijven. Die jam heet Octojam, en alweer de negende editie begint dus binnenkort. Doe mee! https://itch.io/jam/octojam-9/
Als je vastloopt is het fijn om ergens terecht te kunnen met je vragen. Er is een CHIP-8 subreddit, maar die is niet zo actief. Je kunt beter terecht bij de EmuDev subreddit, of op de EmuDev Discord.
Suggestie / feature verzoek:
Eigenlijk merk ik dat ik heel veel artikelen wel leuk en interessant vind, maar ze graag óók als video zie.
Dat was ooit een enquete van Tweakers onder Plus-abbonees meen ik me te herinneren.
Stel dat tweakers letterlijk iemand het Plus-artikel laat voorlezen in een video, ondersteund met de plaatjes en tabellen uit het artikel.
Dat zou ik kijken.
Mag van mij zelfs zoals een iemand die "gewoon" zijn scherm deelt met Tweakers.net open (met bank-TV vriendelijke fontsize) terwijl hij als pop-in te zien is. Hoeft niet ingewikkelder.
Lees gewoon alles voor, of als het erg diep gaat en niet praktisch wordt zeg "dat stukje in het artikel gaat daar dieper op in" en vat het samen. Ik zou het graag kijken/horen terwijl ik in de keuken bezig ben of bij de TV zit..
[Reactie gewijzigd door Barryke op 22 juli 2024 15:40]
Zeker, in je eigen project is unit tests schrijven altijd een goed idee. Maar je wilt vaak ook graag jouw implementatie (en jouw begrip van de instructieset!) kunnen checken tegen de implementatie van anderen, zeker als je "alles goed hebt gedaan", maar Tetris toch niet goed werkt, zeg maar. Dat je net effe niet goed had geïnterpreteerd hoe die ene instructie het flags register beïnvloedt, ofzo.
En dan loop je tegen het probleem aan dat iedereen zo'n emulator in een andere taal programmeert, met een ander framework, voor een ander OS, et cetera. Dus unit tests van iemand anders copy-pasten zit er niet altijd in. Maar je kunt wel altijd een test draaien die zelf is geschreven in CHIP-8.
Zou je niet gewoon unit tests kunnen schrijven om de instructies te testen
Dat lijkt me inderdaad onontbeerlijk, zelfs voor iets simpels als de CHIP-8 instructie set.
Ik hobby zelf af en toe aan mijn eigen zelf gecreëerde fantasy console emulator, die meer lijkt op/geïnspireerd is door bestaande 16-bit consoles. Alleen al de logica voor branch instructies op basis van CPU flags is ingewikkeld genoeg dat je er echt niet zonder unit tests op wil vertrouwen dat je alles goed gedaan hebt