Scrolling going nuts for no reason

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderators: B00daW, Moderators

Post Reply
VGdevOnSNES
Posts: 8
Joined: Sat Apr 03, 2021 6:03 am

Scrolling going nuts for no reason

Post by VGdevOnSNES » Sun Apr 04, 2021 2:43 pm

Is it NMI? Sprite 0? Wrong instruction??? What the hell?

After trying things with PPU_CTRL, PPU_MASK, like disabling render or NMIs, i can't fix that problem.

When i change a character, the scrolling automaticaly focuses on it. But why?
I can't figure what causes that.

Here's the code:

Code: Select all

; Code
; $ = Héxadécimal
; # = Nombre 8-bits

; Registres

PPU_CTRL_REG1      = $2000
PPU_CTRL_REG2      = $2001
PPU_STATUS         = $2002
PPU_OAM_ADDRESS    = $2003
PPU_OAM_DATA       = $2004
PPU_SCROLL_REG     = $2005
PPU_ADDRESS        = $2006
PPU_DATA           = $2007

SND_REGISTER       = $4000
SND_SQUARE1_REG    = $4000
SND_SQUARE2_REG    = $4004
SND_TRIANGLE_REG   = $4008
SND_NOISE_REG      = $400C
SND_DELTA_REG      = $4010
SND_MASTERCTRL_REG = $4015

SPR_DMA            = $4014
JOYPAD_PORT        = $4016
JOYPAD_PORT1       = $4016
JOYPAD_PORT2       = $4017

JOYPAD_A      = %10000000
JOYPAD_B      = %01000000
JOYPAD_SELECT = %00100000
JOYPAD_START  = %00010000
JOYPAD_UP     = %00001000
JOYPAD_DOWN   = %00000100
JOYPAD_LEFT   = %00000010
JOYPAD_RIGHT  = %00000001

; Définitions

Compteur_VBlank    = $00
Mode_Logique       = $01
Timer_Curseur      = $02
Tuile_Nametable_Hi = $03
Tuile_Nametable_Lo = $04
Multi_Curseur      = $05
Vitesse_Curseur    = $06
Vitesse_Defilement = $07
Boutons_manette1   = $10
Boutons_manette2   = $11

GPOS_X_Curseur     = $0203
GPOS_Y_Curseur     = $0200
ID_Tuile_Curseur   = $0201
Palette_Curseur    = $0202

Position_X_Curseur = $12
Position_Y_Curseur = $13
Mode_Manette       = $14
Tuile_Actuelle     = $15

  .org $8000

Reset:
  SEI
  CLD                    ; Désactiver le mode décimal (Drapeau D)
  LDA #%00010000         ; Désactiver les NMI
  STA PPU_CTRL_REG1      ; Initialiser le PPU
  LDA #%00000000
  STA PPU_CTRL_REG2
  DEX
  TXS
  LDX #$40
  STX JOYPAD_PORT2       ; Désactiver l'IRQ de frame de l'APU
  INX                    ; Registre X = #$FF (-1) + #$01 = #$00
  STX SND_DELTA_REG      ; Désactiver les IRQ du DMC
  LDA #$0F
  STA SND_MASTERCTRL_REG ; Désactiver le DMC
  LDX #$00
  JSR VBLANK_wait

Nettoie:
  LDA #$00
  STA $00,X
  STA $0100,X
  STA $0200,X
  STA $0300,X
  STA $0400,X
  STA $0500,X
  STA $0600,X
  STA $0700,X
  INX
  BNE Nettoie
  JSR VBLANK_wait

Charger_curseur:
  LDA #$01
  STA ID_Tuile_Curseur
  LDA #$20
  STA Tuile_Nametable_Hi
  LDA #$03
  STA Vitesse_Curseur
  STA Vitesse_Defilement

Charger_palettes:
  LDA #$3F        ; Hi-byte
  STA PPU_ADDRESS ; Enregistrer le hi-byte de l'adresse $3F00
  LDA #$00        ; Lo-byte
  STA PPU_ADDRESS ; Enregistrer le lo-byte de l'adresse $3F00
  LDX #$00        ; Démarrer à 0

Charger_palettes_loop:
  LDA PALETTES,X            ; Charger les données des palettes avec X comme curseur
  STA PPU_DATA              ; Enregistrer sur le PPU
  INX                       ; Incrementer le curseur (X) par 1
  CPX #$20                  ; Dès que X = $20, on ignore la branche
  BNE Charger_palettes_loop ; Branche jusqu'à ce que la comparaison = 0

Charger_page1_message:
  LDA #$20        ; Hi-byte
  STA PPU_ADDRESS ; Enregistrer le hi-byte de l'adresse $2000
  LDA #$00        ; Lo-byte
  STA PPU_ADDRESS ; Enregistrer le lo-byte de l'adresse $2000
  LDX #$00        ; Démarrer à 0

Charger_page1_message_loop:
  LDA PAGE1_MESSAGE,X
  STA PPU_DATA                   ; Enregistrer sur le PPU
  INX                            ; Incrementer le curseur (X) par 1
  CPX #$16                       ; Dès que X = $16, on ignore la branche
  BNE Charger_page1_message_loop ; Branche jusqu'à ce que la comparaison = 0
  LDX #$00                       ; On réinitialise X

Initialiser_manettes:
  LDA #%10010000
  STA PPU_CTRL_REG1  ; Activer les NMI
  LDY Mode_Logique
  CPY #$01
  BEQ Suite_manettes
  INC Mode_Logique
Suite_manettes:
  JSR Bits_manettes
  LDA Boutons_manette1
  LDA Boutons_manette2
  JSR Bits_manettes
  LDY Mode_Manette
  CPY #$00
  BEQ IO1_Curseur
  JMP IO2_Curseur

Bits_manettes:
  LDA #$01
  STA Boutons_manette2
  STA JOYPAD_PORT
  LSR
  STA JOYPAD_PORT

Dedans_dehors:
  LDA JOYPAD_PORT1
  AND #%00000011
  CMP #$01
  ROL Boutons_manette1
  LDA JOYPAD_PORT2
  AND #%00000011
  CMP #$01
  ROL Boutons_manette2
  BCC Dedans_dehors
  RTS

IO1_Curseur:
  LDA Vitesse_Curseur
  CMP Timer_Curseur
  BNE Passer_Manette
  LDY #$00
  STY Timer_Curseur
  LDX #JOYPAD_RIGHT
  CPX Boutons_manette1
  BEQ Curseur_droite
  LDX #JOYPAD_LEFT
  CPX Boutons_manette1
  BEQ Curseur_gauche
  LDX #JOYPAD_START
  CPX Boutons_manette1
  BEQ Vitesse_moins
  LDX #JOYPAD_SELECT
  CPX Boutons_manette1
  BEQ Vitesse_plus
  LDX #JOYPAD_A
  CPX Boutons_manette1
  BEQ Manette_A
  LDX #$00
  JMP Afficher_sprites
Passer_Manette:
  LDX #$00
  INC Timer_Curseur
  JMP Afficher_sprites
Vitesse_plus:
  LDA #$00
  STA Timer_Curseur
  INC Vitesse_Curseur
  JMP Afficher_sprites
Vitesse_moins:
  LDA #$00
  STA Timer_Curseur
  DEC Vitesse_Curseur
  JMP Afficher_sprites
Curseur_gauche:
  LDY GPOS_X_Curseur
  CPY #$00
  BEQ Curseur_gauche_pre_deux
  JMP Curseur_gauche_pre_trois
Curseur_gauche_pre_deux:
  LDY #$00
Curseur_gauche_deux:
  DEC GPOS_Y_Curseur
  INY
  CPY #$08
  BEQ Curseur_gauche_pre_trois
  JMP Curseur_gauche_deux
Curseur_gauche_pre_trois:
  LDY #$00
Curseur_gauche_trois:
  LDX #$00
  DEC Position_X_Curseur
  DEC GPOS_X_Curseur
  INY
  CPY #$08
  BEQ Decrementer_PPU_ADDRESS_Lo
  JMP Curseur_gauche_trois
Curseur_droite:
  LDY GPOS_X_Curseur
  CPY #$F8
  BEQ Curseur_droite_pre_deux
  JMP Curseur_droite_pre_trois
Curseur_droite_pre_deux:
  LDY #$00
Curseur_droite_deux:
  INC GPOS_Y_Curseur
  INY
  CPY #$08
  BEQ Curseur_droite_pre_trois
  JMP Curseur_droite_deux
Curseur_droite_pre_trois:
  LDY #$00
Curseur_droite_trois:
  LDX #$00
  INC Position_X_Curseur
  INC GPOS_X_Curseur
  INY
  CPY #$08
  BEQ Incrementer_PPU_ADDRESS_Lo
  JMP Curseur_droite_trois

Manette_A:
  INC Mode_Manette
  INC ID_Tuile_Curseur
  JMP Afficher_sprites

Incrementer_PPU_ADDRESS_Lo:
  LDY #$FF
  CPY Tuile_Nametable_Lo
  BEQ Incrementer_PPU_ADDRESS_Hi
  INC Tuile_Nametable_Lo
  JMP Afficher_sprites
Incrementer_PPU_ADDRESS_Hi:
  INC Tuile_Nametable_Lo
  LDY #$23
  CPY Tuile_Nametable_Hi
  BNE Incrementer_PPU_ADDRESS_Hi_Suite
  LDA #$20
  STA Tuile_Nametable_Hi
  JMP Afficher_sprites
Incrementer_PPU_ADDRESS_Hi_Suite:
  INC Tuile_Nametable_Hi
  JMP Afficher_sprites
Decrementer_PPU_ADDRESS_Lo:
  LDY #$00
  CPY Tuile_Nametable_Lo
  BEQ Decrementer_PPU_ADDRESS_Hi
  DEC Tuile_Nametable_Lo
  JMP Afficher_sprites
Decrementer_PPU_ADDRESS_Hi:
  DEC Tuile_Nametable_Lo
  LDY #$20
  CPY Tuile_Nametable_Hi
  BNE Decrementer_PPU_ADDRESS_Hi_Suite
  LDA #$23
  STA Tuile_Nametable_Hi
  JMP Afficher_sprites
Decrementer_PPU_ADDRESS_Hi_Suite:
  DEC Tuile_Nametable_Hi
  JMP Afficher_sprites

D_Passer_Manette:
  LDX #$00
  INC Timer_Curseur
  JMP Afficher_sprites

IO2_Curseur:
  LDA Vitesse_Defilement
  CMP Timer_Curseur
  BNE D_Passer_Manette
  LDY #$00
  STY Timer_Curseur
  LDX #JOYPAD_UP
  CPX Boutons_manette1
  BEQ D_Curseur_haut
  LDX #JOYPAD_DOWN
  CPX Boutons_manette1
  BEQ D_Curseur_bas
  LDX #JOYPAD_START
  CPX Boutons_manette1
  BEQ D_Vitesse_plus
  LDX #JOYPAD_SELECT
  CPX Boutons_manette1
  BEQ D_Vitesse_moins
  LDX #JOYPAD_A
  CPX Boutons_manette1
  BEQ D_Manette_A
  LDX #$00
  JMP Afficher_sprites

D_Manette_A:
  DEC Mode_Manette
  DEC ID_Tuile_Curseur
  JMP Afficher_sprites

D_Curseur_haut:
  LDA Tuile_Nametable_Hi
  STA PPU_ADDRESS
  LDA Tuile_Nametable_Lo
  STA PPU_ADDRESS
  INC Tuile_Actuelle
  LDA Tuile_Actuelle
  STA PPU_DATA
  JMP Afficher_sprites

D_Curseur_bas:
  LDA Tuile_Nametable_Hi
  STA PPU_ADDRESS
  LDA Tuile_Nametable_Lo
  STA PPU_ADDRESS
  DEC Tuile_Actuelle
  LDA Tuile_Actuelle
  STA PPU_DATA
  JMP Afficher_sprites

D_Vitesse_plus:
  INC Vitesse_Defilement
  JMP Afficher_sprites

D_Vitesse_moins:
  DEC Vitesse_Defilement
  JMP Afficher_sprites

Afficher_sprites:
  LDA $0200,X
  STA PPU_OAM_DATA
  INX
  BNE Afficher_sprites

Calibrer_scrolling:
  LDA #%00000000         ; Zéro.
  STA PPU_SCROLL_REG
  LDA #$FF               ; -1.
  STA PPU_SCROLL_REG     ; Registre du scrolling
  LDA #%00011110
  STA PPU_CTRL_REG2      ; Activer le rendu

Loop_infini:
  JMP Loop_infini ; Fin du programme

NonMaskableInterrupt:
  INC Compteur_VBlank
  LDY Mode_Logique
  CPY #$00
  BEQ Interruption
  PLA
  PLA
  PLA
  LDA #$00
  JMP Initialiser_manettes
Interruption:
  RTI ; Return from interrupt

VBLANK_wait:
  BIT PPU_STATUS  ; Test des bits
  BPL VBLANK_wait ; Branche sur plus
  RTS             ; Return

BG_PALETTE = $0F

PALETTES:
  .db BG_PALETTE,$30,$21,$16   ; Palette 0 des caractères
  .db BG_PALETTE,$30,$00,$1D   ; Palette 1 des caractères
  .db BG_PALETTE,$30,$00,$1D   ; Palette 2 des caractères
  .db BG_PALETTE,$30,$00,$1D   ; Palette 3 des caractères
  .db BG_PALETTE,$16,$2B,$1D   ; Palette 0 des sprites
  .db BG_PALETTE,$30,$00,$1D   ; Palette 1 des sprites
  .db BG_PALETTE,$30,$00,$1D   ; Palette 2 des sprites
  .db BG_PALETTE,$30,$00,$1D   ; Palette 3 des sprites

PAGE1_MESSAGE:
  .db "Bonjour tout le monde!"

  .org $FFFA
  .dw NonMaskableInterrupt
  .dw Reset
  .dw Interruption
Don't ask me to translate. I'm too lazy for that and you can surely understand what's going on.

lidnariq
Posts: 10423
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Scrolling going nuts for no reason

Post by lidnariq » Sun Apr 04, 2021 3:01 pm

The NES only has one pointer to PPU memory. It is used both for scrolling and uploads. If your upload does not fit in one vblank and you disable rendering to get more time, you must wait until the next NMI and reset scrolling and re-enable rendering before the next redraw starts.

VGdevOnSNES
Posts: 8
Joined: Sat Apr 03, 2021 6:03 am

Re: Scrolling going nuts for no reason

Post by VGdevOnSNES » Mon Apr 05, 2021 4:59 am

lidnariq wrote:
Sun Apr 04, 2021 3:01 pm
The NES only has one pointer to PPU memory. It is used both for scrolling and uploads. If your upload does not fit in one vblank and you disable rendering to get more time, you must wait until the next NMI and reset scrolling and re-enable rendering before the next redraw starts.
So, i moved the instructions in NMI part.
What i did is resetting the scrolling THEN re-enabling the rendering.
For some reason, it's even worse! The scrolling justs moves up infinitely!

Why does it happen?

VGdevOnSNES
Posts: 8
Joined: Sat Apr 03, 2021 6:03 am

Re: Scrolling going nuts for no reason

Post by VGdevOnSNES » Mon Apr 05, 2021 5:02 am

test it yourself, that should help you.
Attachments
OUTPUT.NES
(40.02 KiB) Downloaded 3 times

Post Reply