Jaffe Skrevet 10. juli 2012 Forfatter Del Skrevet 10. juli 2012 Se der ja, mente PHP og PLP. Bra at noen kan se gjennom det, er sikkert mye rusk her og der. Si i fra om det er noe som er uklart beskrevet osv. Lenke til kommentar
89erik Skrevet 13. juli 2012 Del Skrevet 13. juli 2012 Hei, nå sitter jeg litt fast igjen.. Kode Kompilert kode Jeg har satt PPUen til å generere et NMI ved hvert V-blank. Ved NMI-rutinen (linje 166-209) har jeg satt at den skal tegne to sprites på skjermen. Posisjonene henter den fra RAM. Hovedløkka til programmet (linje 66-146) går i en evig loop og oppdaterer posisjonene. Posisjonen til den første spriten forandrer seg hele tiden (en ball som spretter rundt på skjermen). Den andre spriten er kontrollert av brukeren og står stille hvis man ikke trykker på noe. Problemet er at med en gang jeg har mer enn én sprite på skjermen, begynner de å blinke veldig fort hele tiden. Merkelig nok blinker det ikke når jeg holder inne ned-pilen og flytter den andre spriten nedover. Men når jeg flytter den oppover vises ingen av spritene før jeg slipper knappen... Tror du problemet ligger i at oppdatering av posisjonene ikke skjer i interrupt-rutinen? Et annet antakeligvis relatert problem: Der jeg oppdaterer posisjonene venter jeg på V-blank først. (linje 66-68) Dette gir ikke helt mening i mitt hode da ingenting sendes til PPU her, kun i interrupt-rutinen som alltid skjer ved V-blank. Men hvis jeg ikke venter på V-blank vises ikke spritene i det hele tatt... Og 3 små btw hvis du har tid: Kan jeg få kontrollerne til å generere interrupts når man trykker ned en knapp? Er det vanlig/mulig å dele opp kildefilene, hhv. kode-segmentet spredt over flere filer? Tenker hovedsaklig på at det kanskje kan bli problematisk etterhvert å finne unike label-navn til hver minste lille ting. Jeg tar vare på registerverdiene når jeg går inn i interrupt-rutinen (burde kanskje hatt det på stacken istedet). Er dette nødvendig, eller gjør CPUen det for meg? Lenke til kommentar
Jaffe Skrevet 13. juli 2012 Forfatter Del Skrevet 13. juli 2012 Koden din fungerer hos meg (på emulatoren Nestopia, har ikke testet på NES-en min) etter at jeg la sprite-dataene i henholdsvis byte 8 - 11 og 12 - 15. i stedet for i de to første spritene. Jeg kan ikke her og nå komme med en forklaring på hvorfor i alle dager det skal utgjøre noen forskjell, men jeg vet at det er frarådet å skrive direkte til OAM/SPR-RAM med $2003 og $2004. Det man bør gjøre er å benytte DMA-kontrolleren i CPU-en. Da må du sette av én page i RAM til å lagre en kopi av OAM. I hovedloopen tar du så å skriver de nye koordinatene osv. til RAM i stedet. I NMI kan du da bytte ut hele remsen med skriving til $2003 og $2004 med LDA #0 STA $2003 ; sett OAM-pekeren til 0 LDA #$02 ; page 2 STA $4014 ; sett i gang DMA fra page 2 Dette vil kopiere hele pagen fra $0200 til $02FF over til OAM (og det skjer mye raskere enn vi kan gjøre med LDA- og STA-instruksjoner) Jeg har vært så frekk å endre koden din for å vise hvordan du kan gjøre endringene: http://pastebin.com/Qs7Jt3Ni Du er ikke nødt til å vente på vblank når du bruker NMI, men det du må gjøre er å lese fra $2002. Det resetter et internt vblank-flagg i PPU-en. Du bør også la hovedloopen (Sprite) vente på vblank, så den ikke kjører alt for fort. Det kan du enklest gjøre ved å lage deg en variabel som heter f.eks. vblank. Denne setter du til 0, og i NMI-rutinen setter du den til 1 (for å signalisere at vi er i vblank). I toppen av Sprite-loopen gjør du så følgende: Sprite: LDA vblank BEQ Sprite ; hvis 0, hopp opp igjen LDA #0 ; hvis vi har kommet her er vblank 1, sett den til 0 igjen STA vblank Til de tre spørsmålene dine: - Nei, du kan ikke få kontrollerne til å generere en interrupt når de trykkes. Du må sjekke input hver gang Sprite-loopen kjører. - Ja, det er en god idé. For å se hvordan kan du f.eks. se på kildekoden til Chip's Challenge. Her er "chip.asm" hovedfilen, og denne inkluderer alle de andre filene der det er nødvendig. Filene med .inc-endelse inneholder symboldefinisjoner osv. - Du må ta vare på registerverdiene selv, CPU-en tar ikke vare på noe som helst når den hopper til vanlige subrutiner. Når den hopper til interrupt-rutiner tar den bare vare på P-registeret. Det er dette stacken først og fremst er ment å brukes til. Etter hvert som du kanskje får bruk for å kalle subrutiner inne i andre subrutiner blir det ganske håpløst å holde styr på flere forskjellige midlertidige variable. Lenke til kommentar
Jaffe Skrevet 13. juli 2012 Forfatter Del Skrevet 13. juli 2012 Da var kapittelet (i alle fall en tidlig revisjon) om PPU-en ferdig Det neste kommer til å ta for seg noen enkle program/"spill" og kanskje noen lure algoritmer og triks. Lenke til kommentar
Jaffe Skrevet 19. juli 2012 Forfatter Del Skrevet 19. juli 2012 Har skrevet noen eksempler som tar for seg bl.a. sprites, input fra kontrollene og hvordan man lager en enkel bakgrunn (dvs. fylle nametable og attribute table med data). Hvert eksempel tas opp i en egen seksjon i guiden. Selve koden er å finne her. Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Vil prosessoren se at et tall er negativt hvis den henter det fra minnet? Jeg lagrer et tall i minne som kan være negativt i en subrutine og henter det senere. Kan jeg isåfall tvinge prosessoren til å se på det som et negativt tall dersom det er det? Det vil aldri være høyere enn $F0 (eller hva som var grensa). Har prøvd å ta vare på p-registeret, men det hjalp ikke. Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Og kan DMA brukes litt mer generelt enn kun til OAM? Jeg vil prøve å gjøre større endringer på bakgrunnen ved hver V-blank, og det tar litt vel lang tid å skrive én og én byte.. Lenke til kommentar
Jaffe Skrevet 20. juli 2012 Forfatter Del Skrevet 20. juli 2012 Vil prosessoren se at et tall er negativt hvis den henter det fra minnet? Jeg lagrer et tall i minne som kan være negativt i en subrutine og henter det senere. Kan jeg isåfall tvinge prosessoren til å se på det som et negativt tall dersom det er det? Det vil aldri være høyere enn $F0 (eller hva som var grensa). Har prøvd å ta vare på p-registeret, men det hjalp ikke. Prosessoren ser ikke på tallet som noe spesielt, det er koden vår som evt. må behandle tall der bit nr. 7 er satt som negative. Prosessoren tilrettelegger for dette ved å ha et flagg i P-registeret som kan fortelle oss om et tall er positivt eller negativt. Det kan være jeg misforsto spørsmålet. Hva er det koden din gjør? Lenke til kommentar
Jaffe Skrevet 20. juli 2012 Forfatter Del Skrevet 20. juli 2012 Og kan DMA brukes litt mer generelt enn kun til OAM? Jeg vil prøve å gjøre større endringer på bakgrunnen ved hver V-blank, og det tar litt vel lang tid å skrive én og én byte.. Kun OAM, dessverre. Det er relativt små forandringer som kan gjøres i bakgrunnen i hver vblank-periode. Man rekker typisk ikke mer enn å fylle inn rundt 64 tiles (to rekker eller to kolonner av name table). Hvor mye man rekker avhenger av hvor effektiv koden er, selvfølgelig. Hvilke forandringer er det du har lyst til å gjøre? Du kan jo slå av rendering i én frame og få gjort ganske mye på den tiden, men det vil jo merkes når spillet kjører. Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Vil prosessoren se at et tall er negativt hvis den henter det fra minnet? Jeg lagrer et tall i minne som kan være negativt i en subrutine og henter det senere. Kan jeg isåfall tvinge prosessoren til å se på det som et negativt tall dersom det er det? Det vil aldri være høyere enn $F0 (eller hva som var grensa). Har prøvd å ta vare på p-registeret, men det hjalp ikke. Prosessoren ser ikke på tallet som noe spesielt, det er koden vår som evt. må behandle tall der bit nr. 7 er satt som negative. Prosessoren tilrettelegger for dette ved å ha et flagg i P-registeret som kan fortelle oss om et tall er positivt eller negativt. Det kan være jeg misforsto spørsmålet. Hva er det koden din gjør? Jeg lagrer et negativt tall i minnet, f.eks. -1. Det lagres som $FF og P-registeret antyder at det er et negativt tall. Senere i koden hentes denne verdien til A-registeret og vil da være $FF, men P-registeret sier ikke lenger noe om dette tallet som ble lagret for lenge siden. Hvordan kan jeg få prosessoren til å tolke tallet som -1 i stedet for 255? Kan jeg endre på P-registeret selv? Lenke til kommentar
Pjassop Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Så rart å tenke seg at NES er som en datamaskin inni... Så gammel som den er tenker man liksom at den drives med grus og tannhjul eller noe slikt. Lenke til kommentar
Jaffe Skrevet 20. juli 2012 Forfatter Del Skrevet 20. juli 2012 Vil prosessoren se at et tall er negativt hvis den henter det fra minnet? Jeg lagrer et tall i minne som kan være negativt i en subrutine og henter det senere. Kan jeg isåfall tvinge prosessoren til å se på det som et negativt tall dersom det er det? Det vil aldri være høyere enn $F0 (eller hva som var grensa). Har prøvd å ta vare på p-registeret, men det hjalp ikke. Prosessoren ser ikke på tallet som noe spesielt, det er koden vår som evt. må behandle tall der bit nr. 7 er satt som negative. Prosessoren tilrettelegger for dette ved å ha et flagg i P-registeret som kan fortelle oss om et tall er positivt eller negativt. Det kan være jeg misforsto spørsmålet. Hva er det koden din gjør? Jeg lagrer et negativt tall i minnet, f.eks. -1. Det lagres som $FF og P-registeret antyder at det er et negativt tall. Senere i koden hentes denne verdien til A-registeret og vil da være $FF, men P-registeret sier ikke lenger noe om dette tallet som ble lagret for lenge siden. Hvordan kan jeg få prosessoren til å tolke tallet som -1 i stedet for 255? Kan jeg endre på P-registeret selv? Jeg tror kanskje du misforstår litt. Tallet $FF er 255, men vi kan velge å se på det som -1, siden $FF + 2 blir 1 og så videre. Det er vi som må tolke $FF som et negativt tall når vi skriver koden. Prosessoren skiller ikke mellom negative tall og positive tall når den f.eks. utfører addisjon eller subtraksjon. Den bruker ikke selv informasjonen i P-registeret til å behandle f.eks. negative tall annerledes enn positive tall. Flaggene er der for å gi oss informasjon om resultatet av den forrige instruksjonen. Når en instruksjon resulterer i et tall der den høyeste biten (bit 7) er 1, setter den N-flagget til 1 for å indikere at tallet er negativt (hvis vi bryr oss). Prosesoren bruker ikke selv N-flagget for å behandle noen tall som positive og noen tall som negative, så det har ingenting for seg å manuelt sette N-flagget til 1. Dette er sikkert litt komplisert. Jeg kan prøve å beskrive det litt bedre i guiden! Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Ah, ja jeg har misforstått. Jeg bruker vektorer for å flytte en ball rundt på skjermen. Når ballen går oppover eller mot venstre på skjermen er vektoren "negativ". Så hvis x-retning er -1 (255), og posisjon er 5, så blir neste posisjon 5 + (-1) => 5+255 som overflower og blir 4. Jeg trodde prosessoren brukte statusregisteret til å utføre negative addisjoner, men ser nå at det ikke ville vært nødvendig.. Jeg skulle bruke negative tall til noe annet, bare via minnet istedet, men ser nå at det ikke var det som var problemet. Jeg har valgt en annen løsning uansett så det ordna seg Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 (endret) Jeg skjønner absolutt ingenting av det her: Den siste linja i koden under gir range error (-689 not in [-128..127]). Jeg tok bort linjene som hadde med PLAYER2 å gjøre, og da forandra nummeret seg til -681. Hva betyr dette? LDA #1 STA PLAYER1 STA PLAYER2 LDA #0 STA PLAYER1 STA PLAYER2 LDA PLAYER1 ; A AND #1 BEQ Start Endret 20. juli 2012 av 89erik Lenke til kommentar
Jaffe Skrevet 20. juli 2012 Forfatter Del Skrevet 20. juli 2012 (endret) Det var rart. Hvordan er PLAYER1 og PLAYER2 definert? Jeg antar de representerer tallene $4016 og $4017? edit: Bra du forsto hvordan det hang sammen med negative tall. Jeg skal som sagt få gjort det litt klarere i guiden. Endret 20. juli 2012 av Jaffe Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Hvordan er PLAYER1 og PLAYER2 definert? Jeg antar de representerer tallene $4016 og $4017? Det stemmer Lenke til kommentar
Jaffe Skrevet 20. juli 2012 Forfatter Del Skrevet 20. juli 2012 (endret) Hvordan har du definert dem? Jeg pleier ofte å navngi diverse registre slik: PLAYER1 = $4016PLAYER2 = $4017 PPUDATA = $2007 ... Edit: Vent litt ,nå tror jeg kanskje jeg ser problemet. Klager den på BEQ-instruksjonen? Husk at argumentet til en slik betinget hoppeinstruksjon (branch) er en såkalt relativ adresse; et tall som sier hvor langt fremover eller bakover den skal hoppe. Dette tallet kan maks. bruke 8 bits, så det må være mellom -128 og 127. Her er det antagelig ganske stor avstand (681 bytes) mellom labelen Start og instruksjonen. Dette er jo ganske vesentlig, og er vel absolutt noe jeg også bør nevne i guiden Endret 20. juli 2012 av Jaffe Lenke til kommentar
Jaffe Skrevet 20. juli 2012 Forfatter Del Skrevet 20. juli 2012 Nå glemte jeg å si noe om løsningen på problemet. Det er å gjøre noe slikt: ... AND #1 BNE noe_mer JMP Start noe_mer: Dette fungerer fordi JMP tar en absolutt adresse som argument, og BNE-instruksjonen her bare vil få tallet 3 som argument (den etterfølgende instruksjonen JMP Start tar 3 bytes). Lenke til kommentar
89erik Skrevet 20. juli 2012 Del Skrevet 20. juli 2012 Aaaaaa! Endelig gir det mening Start-labelen var flere hundre linjer bak.. Takk! Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå