+---------------------------------------------+ | Nintendo Entertainment System Documentatie | | | | Versie: 2.00 | +---------------------------------------------+ +-------------------+ | Inhoudsopgave | +-------------------+ 0. Voorwoord A. Over de vertaler B. Over de vertaling 1. Inleiding A. Disclaimer B. Waarom? C. Doel D. Opgedragen aan... E. "Bedankjes" 2. Terminologie A. Intern B. Hardware 3. CPU A. Algemene Informatie B. Geheugen Map C. Interrupten D. NES-specifieke aanpassingen E. Toevoegingen 4. PPU A. Algemene Informatie B. PPU Map C. Name Tables D. Pattern Tables E. Attribute Tables F. Kleurenpalet G. Name Table Mirroring H. Palet Mirroring I. Achtergrond Scrollen J. Scherm en Sprites lagen K. Sprites en SPR-RAM L. Sprite #0 Hit Flag M. Horizontal and Vertical Blanking N. $2005/2006 Magie O. VRAM Lezen/Schrijven P. Toevoegingen 5. pAPU 6. Joypads, paddles, uitbereidingspoorten A. Algemene Informatie B. De Zapper C. Vier-speler apparaten D. Paddles E. Power Pad F. R.O.B. (Robot Operated Buddy) G. Signatures H. Uitbereidngspoorten I. Toevoegingen 7. Memory Mapping Hardware 8. Registers 9. Bestandsformaten A. iNES Formaat (.NES) 10. Programmeren met de NES A. Algemene Informatie B. CPU Notities C. PPU Notities 11. Emulatie A. Algemene Informatie B. CPU Notities C. PPU Notities D. APU Notities 12. Referenentie materiaal A. CPU Informatie B. PPU Informatie C. APU Informatie D. Memory Mapper Informatie E. Mailing Lijsten F. Internetsites G. Hardware Informatie +-----------------+ | 0. Voorwoord | +-----------------+ A. Over de vertaler ------------------- De vertaler van dit document heet Bram Bouwmans. Hij is een programmeur van BX software (www.bxsoftware.com) en heeft ook een NES emulator ontwikkeld. Voor meer informatie en vragen is hij te bereiken op bram@bxsoftware.com. Hij heeft dit document vertaald op verzoek van de webmaster van nesdev.parodius.com. B. Over de vertaling -------------------- In dit document heb ik, Bram Bouwmans, geprobeerd om zoveel mogelijk bij de originele tekst te blijven. Ik heb ervoor gekozen om een aantal termen on- vertaald te laten (zoals "mirroring"), omdat deze bij deze namen vaak worden genoemd in verwante documentatie. En om verwarring te voorkomen heb ik dus de engelse termen gehandhaaft. Tevens ga ik er in dit document vanuit dat de lezer een basiskennis van PC's heeft en bekend is met termen als 'sprites' en 'flags'. Mochten er nog aspecten zijn die niet duidelijk zijn, mail mij dan. Ik wilde tenslotte nog even kwijt, dat U dit document moet zijn als noodmiddel. Ik adviseer het engelse document, maar mocht U echt dit document wegens gebrekkige kennis van engels niet snappen, dan kunt U dit document erbij pakken. +-----------------+ | 1. Inleiding | +-----------------+ A. Disclaimer ------------- Ik ben op geen enkele manier verantwoordelijk voor de gevolgen van deze informatie. Deze informatie is "public-domain" and mag niet worden gebruikt voor commerciele doeleinden. Mocht U toch belsuiten om dit document te gebruiken voor commerciele doeleinden, dan dient U hierover met mij van te voren kontakt op te nemen, zodat ik met U over de opzet van het project kan discussieren. Ik wilde ook niemand financieel hinderen: als U software wilt gaan ontwikkelen voor de echte Nintendo Entertainment System, dan is het verstandig eerst kontakt op te nemen met ofwel Nintendo Amerika ofwel Nintendo Company Ltd. Hun adressen staan hieronder vermeld. Nintendo Amerika Nintendo Company, Ltd. P.O. Box 957 60 Fukuine Redmond, WA 98073 Kamitakamatsu-cho, USA Higashiyama-ku, Koyoto 602, Japan Alle titels van de cartridges en de console zijn geregistreerde handelsmerken van de respectievelijke eigenaars (ik vindt het echter niet nodig om hen allen een voor een op te noemen). B. Waarom --------- Toen dit document werd gemaakt was er slechts een document dat de interne onderdelen van de NES uitlegde: Marat Fayzullin's documentatie, ook wel bekend als "NES.DOC". Hoewel Fayzullin's documentatie op een aantal gebieden niet compleet was, leverde het toch een basis voor dit document en gaf het aan hoe complex de grijze doos van de NES eigenlijk was. Ik nam de mogelijk om "NES.DOC" uit te berijden, gebaseerd om andermans bevindingen evenals mijn eigen. Het begin van dit document lijkt veel op dat van Fayzullin's document, met kleinere en grotere aanpassingen. Marat Fayzullin begon zelf later naar dit document te referreren, nadat hij het had gelezen. Vergeet niet dat zonder Marat's "NES.DOC" zou ik nooit een aanleiding hebben gehad om dit document te schrijven. C. Doel ------- Het doel van dit document is simpel: precieze en up-to-date informatie geven over de Nintendo Entertainment System en zijn Japanse tegenhanger, de Famicom. D. Opgedragen aan... -------------------- Ik zou dit document graaf opdragen aan Alex Krasivsky. Alex was een goede vriend en was in mijn ogen de persoon die de bal van emulatie aan het rollen bracht. Tijdens de goede tijden en de slechte rijden, Alex was er altijd. Spasibo, Alex; umnyj Russki... E. "Bedankjes" -------------- Ik zou graag even de tijd willen nemen om alle mensen te bedanken die mij hebben geholpen om dit document tot stand te brengen. Zonder hun had ik dit document nooit kunnen schrijven. Alex Krasivsky - bcat@lapkin.rosprint.ru Andrew Davie Avatar Z - swahlen@nfinity.com Barubary - barubary@mailexcite.com Bluefoot - danmcc@injersey.com CiXeL Chi-Wen Yang - yangfanw@ms4.hinet.net Chris Hickman - typhoonz@parodius.com D - slf05@cc.usu.edu Dan Boris - dan.boris@coat.com David de Regt - akilla@earthlink.net Donald Moore - moore@futureone.com Fredrik Olsson - flubba@hem2.passagen.se Icer Addis - bldlust@maelstrom.net Jon Merkel - jpm5974@omega.uta.edu Kevin Horton - khorton@iquest.net Loopy - zxcvzxcv@netzero.net Marat Fayzullin - fms@cs.umd.edu Mark Knibbs - mark_k@iname.com Martin Nielsen - mnielsen@get2net.dk Matt Conte - itsbroke@classicgaming.com Matthew Richey - mr6v@andrew.cmu.edu Memblers - 5010.0951@tcon.net MiKael Iushin - acc@tulatelecom.ru Mike Perry - mj-perry@uiuc.edu Morgan Johansson - morgan.johansson@mbox301.swipnet.se Neill Corlett - corlett@elwha.nrrc.ncsu.edu Pat Mccomack - splat@primenet.com Patrik Alexandersson - patrikus@hem2.passagen.se Paul Robson - AutismUK@aol.com Ryan Auge - rauge@hay.net Stumble - stumble@alpha.pulsar.net Tennessee Carmel-Veilleux - veilleux@ameth.org Thomas Steen - Thomas.Steen@no.jotankers.com Tony Young - KBAAA@aol.com Vince Indriolo - indriolo@nm.picker.com \FireBug\ - lavos999@aol.com Speciale dank gaat uit naar Stumble, voor het leveren van informatie over IRC terwijl daardoor slaap te vermijden. +-----------------+ | 2. Terminologie | +-----------------+ A. Intern --------- CPU - Central Processing Unit: Verklaard zichzeld. De NES gebruikt een standaard 6502 (NMOS). PPU - Picture Processing Unit: Beheert de graphics, sprites en andere video-georienteerde aspecten. pAPU - pseuedo-Audio Processing Unit: Eigen aan de CPU; genereert geluidsgolven via vijf (5) geluidskanalen: vier (4) analoge, en een (1) digitale. Er is geen fysieke IC voor geluidsbewerking of geluidsgeneratie binnenin de NES. MMC - Multi-Memory Controller: Micro-controllers gebruikt in NES spel- letjes om extra geheugen te bereiken achter de 64Kb grens van de 6502 CPU. Ze kunnen ook worden gebruikt om extra CHR-ROM te bereiken en voor "speciale effecten" zoals een IRQ dwingen en andere dingen. VRAM - Video RAM: Dit RAM-geheugen is een deel van de PPU. Er is 16kb VRAM geinstalleerd in de NES. SPR-RAM - Sprite RAM: 256 bytes RAM-geheugen welke word gebruikt voor sprites. Het is niet echt een deel van de VRAM of ROM, ondanks dat het wel een intern deel is van de PPU. PRG-ROM - Program ROM: De echte programma-codes worden hier opgeslagen. PRG-RAM - Program RAM: Hetzelfde als PRG-ROM, maar dan RAM i.p.v. ROM. CHR-ROM - Character ROM: De VRAM gegevens welke in de PPU worden bewaard of in en uitgewisseld via de MMC's. VROM - Hetzelfde als CHR-ROM. SRAM - Save RAM: RAM dat word gebruikt in RPGs zoals "Crystalis", de Final Fantasy series, en "The Legend of Zelda." WRAM - Hetzelfde als SRAM. DMC - Delta Modulation Channel: Een kanaal van de APU dat de digitale data verwerkt. Meestal wordt hiernaar toe gerefeerd als het PCM (Pulse Code Modulation)-kanaal. EX-RAM - Expansion RAM: Dit is het geheugen dat wordt gebruikt in Nintendo's MMC5. Het staat spelletjes toe de mogelijkheden van het VRAM uit te bereiden. B. Hardware ----------- NES - Nintendo Entertainment System: Behoeft geen verdere uitleg. Dandy - Hetzelfde (hardware-gezien) als de Famicom. Famicom - Hetzelfde als de NES, behalve dat de RAW-methode van de DMC digitale audio playback niet wordt ondersteund. FDS - Famicom Disk System: Dit zit bovenop de Famicom, en het biedt de mogelijkheid om 3" double-sided floppy disks te gebruiken voor spelletjes. +--------+ | 3. CPU | +--------+ A. Algemene Informatie ---------------------- De NES gebruikt een aangepaste NMOS 6502 CPU, ontworpen en gemaakt door Ricoh. De voornaamste aanpassingen zijn het toevoegen van geluid. De NTSC NES draait op 1.7897725MHz, en 1.773447MHz voor een PAL-systeem. B. Geheugen Map --------------- +---------+---------+-------+-----------------------+ | Adres | Grootte | Flags | Omschrijving | +---------+---------+-------+-----------------------+ | $0000 | $800 | | RAM | | $0800 | $800 | M | RAM | | $1000 | $800 | M | RAM | | $1800 | $800 | M | RAM | | $2000 | 8 | | Registers | | $2008 | $1FF8 | R | Registers | | $4000 | $20 | | Registers | | $4020 | $1FDF | | Expansion ROM | | $6000 | $2000 | | SRAM | | $8000 | $4000 | | PRG-ROM | | $C000 | $4000 | | PRG-ROM | +---------+---------+-------+-----------------------+ Flag legenda: M = Mirror van $0000 R = Mirror van $2000-2008 iedere 8 bytes (d.w.z. $2008=$2000, $2018=$2000, etc.) C. Interrupten -------------- De 6502 heeft drie (3) interrupten: IRQ/BRK, NMI, en RESET. Ieder interrupt heeft een vector. Een vector is een 16 bits adres dat een locatie specificeerd waar de CPU naar "springt" als de interrupt wordt ge-triggered. IRQ/BRK kan op twee manieren worden ge-triggered: wanneer een software-matige IRQ wordt ge-triggered (BRK instructie van de CPU) of wanneer een hardware IRQ wordt uitgevoerd (via de IRQ lijn). RESET wordt ge-triggered wanneer de NES opstart. De ROM wordt in het geheugen geladen en de 6502 springt dan naar het adres gespecificeerd door de RESET- vector. Geen registers worden aangepast en het geheugen wordt niet gewist. Dit gebeurd alleen als de NES helemaal opnieuw wordt opgestart. NMI staat voor "Non-Maskable Interrupt", en wordt gegenereerd door een beeldschermverversing (VBlank), welke op verschillende intervallen gebeurd, afhankelijk van het systeem (PAL/NTSC). NMI wordt op een NTSC console 60 maal/sec ge-update en 50 maal/sec. op een PAL- console. "Interrupt latency" van de 6502 is zeven (7) cycles; Dit wil zeggen dat het zeven (7) cycles kost om in en uit het interrupt te komen. De meeste interrupten worden afgesloten met een RTI-instructie. Sommige NES- cartridges gebruiken een andere methode zoals quareSoft's "Final Fantasy 1". Deze cartirdge past de stack handmatig aan en doet dan een RTS. Dit is tech- nisch gezien mogelijk maar nutteloos. De eerder genoemde interrupten hebben de volgende vector adressen in het ROM: $FFFA = NMI $FFFC = RESET $FFFE = IRQ/BRK Interrupt prioriteiten zijn als volgt: Hoogst = RESET NMI Laagst = IRQ/BRK D. NES-specieke aanpassingen ---------------------------- De NES's 6502 heeft geen ondersteuning voor de decimale modus. Zowel de CLD als de SED opcodes werken wel, maar de bits die worden geset/ge- reset worden niet gebruikt. Toch is het gebruikelijk voor spelletjes om toch de opcode CLD te gebruiken omdat de status van het "d"-bit onbekend is op het moment dat de NES start of wordt ge-reset. Alles wat te maken heeft met geluid word intern bij de CPU gedaan. E. Toevoegingen --------------- Let op dat er twee aparte 16K PRG-ROM segmenten zijn; sommige spelletjes hebben slechts 1 16K segment welke moet worden geladen in ZOWEL $C000 en $8000. De meeste spellen laden zichzelf in $8000 en gebruiken 32K PRG-ROM (2 seg- menten van 16K dus). Deze methode is het eerst gebruikt door Super Mario Brothers. Hoewel alle spelletjes met meer dan een (1) 16K PRG-ROM segment zichzelf in $8000 laden, zijn er ook spelletjes die Memory Mappers gebruiken om PRG-ROM data in en uit te "swappen". Als een BRK opcode wordt ontdekt, dan "push"-t de NES's 6502 de CPU status flag op de stack met de "b"-bit op "1". Bij een IRQ of NMI gebeurt dit met de "b"- bit op "0". Dit is gedaan omdat de hardware-matige IRQ (IRQ) en de software- matige IRQ (BRK) dezelfde vector delen. Men kan nu bijvoorbeeld onderscheid maken m.b.v. de volgende code: C134: PLA ; Kopieer de CPU status flag C135: PHA ; Zet de status flag terug op de stack C136: AND #$10 ; Bekijk D4 ('b'-bit) C138: BNE is_BRK_opcode ; Als ie "1" is dan een software IRQ (BRK) De 6502 heeft een foutje in opcode $6C (jump absolute indirect). De CPU berekent niet correct het effectieve adres als de lagere byte $FF is. Voorbeeld: C100: 4F C1FF: 00 C200: 23 .. D000: 6C FF C1 - JMP ($C1FF) Normaal gesproken zou er gesprongen worden naar $2300. Maar doordat de hogere byte van het berekende adres niet wordt verhoogd bij een "page-wrap" zal de NES springen naar geheugenplek $4000. Let op dat "page wrapping" niet voorkomt in indexed- indirect addressing modes. Door de beperkingen van de zero-page, zouden alle indexed-indirect schrijf/lees- activiteiten moeten worden toegepast met een "AND $FF". Een voorbeeld: C000: LDX #3 ; Lees indirect adres van $0002+$0003, C002: LDA ($FF,X) ; Niet $0102+$0103. +--------+ | 4. PPU | +--------+ A. Algemene informatie ---------------------- "Mirroring" (ook wel bekend als "shadowing") is het proces van een bepaald adres of adres-regio doorsturen of "mappen" naar een ander adres/adres-regio. Een soort van spiegelen. B. Geheugen Map --------------- Hieronder staan twee (2) geheugen mappen. De eerste is een "RAM Memory Map," die wat algemener is, terwijl de tweede speciaal voor programmeurs is en daardoor dieper op de details van het geheugen ingaat. RAM Memory Map +---------+---------+--------------------+ | Adres | Grootte | Omschrijving | +---------+---------+--------------------+ | $0000 | $1000 | Pattern Table #0 | | $1000 | $1000 | Pattern Table #1 | | $2000 | $800 | Name Tables | | $3F00 | $20 | Kleurenpalet | +---------+---------+--------------------+ Programmeur Memory Map +-------+----------+-------+--------------------+ | Adres | Grootte | Flags | Omschrijving | +-------+----------+-------+--------------------+ | $0000 | $1000 | C | Pattern Table #0 | | $1000 | $1000 | C | Pattern Table #1 | | $2000 | $3C0 | | Name Table #0 | | $23C0 | $40 | N | Attribute Table #0 | | $2400 | $3C0 | N | Name Table #1 | | $27C0 | $40 | N | Attribute Table #1 | | $2800 | $3C0 | N | Name Table #2 | | $2BC0 | $40 | N | Attribute Table #2 | | $2C00 | $3C0 | N | Name Table #3 | | $2FC0 | $40 | N | Attribute Table #3 | | $3000 | $F00 | R | | | $3F00 | $10 | | Image Palette #1 | | $3F10 | $10 | | Sprite Palette #1 | | $3F20 | $E0 | P | | | $4000 | $C000 | F | | +-------+----------+-------+---------------------+ C = Mogelijk CHR-ROM N = Mirror (zie Subsectie G) P = Mirror (zie Subsectie H) R = Mirror van $2000-2EFF (VRAM) F = Mirror van $0000-3FFF (VRAM) C. Name Tables -------------- De NES toont graphics door het gebruik van een matrix van "tiles". Dit grid wordt een Name Table genoemd. In de grid / matrix kunnen de tile- nummers worden gevonden. De bijbehorenden tiles kunnen worden gevonden in de Pattern Tables. The gehele Name Table bestaat uit 32x30 tiles (= 256x240 pixels). Bedenk wel dat de werkelijk getoonde resolutie verschilt bij NTSC en PAL units. D. Pattern Tables ----------------- De Pattern Tables bevatten dus de werkelijke 8x8 tiles waarnaar de Name Table refereert. Ook bevat het de twee (2) lagere bits van het 4-bit kleurenpalet. Voorbeeld: VRAM Inhoud van de Kleur- Adr Pattern Table Resultaat ------ --------------- --------- $0000: %00010000 = $10 --+ ...1.... Punten staan voor .. %00000000 = $00 | ..2.2... kleur 0. Nummers .. %01000100 = $44 | .3...3.. staan voor het echte .. %00000000 = $00 +-- Lager Bit 0 2.....2. kleurnummer. .. %11111110 = $FE | 1111111. .. %00000000 = $00 | 2.....2. .. %10000010 = $82 | 3.....3. $0007: %00000000 = $00 --+ ........ $0008: %00000000 = $00 --+ .. %00101000 = $28 | .. %01000100 = $44 | .. %10000010 = $82 +-- Lager Bit 1 (van het kleurenpalet) .. %00000000 = $00 | .. %10000010 = $82 | .. %10000010 = $82 | $000F: %00000000 = $00 --+ E. Attribute Tables ------------------- Elke byte in een Attribute Table representeert een 4x4 groep "tiles" op het scherm. De Attribute Table bevat de twee (2) hogere bits van het kleurennummer (lagere twee (2) kunnen worden gevonden in de Pattern Table). It's quite confusing; two graphical diagrams may help: +------------+------------+ | Vierk. 0 | Vierk. 1 | #0-F zijn 8x8 tiles | #0 #1 | #4 #5 | | #2 #3 | #6 #7 | Vierkant nr. X zijn vier (4) 8x8 tiles +------------+------------+ (d.w.z. een 16x16 pixel grid) | Vierk. 2 | Vierk. 3 | | #8 #9 | #C #D | | #A #B | #E #F | +------------+------------+ Dit is hoe de twee (2) hogere bits worden opgeslagen (m.b.t. het boven- staande voorbeekd): Attribute Byte (Vierk. #) ---------------- 33221100 ||||||+- Hogere twee (2) kleurenbits voor Vierk. 1 (tiles 0,1,2,3) ||||+--- Hogere twee (2) kleurenbits voor Vierk. 2 (tiles 4,5,6,7) ||+----- Hogere twee (2) kleurenbits voor Vierk. 3 (tiles 8,9,A,B) +------- Hogere twee (2) kleurenbits voor Vierk. 4 (tiles C,D,E,F) F. Kleurenpalet --------------- De NES heeft twee (2) 16-kleuren paletten. een "Image Palette" en een "Sprite Palette". Deze paletten bevatten niet de echte RGB-waardes, maar zijn meer een opzoektabel. D7-D6 van bytes geschreven naar $3F00-3FFF wordt niks meer gedaan. G. Name Table Mirroring ----------------------- Men moet goed in de gaten houden dat er vele vormen van mirroring zijn in de NES. Sommige methodes gebruiken zelfs CHR-ROM-mapped Name Tables (mapper-specifiek). De NES heeft slecht 2048 ($800) bytes RAM in gebruik voor Name Tables. Maar zoals te zien in subsectie B, kan de NES vier (4) Name Tables hebben. Vele cartridges hebben standaard "Horizontaal" en "Verticaal" mirroring, zodat je kunt veranderen waar de Name Tables naar wijzen in de PPU Ram. Deze vorm van mirroring veranderd twee Name Tables teglijkertijd. Je kan ze niet afzonderlijk switchen. De volgende tabel, zou je moeten helpen in het begrijpen van alle types van mirroring op de NES. Let well op dat de adressen die getoont zijn (12 bits) referreren naar het Name Table-gedeelte van de NES' PPU Ram. Deze zijn hetzelfde als "$2xxx" in het VRam. Naam NT#0 NT#1 NT#2 NT#3 Flags +--------------------------+------+------+------+------+-------+ | Horizontaal | $000 | $000 | $400 | $400 | | | Verticaal | $000 | $400 | $000 | $400 | | | Vier-scherm | $000 | $400 | $800 | $C00 | F | | Enkel-scherm | | | | | S | | CHR-ROM mirroring | | | | | C | +--------------------------+------+------+------+------+-------+ F = Vier-scherm mirroring hangt af van een extra 2048 ($800) RAM (zit in de cartridge), resulterend in vier (4) fysieke onaf- hankelijke Name Tables. S = Enkel-scherm spelletjes hebben "mappers" welke je laten selecteren welk PPU Ram gedeelte je wilt gebruiken ($000, $400, $800 of $C00). All Name Tables verwijzen naar hetzelfde PPU Ram adres. C = Mapper #68 (Afterburner 2) laat je CHR-ROM mappen naar het Name Table gedeelte van de NES's PPU RAM-deel. Dit maakt Name Tables uiteraard ROM-gebaseerd en kan men er niet naar schrijven. Maar deze feature kan worden bestuurd via de mapper zelf, zodat je 't kan in- en uitschakelen. H. Palet Mirroring -------------------- Mirroring gebeurt tussen het "Image Palette" en het "Sprite Palette". Alle data geschreven naar $3F00 wordt ge-mirrored naar $3F10. Alle data geschreven naar $3F04 wordt ge-mirrored naar $3F14, etc. Kleur #0 in de bovenste drie (3) paletten van zowel de Image als de Spite palettes zijn de transparante kleur. De PPU gebruikt de waarde in $3F00 om de achtergrondkleur te definieren. Voor een uitgebreidere uitleg, moet je het volgende aannemen: * $0D is geschreven naar $3F00 (ge-mirrored naar $3F10) * $03 is geschreven naar $3F08 (ge-mirrored naar $3F18) * $1A is geschreven naar $3F18 * $3F08 is gelezen in de Accumulator De PPU gebruikt $0D als achtergrondkleur, ondanks dat $3F08 een waarde van $03 heeft (omdat kleur #0 transparant is wordt er niks getekent). Uiteindelijk heeft de accumulator een waarde van $1A, welke is ge- mirrored vanuit $3F18. Wederom, de waarde $1A is niet getekend omdat kleur #0 de transparantie is. De gehele "Image" en "Sprite Palettes" zijn beiden ook ge-mirrored naar andere delen van het VRam; $3F20-3FFF zijn mirrors van beide paletten. D7-D6 van de bytes geschreven naar $3F00-3FFF worden genegeerd. I. Achtergrond scrollen ----------------------- De NES kan de achterground (=voor-gerenderde Name Table + Pattern Table + Attribute Table) onafhankelijk van de bovenliggende sprites scrollen. De achtergrond kan zowel horizontaal als verticaal worden gescrolled. Scrollen werkt als volgt: Horizontaal Scrollen Verticaal Scrollen 0 512 +-----+-----+ +-----+ 0 | | | | | | A | B | | A | | | | | | +-----+-----+ +-----+ | | | B | | | +-----+ 480 Name Table "A" is gespecificieerd via Bits D1-D0 in register $2000, en "B" is de Name Table erna (door mirroring, is dit dynamisch). Dit werkt niet voor een spel waarin zowel Horizontaal als Verticaal scrollen aanstaat. De achtergrond bestrijkt meerdere Name Tables, zoals hieronder blijkt: +---------------+---------------+ | Name Table #2 | Name Table #3 | | ($2800) | ($2C00) | +---------------+---------------+ | Name Table #0 | Name Table #1 | | ($2000) | ($2400) | +---------------+---------------+ Schrijven naar de Horizontale Scroll waarde in $2005 gaat van 0 tot 256. Schrijven naar de Verticale Scroll waarde gaat van 0 tot 239; waardes boven de 239 worden beschouwd als negative (d.w.z. 248 = -8). J. Scherm en Sprite Lagen ----------------------------- Er is een bepaalde volgorde waarin de NES de graphics opbouwd: VOOR ACHTER +----+-----------+----+-----------+-----+ | KI | OBJs 0-63 | AG | OBJs 0-63 | EXT | +----+-----------+----+-----------+-----+ | SPR-RAM | | SPR-RAM | | BGPRI==0 | | BGPRI==1 | +-----------+ +-----------+ KI staats voor 'Kleur Intensiteit', welke synoniem is voor D7-D5 of $2001. AG is de achtergrond, en EXT is voor de EXTensie poort video signaal. 'BGPRI' staat voor de 'Background Priority' bit in de SPR-RAM, op een "per-sprite" basis (D5, Byte 2). Afhankelijk van of deze bit is ge-set, wordt een sprite voor of achter de achtergrond getekend. OBJ nummers representeren echte Sprite-nummers (lees subsectie K), niet Tile-nummers. VOOR is wat wordt gezien bovenop de rest (wordt als laatst getekend) en ACHTER is wat al onderste word gezien (als eerste getekend). K. Sprites en SPR-RAM ---------------------- De NES kan 64 sprites aan, welke of 8x8 of 8x16 pixels zijn in grootte. De data van de sprites is bewaard in de Pattern Tables. Sprite-attributen zoals "flipping" en "priority" zijn opgeslagen in SPR-RAM, welke een apart deel van 256 bytes is, onafhankelijk van ROM of VRam. Het formaat van de SPR-RAM is als volgt: +-----------+-----------+-----+------------+ | Sprite #0 | Sprite #1 | ... | Sprite #63 | +-+------+--+-----------+-----+------------+ | | +------+----------+--------------------------------------+ + Byte | Bits | Omschrijving | +------+----------+--------------------------------------+ | 0 | YYYYYYYY | Y Coordinaat - 1. Beschouw het coor- | | | | dinaat als de linkerbovenhoek van de | | | | sprite zelf. | | 1 | IIIIIIII | Tile nummer # | | 2 | vhp000cc | Attributen | | | | v = Verticale Flip (1=Flip) | | | | h = Horizontale Flip (1=Flip) | | | | p = Achtergrond Priority | | | | 0 = Voor achtergrond | | | | 1 = Achter achtergrond | | | | c = Bovenste 2 bits van de kleur | | 3 | XXXXXXXX | X Coordinaat | +------+----------+--------------------------------------+ Het Tile nummer # werkt net als bij de Name Table. Sprites van 8x16 pixels werken net even iets anders. Een 8x16 sprite met een even (2,4,6,8,etc.) Tile nummer gebruikt de Pattern Table op $0000 van de VRam. Daarentegen, 8x16 sprites met een oneven Tile Nummer gebruiken de Pattern Table van $1000. *LET OP*: Register $2000 heeft geen effect op 8x16 sprites. Alle 64 sprites hebben een interne "priority"; sprite #0 wordt later getekend dan sprite #1, etc. (tenzij bijv. #0 achter de achtergrond ligt, dan wordt #0 natuurlijk eerder getekend). Slecht acht (8) sprites kunnen worden getoond op een (1) scanline. Elke sprite wordt bekeken en als er meer dan 8 op een scanline liggen, dan was het bij de NES zo, dat alles ineens heel langzaam ging. (NOTE: Op de echte NES is het zo dat de sprites kunnen worden uitgezet (D4 van $2001 is dan "0"). Als dit lange tijd duurde, dan verviel de SPR-RAM, d.w.z. de elektrische stroompjes die de data moesten vasthouden werden steeds zwakker zodat data kwijtraakte). L. Sprite #0 Hit Flag --------------------- De PPU is in staat om te bekijken waar Sprite #0 is en zet zijn bevindingen in D6 van $2002. Het werkt op de volgende manier: De PPU zoekt naar de eerste niet-transparante "Sprite pixel" en de eerste niet-transparante "achtergrond pixel". Een "achtergrond pixel" is een tile in gebruik door de Name Table. Vergeet niet dat kleur #0 de transparantie definieert. De pixel die ervoor zorgt dat pixel D6 een "1" wordt, wordt getekend! Het volgende voorbeeld kan helpen. Hieronder zijn twee tiles. De transparente kleuren (kleur #0) zijn voorgesteld als een "_". Een sterretje ("*") geeft aan dat D6 naar "1" wordt gezet. Sprite Achtergrond Resulaat ------ ----------- -------- __1111__ ________ __1111__ _111111_ _______2 _1111112 11222211 ______21 11222211 112__211 + _____211 = 112__*11 '*' zal worden getekend als kleur #2 112__211 ____2111 112_2211 11222211 ___21111 11222211 _111111_ __211111 _1111111 __1111__ _2111111 _2111111 Dit geldt ook voor sprites die ACHTER de achtergrond zijn (via het 'Background Priority' SPR-RAM bit), hoewel het bovenstaande voorbeeld "achtergrond+sprite" is) D6 wordt weer naar "0" gezet na een VBlank. M. Horizontal en Vertical Blanking ----------------------------------- De NES, net als elk console, heeft een verversing; het beeldapparaat ( meestal televisie) zet het elektronenpistool weer terug naar linksbovenin. Een verversing (meestal aangeduid als 'refresh') gebeurd 60 maal per seconde display device is a television set. The refresh occurs 60 times a op een NTSC apparaat en 50 op een PAL apparaat. Het pistool tekent de pixels van links naar rechts. Dit resulteert in een (1) horizontale scanline. Na een scanline keert het pistool terug naar links en staat klaar om de volgende scanline te tekenen. Dit proces (terugkeren van het pistool) wordt beschreven als een Horizontal Blank periode (HBlank). Als het pistool alle scanlines heeft getekend, moet het terug naar de begin- positie bovenaan het beeld. Dit wordt de Vertical Blank periode genoemd, ofwel de VBlank. Zoals je in het onderstaande diagram kunt zien, werkt het pistool min of meer in een zigzag patroon totdat de VBlank plaatsvindt en het proces zichzelf herhaalt. +-----------+ +--->|***********| <-- Scanline 0 | | ___---~~~ | <-- HBlank V |***********| <-- Scanline 1 B | ___---~~~ | <-- HBlank l | ... | ... a | ... | ... n |***********| <-- Scanline 239 k +-----+-----+ | | +--VBlank--+ Een NTSC NES heeft de volgende refresh en schermindeling: +--------+ 0 ----+ | | | | | | | Scherm | +-- (0-239) 256x240 op-scherm resultaat | | | | | | +--------+ 240 --+ | ?? | +-- (240-242) Onbekend +--------+ 243 --+ | | | | VBlank | +-- (243-262) VBlank | | | +--------+ 262 --+ De VBlank flag zit in D7 van $2002. Het geeft aan of de PPU in de VBlank is. Een programma kan D7 terugzetten naar "0" door te lezen in $2002. N. $2005/2006 Magie ------------------- Voor gedetaileerde informatie over de $2005 en $2006 registers, zou je Loopy's $2005/2006 document moeten proberen. Deze geeft precieze informatie over hoe deze registers werken. O. PPU Quirks ------------- De eerste keer dat je van het VRAM leest is ongeldig. Hierdoor zal de NES een half-gebufferde waarde teruggeven van het VRAM inplaats van normaal lineair, zoals je zou verwachten. Zie het volgende voorbeeld: VRAM $2000 heeft $AA $BB $CC $DD. VRAM verhogingswaarde is 1. Het resultaat van de uitvoering staat in het commentaarveld. LDA #$20 STA $2006 LDA #$00 STA $2006 ; VRAM adres is nu $2000 LDA $2007 ; A=?? VRAM Buffer=$AA LDA $2007 ; A=$AA VRAM Buffer=$BB LDA $2007 ; A=$BB VRAM Buffer=$CC LDA #$20 STA $2006 LDA #$00 STA $2006 ; VRAM adres is nu $2000 LDA $2007 ; A=$CC VRAM Buffer=$AA LDA $2007 ; A=$AA VRAM Buffer=$BB Zoals hierboven zal de PPU's interne adres achteraf toenemenen nadat voor de eerste keer is gelezen. Dit geldt alleen voor VRAM van $0000-3EFF (d.w.z. Paletdata en hun mirrors hebben hier geen last van). P. Toevoegingen --------------- Het VRAM adres van de PPU zal automatisch met 1 of 32 (afhankelijk van D2 van $2000) toenemen na van $2007 te hebben gelezen. +---------+ | 5. pAPU | +---------+ Moet nog geschreven worden. Eerdere informatie was niet precies of incorrect. Niemand heeft 100% goede geluidsinformatie op dit moment. Deze sectie zal af worden gemaakt als iemand besluit om de pAPU van de NES achterwaards te engineren (uit elkaar halen) en informatie hierover openbaar te maken. +-------------------------------------------+ | 6. Joypads, paddles, uitbereidingspoorten | +-------------------------------------------+ A. Algemene Informatie ---------------------- De NES ondersteunt een aantal invoerapparaturen zoals joypads, Zappers (soort Pistolen), en vier-speler-apparaten. Joypad #1 en #2 kunnen worden bereikt via respectievelijk $4016 and $4017. De joypads worden ge-reset via door eerst een 1 en dan een 0 naar $4016 te schrijven. Zie subsectie H voor meer informatie. Als alles wordt ingedrukt, wordt alle informatie in een bit (D0) opgeslagen als een reeks informatie. Meerdere keren moet je hierdoor lezen om alle informatie over de controller te verkrijgen. 1 = A 9 = N.v.t. 17 = +--+ 2 = B 10 = N.v.t. 18 = +-- Handtekening 3 = SELECT 11 = N.v.t. 19 = | 4 = START 12 = N.v.t. 20 = +--+ 5 = OMHOOG 13 = N.v.t. 21 = 0 6 = OMLAAG 14 = N.v.t. 22 = 0 7 = LINKS 15 = N.v.t. 23 = 0 8 = RECHTS 16 = N.v.t. 24 = 0 Zie subsectie G voor meer informatie over Handtekeningen. B. De Zapper ------------- De Zapper (ook wel bekend als de "Light Gun") gebruikt bits in $4016 en $4017, beschreven in sectie 8. Zie bits D4, D3, en D0. Je kan twee Zappers hebben aangesloten op beide poorten tegelijk- tijd. C. Vier-speler apparaten ------------------------ Sommige NES spellen staan het gebruik van vier-speler apparaten toe, zodat je i.p.v. 2, 4 spelers kunt hebben. Een paar spellen die deze mogelijheid gebruiken zijn: Tengen's "Gauntlet II," en Nintendo's "RC Pro Am 2." Alle vier (4) controllers lezen hun status-bits van D0 van $4016 of $4017, zoals gezegd in subsectie A. Voor register $4016, leesacties #1-8 gaan over joypad #1, en #9-16 over joypad #3. Voor $4017, is het respectievelijk voor joypad #2 en #4. Hieronder een lijst van lees #'s en hun resultaten. 1 = A 9 = A 17 = +--+ 2 = B 10 = B 18 = +-- Handtekening 3 = SELECT 11 = SELECT 19 = | 4 = START 12 = START 20 = +--+ 5 = OMHOOG 13 = OMHOOG 21 = 0 6 = OMLAAG 14 = OMLAAG 22 = 0 7 = LINKS 15 = LINKS 23 = 0 8 = RECHTS 16 = RECHTS 24 = 0 Zie subsectie G voor informatie over Handtekeningen. D. Paddles ---------- Taito's "Arkanoid" gebruikte een "paddle" als controller. De paddle's positie wordt gelezen vanuit D1 van $4017; de data wordt omgekeerd (0=1, 1=0). De eerste gelezen waarde is de MSB, en de 8ste waarde (natuurlijk) de LSB. Geldige waardes gaan van 98 tot 242 waar 98 staat voor het compleet tegen-de-klok-in draaien van de paddle. Bijvoorbeeld, als %01101011 is gelezen, dan is de waarde ge-NOT, dus %10010100 hetgeen staat voor 146. The paddle also contains one button, which is read via D1 of $4016. A value of 1 specifies that the button is being pressed. E. Power Pad ------------ Geen informatie over bekend op het moment. F. R.O.B. (Robot Operated Buddy) -------------------------------- Geen informatie over bekend op het moment. G. Handtekeningen ----------------- Een handtekening laat de programmeur zien of een apparaat is aangesloten en zo ja, wat voor apparaat het dan is. Geldige waardes zijn: %0000 = Niet aangesloten %0001 = Joypad ($4016) %0010 = Joypad ($4017) H. Uitbereidingspoorten ----------------------- Als een joypad is een niet standaard volgorde gegevens wegschrijft, dan betekent dit dat de joypad niet langer meer het gebruikte control is, maar dat een uitbereidingspoort wordt gebruikt. Voor de NES gebruikers is de uitbereidingspoort aan de onderkant van de NES bevestigd en wordt bedekt door een klein stukje grijs plastic. Famicom gebruikers hebben deze poort aan de voorkant van hun console. Een voorbeeld van communiceren met een uitbereidingspoort is als volgt: LDA #%00000001 STA $4016 STA $4017 ; Begin te lezen van de uitbereidingspoort LDA #%00000011 ; Schrijf %110 naar de uitbereidingspoort STA $4016 Ik ben echter nog nooit een cartridge tegengekomen die deze methode van communicatie gebruikt. I. Toevoegingen --------------- Geen. +----------------------------+ | 7. Memory Mapping Hardware | +----------------------------+ Door het enorme aantal mappers (meer dan 64), is deze sectie, die wel aan- wezig was in v0.53 van dit document, verwijderd. Echter, alle data is niet verloren, omdat \FireBug\ van Vertigo 2099 een document heeft geschreven over vrijwel elke bestaande mapper. Je kunt een kopie verkrijgen via de volgende URL: http://free.prohosting.com/~nintendo/mappers.nfo Let op, ik neem geen verantwoording voor de informatie die in het genoemde document staat. Neem contact op met lavos999@aol.com voor meer informatie. +--------------+ | 8. Registers | +--------------+ Programmeurs communiceren met de PPU en de pAPU via de registers, welke niks anders zijn dat speciale geheugenlocaties die de programmeur veranderingen laten doorgeven aan de NES. Zonder registers zouden programma's niet werken. Elk register is een 16-bit adres. Legenda: R = Leesbaar W = Schrijfbaar 2 = 2x schrijven 16 = 16-bit register LET OP: 16-bit registers bestaan eigenlijk uit twee lineaire 8 bit registers welke onafhankelijk worden toegekend. De reden dat ze worden gespe- cificeerd als 16-bit is voor het gemak. Bijvoorbeeld, "$4002+$4003" zou betekenen dat D15-D8 in $4003 zouden zijn en D7-D0 in $4002. LET OP: Bits die niet zijn beschreven hebben geen speciale functie +---------+----------------------------------------------------------+ | Adres | Omschrijving | +---------+----------------------------------------------------------+ | $2000 | PPU Control Register #1 (W) | | | | | | D7: Voer de NMI uit als de VBlank plaatsvindt | | | 0 = Niet-actief | | | 1 = Actief | | | D5: Sprite grootte | | | 0 = 8x8 | | | 1 = 8x16 | | | D4: Achtergrond Pattern Table Adres | | | 0 = $0000 (VRAM) | | | 1 = $1000 (VRAM) | | | D3: Sprite Pattern Table Adres | | | 0 = $0000 (VRAM) | | | 1 = $1000 (VRAM) | | | D2: PPU Adres Toename | | | 0 = toename met 1 | | | 1 = toename met 32 | | | D1-D0: Name Table Adres | | | 00 = $2000 (VRAM) | | | 01 = $2400 (VRAM) | | | 10 = $2800 (VRAM) | | | 11 = $2C00 (VRAM) | +---------+----------------------------------------------------------+ | $2001 | PPU Control Register #2 (W) | | | | | | D7-D5: Achtergrondkleur (als D0 == 1) | | | 000 = Geen +------------+ | | | 001 = Groen | LET OP: Gebruik niet | | | 010 = Blauw | meer dan 1 type | | | 100 = Rood +------------+ | | | D7-D5: Kleurintensiviteit (als D0 == 0) | | | 000 = Geen +--+ | | | 001 = Groen intensiever | LET OP: Gebruik niet | | | 010 = Blauw intensiever | meer dan 1 type | | | 100 = Rood intensiever+--+ | | | D4: Sprites zichtbaarheid | | | 0 = Sprites worden niet getoond | | | 1 = Sprites worden getoond | | | D3: Achtergrond zichtbaarheid | | | 0 = Achtergrond wordt niet getoond | | | 1 = Achtergrond wordt getoond | | | D2: Sprite Clipping | | | 0 = Sprites onzichtbaar in de linker 8-pixelrij| | | 1 = Geen "clipping" | | | D1: Achtergrond Clipping | | | 0 = AG ontzichtbaar in de linker 8-pixel rijd | | | 1 = Geen "clipping" | | | D0: Beeldschermtype | | | 0 = Kleur | | | 1 = Zwart-Wit | +---------+----------------------------------------------------------+ | $2002 | PPU Status Register (R) | | | | | | D7: VBlank activiteit | | | 0 = Niet in de VBlank | | | 1 = Wel in de VBlank | | | D6: Sprite #0 Occurance | | | 0 = Sprite #0 is niet gevonden | | | 1 = PPU is Sprite #0 tegengekomen | | | D5: Scanline Sprite aantal | | | 0 = Acht (8) sprites of minder op de huidige | | | scanline | | | 1 = Meer dan 8 sprites op de huidige scanline | | | D4: VRAM Schrijf Flag | | | 0 = Schrijven naar VRAM word toegestaan | | | 1 = Schrijven naar VRAM word genegeerd | | | | | |LETOP: D7 wordt 0 als dit register wordt gelezen | | |LETOP: Nadat er hiernaar wordt geschreven wordt het | | | $2005 register ge-reset. | | |LETOP: Nadat er hiernaar wordt geschreven wordt het | | | $2006 register ge-reset. | | | | | | Voor meer informatie over D6, zie sectie 4, subsectie L. | +---------+----------------------------------------------------------+ | $2003 | SPR-RAM Adres Register (W) | | | | | | D7-D0: 8-bit adres in SPR-RAM om naar te schrijven via | | | $2004. | +---------+----------------------------------------------------------+ | $2004 | SPR-RAM I/O Register (W) | | | | | | D7-D0: 8-bit data wordt naar SPR-RAM geschreven. | +---------+----------------------------------------------------------+ | $2005 | VRAM Adres Register #1 (W2) | | | | | | Meestal gebruikt om het scherm te scrollen (afgezien vd | | | sprites). Dit register beheerst waar naar/van het VRAM | | | wordt gelezen of geschreven. | | | | | | Sectie 4, subsectie N voor meer informatie. | +---------+----------------------------------------------------------+ | $2006 | VRAM Adres Register #2 (W2) | | | | | | Meestal gebruikt om het 16-bit adres te specificeren | | | waarlangs het VRAM via register $2007 wordt bereikt. | | | | | | Sectie 4, subsectie N voor meer informatie. | +---------+----------------------------------------------------------+ | $2007 | VRAM I/O Register (RW) | | | | | | D7-D0: 8-bit data gelezen/geschreven van/naar het VRAM | +---------+----------------------------------------------------------+ | $4000 | pAPU Pulse #1 Control Register (W) | | $4001 | pAPU Pulse #1 Ramp Control Register (W) | | $4002 | pAPU Pulse #1 Fine Tune (FT) Register (W) | | $4003 | pAPU Pulse #1 Coarse Tune (CT) Register (W) | | $4004 | pAPU Pulse #2 Control Register (W) | | $4005 | pAPU Pulse #2 Ramp Control Register (W) | | $4006 | pAPU Pulse #2 Fine Tune Register (W) | | $4007 | pAPU Pulse #2 Coarse Tune Register (W) | | $4008 | pAPU Triangle Control Register #1 (W) | | $4009 | pAPU Triangle Control Register #2 (?) | | $400A | pAPU Triangle Frequency Register #1 (W) | | $400B | pAPU Triangle Frequency Register #2 (W) | | $400C | pAPU Noise Control Register #1 (W) | | $400D | Ongebruikt (???) | | $400E | pAPU Noise Frequency Register #1 (W) | | $400F | pAPU Noise Frequency Register #2 (W) | | $4010 | pAPU Delta Modulation Control Register (W) | | $4011 | pAPU Delta Modulation D/A Register (W) | | $4012 | pAPU Delta Modulation Address Register (W) | | $4013 | pAPU Delta Modulation Data Length Register (W) | +---------+----------------------------------------------------------+ | $4014 | Sprite DMA Register (W) | | | | | | Copieert 256 bytes van geheugen naar het SPR-RAM. Het | | | adres wordt gelezen van 100*N waar N de waarde is die | | | wordt geschreven. | +---------+----------------------------------------------------------+ | $4015 | pAPU Sound/Vertical Clock Signal Register (R) | | | | | | D6: Vertical Clock Signal IRQ beschikbaarheid | | | 0 = Een (1) frame is bezig, zodat de IRQ dus | | | niet kan gebeuren. | | | 1 = Een (1) frame wordt onderbroken via de IRQ | | | D4: Delta Modulation | | | D3: Noise | | | D2: Triangle | | | D1: Pulse #2 | | | D0: Pulse #1 | | | 0 = Niet in gebruik | | | 1 = In gebruik | | +----------------------------------------------------------+ | | pAPU Kanaal Control (W) | | | | | | D4: Delta Modulation | | | D3: Noise | | | D2: Triangle | | | D1: Pulse #2 | | | D0: Pulse #1 | | | 0 = Kanaal uitgeschakeld | | | 1 = Kanaal aangeschakeld | +---------+----------------------------------------------------------+ | $4016 | Joypad #1 (RW) | | | | | | LEZEN: | | | D4: Zapper trekker | | | 0 = Trekker wordt overgehaald | | | 1 = Trekker wordt losgelaten | | | D3: Zapper Sprite Detectie | | | 0 = Sprite is niet voor het richtkruis | | | 1 = Sprite is voor het richtkruis | | | D0: Joypad data | | +----------------------------------------------------------+ | | SCHRIJVEN: | | | Joypad Strobe (W) | | | | | | D0: Joypad Strobe | | | 0 = Leeg joypad strobe | | | 1 = Reset joypad strobe | | +----------------------------------------------------------+ | | SCHRIJVEN: | | | Uitbereidingspoort (W) | | | | | | D0: Uitbereidingspoort methode | | | 0 = Schrijven | | | 1 = Lezen | +---------+----------------------------------------------------------+ | $4017 | Joypad #2/SOFTCLK (RW) | | | | | | LEZEN: | | | D7: Verticaal Clock Signaal (Extern) | | | 0 = Is nu niet bezig | | | 1 = Is nu bezig | | | D6: Verticaal Clock Signaal (Intern) | | | 0 = Is nu bezig (D6 van $4016 beinvloed) | | | 1 = Is niet bezig(D6 van $4016 onbeinvloed) | | | D4: Zapper Trekker | | | 0 = Trekker wordt overgehaald | | | 1 = Losgelaten (niet vastgehouden) | | | D3: Zapper Sprite Detectie | | | 0 = Sprite niet voor het richtkruis | | | 1 = Sprite voor het richtkruis | | | D0: Joypad data | | +----------------------------------------------------------+ | | SCHRIJVEN: | | | Uitbereidingspoort (W) | | | | | | D0: Uitbereidingspoort Methode | | | 0 = Schrijven (???) | | | 1 = Lezen | +---------+----------------------------------------------------------+ +---------------------+ | 9. Bestandsformaten | +---------------------+ A. iNES Formaat (.NES) ---------------------- +--------+---------+------------------------------------------+ | Offset | Grootte |Content(s) | +--------+---------+------------------------------------------+ | 0 | 3 | 'NES' | | 3 | 1 | $1A | | 4 | 1 | aantal 16K PRG-ROM's | | 5 | 1 | aantal 8K CHR-ROM's | | 6 | 1 | ROM Control Byte #1 | | | | %####vTsM | | | | | ||||+- 0=Horizontale mirroring | | | | | |||| 1=Verticale mirroring | | | | | |||+-- 1=SRAM ingeschakeld | | | | | ||+--- 1=512-byte trainer aanwezig | | | | | |+---- 1=Vier-scherm mirroring | | | | | | | | | | +--+----- Mapper # (lagere 4-bits) | | 7 | 1 | ROM Control Byte #2 | | | | %####0000 | | | | | | | | | | +--+----- Mapper # (hogere 4-bits) | | 8-15 | 8 | $00 | | 16-.. | | De 16K PRG-ROM's (in lineaire volgorde). | | ... | | Als een trainer aanwezig is, dan komt | | ... | | deze eerst. | | ..-EOF | | CHR-ROM stukken (in oplopende volgorde) | +--------+---------+------------------------------------------+ +-----------------------------+ | 10. Programmeren met de NES | +-----------------------------+ A. Algemene informatie ---------------------- Geen. B. CPU Notities --------------- Geen. Zie sectie 11, subsectie B voor mogelijke informatie. C. PPU Notities --------------- Lezen en schrijven van/naar het VRAM gebeurt d.m.v. een aantal stappen: Schrijven naar VRAM Lezen vanuit VRAM ------------------- ----------------- 1) Wachten voor VBlank 1) Wachten voor VBlank 2) Schrijf hoger VRAM adres 2) Schrijf hoger VRAM adres byte in $2006 byte in $2006 3) Schrijf lager VRAM adres 3) Schrijf lager VRAM adres byte in $2006 byte in $2006 4) Schrijf data naar $2007 4) Lees $2007 (1x ongeldige data) 5) Lees data vanuit $2007 LETOP: Stap #4 bij het lezen van VRAM is alleen nodig als de gelezen VRAM data niet in de $3F00-3FFF waarden valt. LETOP: Toegang tot VRAM kan alleen plaatsvinden tijdens de VBlank. Anders krijg je rotzooi (meestal) te zien op het scherm. Zie sectie 4, sub- sectie N voor meer informatie. Wachten voor de VBlank is best simpel: 8000: LDA $2002 BPL $8000 Lezen vanuit $2002 zal ertoe leiden dat alle bits worden gelezen, maar D7 zal naar 0 worden gezet na het lezen. Het echte palet gebruikt door de NES wordt niet weergegeven in RGB waardes. Echter zijn vrijwel perfecte paletten te vinden in de betere emulators. Neem kontakt op met de desbetreffende auteurs voor dit palet in RGB kleuren. Zorg ervoor dat je het interne VRAM adres via $2006 redelijk vaak leeg maakt. Je zult vaak meemaken dat als het palet uit-"fade"-t of als het VRAM update, zal het scherm eruit zien als een zooitje (vierkantje op het scherm of andere "rare" dingen). De reden hiervan is dat je code langer duurde dan de VBlank. Als de VBlank het scherm gaat verversen met de data in de PPU dan neemt hij de interne waarde van het VRAM adres als startbasis voor Namt Table #0. De oplossing voor dit probleem is om het VRAM adres terug te zetten naar $0000 of $2000, zodat de verversing zoals normaal zal verlopen. De code hiervoor zou als volgt zijn: LDA #$00 STA $2006 STA $2006 Deze code is ook terug te vinden in behoorlijk wat commerciele spellen. +--------------+ | 11. Emulatie | +--------------+ A. Algemene informatie ---------------------- Als je een emulator gaat programmeren in C of C++, ben dan bekend met pointers. Dit zal je helpen op een aantal punten waneer het komt op mirroring en VRAM adressen. Voor de assembly-programmeurs, zijn pointers niets meer dan indirecte adressen. Het is makkelijker om een 32-bit waarde te veranderen, dan om 64K data uit te wisselen. Als SRAM ($6000-7FFF) is uitgeschakeld, word het schrijven naar dat gebied genegeerd. Lezen kan waardes opleveren die vooraf achter waren gelaten en daarom moet emulators de waarde 0 dan geven. RAM-gebaseerde geheugenplaatsen ($0000-07FF) moeten niet allemaal op "0" worden gezet op een RESET. Dit gebeurt alleen bij een POWER ON/OFF. Zie sectie 12, subsectie E voor Mailing List informatie. B. CPU Notities --------------- De NES gebruikt niet een 65c02 (CMOS) CPU zoals werd beweerd. Negeer foute opcodes. Sommige ROM's op het internet hebben foute opcodes (bijv. "Adventures of Lolo") doordat de cartridge tijdens het omzetproces (cartridge->PC) vies was of kapot. Er zijn 154 geldige opcodes (van de 256 in totaal) op de NES. C. PPU Notities --------------- De formule voor het berekenen van het basis adres van een Name Table's tilenummer is: (TILENUM * 16) + PATTERNTABLE Waar TILENUM het tile nummer in de Name Table is en PATTERNTABLE het Pattern Table adres gedefinieerd via register $2000. DOS programmeurs worden aanbevolen om Mode Q te gebruiken voor hun emulator. Mode Q heeft een goede resolutie, genoeg kleuren en is snel genoeg i.t.t. mode X. Meeste emulators limiteren het aantal sprites dat per scanline can worden getoond niet. In de echte NES zou bij meer dan 8 sprites een enorme vertraging optreden die gepaard gaat met "flikkeren" van het beeld. Emulators moeten niet gebruikte bits NIET negeren. Dit kan resulteren in het niet werken van een cartridge. D. APU Notities --------------- Moet nog worden geschreven. +--------------------------+ | 12. Referentie materiaal | +--------------------------+ A. CPU Informatie ----------------- Geen. B. PPU Informatie ----------------- Geen. C. APU Informatie ----------------- Geen. D. MMC Informatie ----------------- Geen. E. Mailing Lijsten ------------------ Er bestaan NES ontwikkelings Mailingslijsten. Neem contact op met Mark Knibbs voor meer informatie. De lijst is voor iedereen die wil praten/discusieren over tehnische aspecten van de NES. F. Internetsites ---------------- De volgenden zijn internetsutes, waar NES-georienteerde informatie kan worden gevonde. Als je fouten, slechte links of andere onvolkomenheden tegenkomt, neem dan kontakt op met de webmaster, en NIET MET ME. Bedankt. http://nesdev.parodius.com/ Heeft een goede hoeveelheid documentatie over allerlei NES-georienteerde onderwerpen, inclusief moeilijk-te-vinden mapper informatie. Het lijkt een goede site. http://www.ameth.org/~veilleux/NES_info.html Op dit moment alleen maar hardware-georienteerd materiaal zoals informatie over cartriges, the console zelf, mappers en MMC's. G. Hardware Informatie ---------------------- De volgende beveiligingsbits kunnen worden gekocht bij MCM Electronics (http://www.mcmelectronics.com/): Voor NES cartridges : 22-1145 (3.8mm beveiligingsbit) Voor NES consoles : 22-1150 (4.5mm beveiligingsbit) De 4.5mm beveiligingsschroef is ook gebruikt in de Super Nintendo en de Nintendo 64.