It is currently Sat Sep 23, 2017 7:25 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Fri Aug 04, 2017 8:41 am 
Offline
User avatar

Joined: Wed Sep 21, 2016 12:08 pm
Posts: 33
I'm trying to use CHR-RAM but am having a problem when I try to copy the pattern table data from PRG ROM.

Here is my NMI Code

Code:
LBL.NMI:

  PHA
  TXA
  PHA
  TYA
  PHA

LDA FLAG.NMI.Update.Background   
BNE LBL.NMI.LoadBackground
  JMP LBL.NMI.LoadTiles

LBL.NMI.LoadBackground:
  LDA FALSE
  STA FLAG.NMI.Update.Background   

  LDA #$00
  STA $2001

  LDA $2002
  LDA #$20
  STA $2006
  LDA #$00
  STA $2006

  LDX #$04
  LDY #$00
LBL.LoadBackground.Nametable.Loop:
    LDA (PTR.Background.Nametable), y
    STA $2007
    INY
    BNE LBL.LoadBackground.Nametable.Loop
      INC PTR.Background.Nametable + 1;
      DEX
      BNE LBL.LoadBackground.Nametable.Loop

LBL.NMI.LoadTiles:
  LDA FLAG.NMI.Update.Bank
  BNE LBL.NMI.LoadTiles.Continue
    JMP LBL.NMI.Reset

LBL.NMI.LoadTiles.Continue:   
  LDA FALSE
  STA FLAG.NMI.Update.Bank
 
  LDA $2002
  LDA #$00
  STA $2006
  STA $2006

  LDX #$03
  LDY #$00
  LBL.LoadTiles.Loop:
    LDA (PTR.Tiles),y
    STA $2007
    INY
    BNE LBL.LoadTiles.Loop
     INC PTR.Tiles+1;
     DEX
     BNE LBL.LoadTiles.Loop

PLA
TAY
PLA
TAX
PLA
RTI

LBL.NMI.Reset:

  LDA #%10001000
  STA $2000
  LDA #%00011110
  STA $2001
  LDA #$00
  STA $2005
  STA $2005

  INC VAR.Frame
 
  PLA
  TAY
  PLA
  TAX
  PLA
  RTI


The Level Initiation Loop is given below

Code:
LBL.State.Game.Initialize:
  JSR LBL.Wait.Frame
  JSR LBL.Jumper.Scene.Initialize
  LDA #State.Game.Update
  STA VAR.State.Game
  RTS

LBL.Wait.Frame:
  LDA VAR.Frame
LBL.Wait.Frame.Loop:
  CMP VAR.Frame
  BEQ LBL.Wait.Frame.Loop
RTS



It works great until I increase the number of pages to copy from 3 to 4 or more ("LDX #$03 to LDX #$04"). Then the PPU becomes corrupted.

I'm missing something, but can't tell if it's a coding error or fundamental misunderstanding about the PPU Enable/Disable and NMI timing.

Thank you for any help!


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 8:54 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10012
Location: Rio de Janeiro - Brazil
Normally you wouldn't be doing this kind of heavy VRAM updating in the NMI, which is more for incremental frame-to-frame updates, so my guess is that you have multiple NMIs firing before the previous instances have time to finish (i.e. they're taking longer than a frame to finish), and they end up using "corrupted" flags, pointers and the like.


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 9:05 am 
Offline
User avatar

Joined: Wed Sep 21, 2016 12:08 pm
Posts: 33
I thought that too so I tried adding a disable NMI command (STA $2000) at the beginning of the NMI to see if that would fix the problem and it didn't. It made it worse. I also tried using the debugger in FCEUX to see if a second NMI is being triggered before I complete the loop (using breakpoints) and it wasn't. The more I look at the problem, the more I wonder if it's a flaw in the engine. I'll look at how I might effeciently pull the scene initialization code out of the NMI.


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 9:13 am 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 783
Location: cypress, texas
Just want to pass on a smaller LBL.Wait.Frame that someone from this forum recommended me use.
Code:
- lda $2002
bpl -


I don't know if this will solve your problem, but you need to wait two vblanks during startup. And I would also recommend not using two jsrs to LBL.Wait.Frame; instead just place those two lines of code twice cause the jsrs are slow and you lose cycles for each use of them. JSRs are good; you can input sections of code using only 3 bytes; that helps with padding correctly; and if you jsr a function twice or more that is a good use; macro functions only JSRed once, unless you need to use only three bytes for padding purposes. :)

edit: Want to clear this up. JMP and RTS, together, take 12 cycles to run, so you would save 24 cycles if you followed my advise and save 2 bytes.
Code:
- lda $2002
bpl -

- lda $2002
bpl -
takes 10 bytes
Code:
jsr LBL.Wait.Frame
jsr LBL.Wait.Frame

LBL.Wait.Frame:
- lda $2002
bpl -
rts
takes 12 bytes. Hope this will be helpful to someone. Glad your code is working now! tokumaru is so very smart and helpful. :D


Last edited by unregistered on Fri Aug 04, 2017 1:21 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 9:24 am 
Offline
User avatar

Joined: Wed Sep 21, 2016 12:08 pm
Posts: 33
I have this when I'm simply waiting for an NMI call, but the Wait.Frame specifically watches the frame count variable for a change in value. If I'm doing partial frame updates in each NMI, I can use my code to wait over several NMIs before continuing.


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 10:24 am 
Offline
User avatar

Joined: Wed Sep 21, 2016 12:08 pm
Posts: 33
tokumaru wrote:
Normally you wouldn't be doing this kind of heavy VRAM updating in the NMI, which is more for incremental frame-to-frame updates, so my guess is that you have multiple NMIs firing before the previous instances have time to finish (i.e. they're taking longer than a frame to finish), and they end up using "corrupted" flags, pointers and the like.


I removed the Screen Initialization Code from the NMI logic and that fixed all my problems!


Top
 Profile  
 
PostPosted: Fri Aug 04, 2017 12:57 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 783
Location: cypress, texas
Lucradan wrote:
I have this when I'm simply waiting for an NMI call, but the Wait.Frame specifically watches the frame count variable for a change in value. If I'm doing partial frame updates in each NMI, I can use my code to wait over several NMIs before continuing.

That's pretty cool, I kind of see that now. :) Wow, my first comment was totally off; I'm sorry, waiting for two frames is only needed in the reset code... not in the NMI code. I made a mistake. :(

Everywhere you have:
Code:
bne
jmp
you can save a byte with
Code:
bne
beq
cause the BEQ will work just like a JMP if it follows a BNE. Just make sure the beq branches to the same page. :)

edit


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group