It is currently Tue Nov 21, 2017 8:37 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 73 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
PostPosted: Tue Jul 22, 2014 9:43 am 
Offline
User avatar

Joined: Wed Jul 13, 2011 6:51 am
Posts: 395
Location: Brasilia, Brazil
yogi wrote:
Thanks man, I'll look it over but my code is working with the new controller Read code I posted.
Yogi


Yep, but I meant, put this on place of your code and test if it has any differences on performance...


Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 10:04 am 
Offline

Joined: Sun Nov 17, 2013 8:14 pm
Posts: 133
Location: Bowie, Maryland
From your 4th test rom
Code:
ControllerTest:                 ;EDIT:
   JSR ReadController   ; ReadController: returns in A AND NewButtons
   STA NewButtons3    ; First Read Val
   JSR ReadController
   PHA                        ; Stack has Second Read Val
   JSR ReadController
   STA NewButtons2     ; Third Read Val
   JSR ReadController   ; Fourth Read in NewButtons

   PLA                          ; POP Second Read
   CMP NewButtons3      ; Is Second = First?
   BEQ JoyEnd
   CMP NewButtons       ; Is Second = Fourth?
   BEQ JoyEnd
   LDA NewButtons2      ; No, so use Third Reading must be good (?)
   CMP #0                     ; CMP Third to 0 (?) set/clr Z (?)
JoyEnd:
   STA NewButtons        ; Store current Read 
   RTS                         ; Return

My code works for me, so not sure I should comment on your's if it works for you.
Yogi
EDIT: just noticed that your NES doesn't actually change the song, just moves the sprite. Was this your intent?
EDIT2: Changed the comments to better reflect the VAR usage.


Last edited by yogi on Tue Jul 22, 2014 2:37 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 10:22 am 
Offline
User avatar

Joined: Wed Jul 13, 2011 6:51 am
Posts: 395
Location: Brasilia, Brazil
yogi wrote:
EDIT: just noticed that your NES doesn't actually change the song, just moves the sprite. Was this your intent?


Yes, I was using a 1 song NSF and issuing a music change command would crash the playback driver.

That patch on the code was intended to stop the change music command from crashing the sound playback thread so the behavior of DPCM controller glitch could be fully appreciated.


Edit:
That controller code is from blargg:
viewtopic.php?t=4124

The point is doing multiple reads to reduce the chances of glitch on the controller input. As a bonus it also checks the expansion port for external controllers (this is a Famicom and some people use controllers connected to the 15 pin expansion port it has on the front...).


Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 10:47 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19238
Location: NE Indiana, USA (NTSC)
Here's the DPCM-safe code I use in my own projects, extracted from my project template. It handles both player 1 and player 2 as well as Famicom expansion controllers. And because it reads only twice, it takes nearly constant time unlike some routines that read repeatedly and wait for it to settle.
Code:
.segment "ZEROPAGE"
cur_keys: .res 2
new_keys: .res 2

.segment "CODE"
.proc read_pads
thisRead = $0000  ; local temporary variables
firstRead = $0002
lastFrameKeys = $0004

  ; store the current keypress state to detect key-down later
  lda cur_keys
  sta lastFrameKeys
  lda cur_keys+1
  sta lastFrameKeys+1

  ; Read the joypads twice in case DMC DMA caused a clock glitch.
  jsr read_pads_once
  lda thisRead
  sta firstRead
  lda thisRead+1
  sta firstRead+1
  jsr read_pads_once

  ; For each player, make sure the reads agree, then find newly
  ; pressed keys.
  ldx #1
@fixupKeys:

  ; If the player's keys read out the same way both times, update.
  ; Otherwise, keep the last frame's keypresses.
  lda thisRead,x
  cmp firstRead,x
  bne @dontUpdateGlitch
  sta cur_keys,x
@dontUpdateGlitch:
 
  lda lastFrameKeys,x   ; A = keys that were down last frame
  eor #$FF              ; A = keys that were up last frame
  and cur_keys,x        ; A = keys down now and up last frame
  sta new_keys,x
  dex
  bpl @fixupKeys
  rts

read_pads_once:

  ; Bits from the controllers are shifted into thisRead and
  ; thisRead+1.  In addition, thisRead+1 serves as the loop counter:
  ; once the $01 gets shifted left eight times, the 1 bit will
  ; end up in carry, terminating the loop.
  lda #$01
  sta thisRead+1
  ; Write 1 then 0 to JOY1 to send a latch signal, telling the
  ; controllers to copy button states into a shift register
  sta JOY1
  lsr a
  sta JOY1
  loop:
    ; On NES and AV Famicom, button presses always show up in D0.
    ; On the original Famicom, presses on the hardwired controllers
    ; show up in D0 and presses on plug-in controllers show up in D1.
    ; D2-D7 consist of data from the Zapper, Power Pad, Vs. System
    ; DIP switches, and bus capacitance; ignore them.
    lda JOY1       ; read player 1's controller
    and #%00000011 ; ignore D2-D7
    cmp #1         ; CLC if A=0, SEC if A>=1
    rol thisRead   ; put one bit in the register
    lda JOY2       ; read player 2's controller the same way
    and #$03
    cmp #1
    rol thisRead+1
    bcc loop       ; once $01 has been shifted 8 times, we're done
  rts
.endproc


Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 12:46 pm 
Offline

Joined: Sun Nov 17, 2013 8:14 pm
Posts: 133
Location: Bowie, Maryland
l_oliveira wrote:
yogi wrote:
EDIT: just noticed that your NES doesn't actually change the song, just moves the sprite. Was this your intent?


Yes, I was using a 1 song NSF and issuing a music change command would crash the playback driver.

That patch on the code was intended to stop the change music command from crashing the sound playback thread so the behavior of DPCM controller glitch could be fully appreciated.

OK thought so but just thought I should point it out if you didn't realise. In my routine I can start/stop playback and test song selection, of course if I try to play song 2-10 of a single song NSF it will crash.

Quote:
Edit:
That controller code is from blargg:
viewtopic.php?t=4124

The point is doing multiple reads to reduce the chances of glitch on the controller input. As a bonus it also checks the expansion port for external controllers (this is a Famicom and some people use controllers connected to the 15 pin expansion port it has on the front...).

I understand the need to do multi reads; but the fourth read is not used for anything. Is it just a wait loop?

Quote:
Yep, but I meant, put this on place of your code and test if it has any differences on performance...

Well this code would need some fixes to work in my code infrastructure that aren't trivial. I'll try it at some point, after I get a bit more testing done.
So far with my testing: Went through the NSFs I used in this test rom
Attachment:
vegaplayMMC1test16.nes [256.02 KiB]
Downloaded 51 times

Some of the source NSFs have a 'random dropped frame' issue in Nestopia that also shows up in the NES (GIGO ?).
The worst is (NSF #5):
Attachment:
Entry087.nsf [23.25 KiB]
Downloaded 51 times

It's a good. fast song but really hammers the DPCM channel. This is the only one that causes an occasional bankswitch now (so even doing multi reads can return a false read?). With Nestopia the NSF drops the tempo from time to time (unintentionally, I think) as do a few other NSF also.
The fact that the source NSFs have problems playing in Nestopia leads me to believe there is:
a. a bug/problem with the NSF in question
b. a bug with Nestopia
c. a bug caused by Windows
d. The Moon is in the wrong phase for chiptune playback

Will be burning to a cart to see how real HW handles it.
Yogi


Last edited by yogi on Tue Jul 22, 2014 12:58 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 12:55 pm 
Offline

Joined: Sun Nov 17, 2013 8:14 pm
Posts: 133
Location: Bowie, Maryland
tepples wrote:
Here's the DPCM-safe code I use in my own projects, extracted from my project template. It handles both player 1 and player 2 as well as Famicom expansion controllers. And because it reads only twice, it takes nearly constant time unlike some routines that read repeatedly and wait for it to settle.
Code:
.segment "ZEROPAGE"
cur_keys: .res 2
new_keys: .res 2

.segment "CODE"
.proc read_pads
thisRead = $0000  ; local temporary variables
firstRead = $0002
lastFrameKeys = $0004

  ; store the current keypress state to detect key-down later
  lda cur_keys
  sta lastFrameKeys
  lda cur_keys+1
  sta lastFrameKeys+1

  ; Read the joypads twice in case DMC DMA caused a clock glitch.
  jsr read_pads_once
  lda thisRead
  sta firstRead
  lda thisRead+1
  sta firstRead+1
  jsr read_pads_once

  ; For each player, make sure the reads agree, then find newly
  ; pressed keys.
  ldx #1
@fixupKeys:

  ; If the player's keys read out the same way both times, update.
  ; Otherwise, keep the last frame's keypresses.
  lda thisRead,x
  cmp firstRead,x
  bne @dontUpdateGlitch
  sta cur_keys,x
@dontUpdateGlitch:
 
  lda lastFrameKeys,x   ; A = keys that were down last frame
  eor #$FF              ; A = keys that were up last frame
  and cur_keys,x        ; A = keys down now and up last frame
  sta new_keys,x
  dex
  bpl @fixupKeys
  rts

read_pads_once:

  ; Bits from the controllers are shifted into thisRead and
  ; thisRead+1.  In addition, thisRead+1 serves as the loop counter:
  ; once the $01 gets shifted left eight times, the 1 bit will
  ; end up in carry, terminating the loop.
  lda #$01
  sta thisRead+1
  ; Write 1 then 0 to JOY1 to send a latch signal, telling the
  ; controllers to copy button states into a shift register
  sta JOY1
  lsr a
  sta JOY1
  loop:
    ; On NES and AV Famicom, button presses always show up in D0.
    ; On the original Famicom, presses on the hardwired controllers
    ; show up in D0 and presses on plug-in controllers show up in D1.
    ; D2-D7 consist of data from the Zapper, Power Pad, Vs. System
    ; DIP switches, and bus capacitance; ignore them.
    lda JOY1       ; read player 1's controller
    and #%00000011 ; ignore D2-D7
    cmp #1         ; CLC if A=0, SEC if A>=1
    rol thisRead   ; put one bit in the register
    lda JOY2       ; read player 2's controller the same way
    and #$03
    cmp #1
    rol thisRead+1
    bcc loop       ; once $01 has been shifted 8 times, we're done
  rts
.endproc

Thanks, at one point I tried converting the core read routine from your template, but ran into issues with my cut down (busted) version and the surrounding code. I will revisit it with a fresh mind :)
yogi


Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 1:32 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
yogi wrote:
I understand the need to do multi reads; but the fourth read is not used for anything. Is it just a wait loop?

The fourth read places the controller byte into NewButtons (in this case). The value gets compared to later on with CMP NewButtons.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Tue Jul 22, 2014 2:07 pm 
Offline

Joined: Sun Nov 17, 2013 8:14 pm
Posts: 133
Location: Bowie, Maryland
thefox wrote:
yogi wrote:
I understand the need to do multi reads; but the fourth read is not used for anything. Is it just a wait loop?

The fourth read places the controller byte into NewButtons (in this case). The value gets compared to later on with CMP NewButtons.

Hey Thefox, sorry, I missed that in the ReadController Sub
Yogi


Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 7:59 am 
Offline
User avatar

Joined: Wed Jul 13, 2011 6:51 am
Posts: 395
Location: Brasilia, Brazil
Hey yogi, more stuff for you to play with ! :)

The N163 was a tad tricky to get to work because hardware NSF players don't rely on the mapper native mechanism so they aren't affected by this issue:

N163 has the sound hardware enable bit on one of the bank change registers so I had to "patch" the driver code to not write there as it was crashing due to unwanted memory bank changes.

And this song is just plain awesome...

Edit: There were some writes missing on the code. I did not init the registers which did CIRAM control so in FCEUX it works fine but on the real thing you get a nice gray screen with music playing.

There's a fixed version, now.

Edit2: The volume is wrong on my cart. N163 plays way too loud. This tune is 1 channel and my N163 dev cart is based on a 8 channel game.


Attachments:
Making it run on a N163v2.zip [29.48 KiB]
Downloaded 58 times
Making it run on a N163.zip [29.44 KiB]
Downloaded 56 times
Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 12:29 pm 
Offline
User avatar

Joined: Wed Jul 13, 2011 6:51 am
Posts: 395
Location: Brasilia, Brazil
Now that the basic idea is laid out, the mapper init code can be useful to other people so I'd like to add this one, too.


Attachments:
Making it run on a Sunsoft5B.zip [15.26 KiB]
Downloaded 57 times
Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 2:28 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6447
Location: UK (temporarily)
l_oliveira wrote:
I did not init the registers which did CIRAM control
Huh, I bet you could use that to make a board that wouldn't need to have its CHR-ROM replaced.
Quote:
This tune is 1 channel and my N163 dev cart is based on a 8 channel game.
Sadly, nothing to be done for that other than adding a potentiometer...


Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 2:42 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5824
Location: Canada
Could you re-export the tune with more channels enabled but silent? That would lower the volume. (Trivial if you have famitracker source, not so trivial if all you have is the NSF.)


Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 2:51 pm 
Offline
User avatar

Joined: Wed Jul 13, 2011 6:51 am
Posts: 395
Location: Brasilia, Brazil
lidnariq wrote:
Huh, I bet you could use that to make a board that wouldn't need to have its CHR-ROM replaced.

Yep, but the point here was use that "ugly" board I made with the N163 I got from Namco Classic II, so it already has a socket for CHR-ROM...

(this one)http://forums.nesdev.com/viewtopic.php?f=9&t=8570

lidnariq wrote:
Sadly, nothing to be done for that other than adding a potentiometer...

Yeah ... I will look into implementing something like that.

rainwarrior wrote:
Could you re-export the tune with more channels enabled but silent? That would lower the volume. (Trivial if you have famitracker source, not so trivial if all you have is the NSF.)


That's actually a very good idea, but considering the "generic" context this is going to have, adjustable volume could be something more desirable ...


Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 3:40 pm 
Offline

Joined: Sun Nov 17, 2013 8:14 pm
Posts: 133
Location: Bowie, Maryland
Hey Guys,
You've been busy l_oliveira. ++ on the Sunsoft 5B :) With INL's flash cart this would be killer!
The N163 sounds so good, may have to go hunting on Ebay for a donor cart. Looked over the code but will need a closer look for an indepth understanding. Lik'en It

Been working on another preview. This time moved the Sprite Ram into WRAM @ $6000, had a few NSF that trashed it @ $0500.

As to the DMA bug, I took the coward's way out; now the code only checks the 'Start' button during playback. You can select Song/NSF only when NO song is playing. This avoids the random false 'Right' trigger, but it's not a great solution. So there is extra button pressing, Start Button to stop the playing song and then select a new song/NSF.
I tried your ControllerTest routine, l_oliveira, but ran into issues that broke the main code so I set it aside for the moment.
As things are I had planned to use Right/Left buttons on Controller 2 for Midi controlled Frame FF and Rewind. Wouldn't be the end of the world if I have to re-assign these functions to other buttons, just have to adjust my PIC code. Hummm

When I included this 'pre check' just after my Controller1Test
Code:
   LDA NewButtons      ; Check for a New Active buttons
   BEQ BreakOut      ; NewButtons=$FF, No buttons pressed
   CMP OldButtons      ; Pressed buttons same as last MainLoop Pass?
   BNE Update         ; No , so test Controller 1 buttons
   
BreakOut:
   JMP MainLoop

This improved playback in the last Preview code, but didn't eliminate the DMA bug.

The odd effect was, the NSF that would trip a bankswitch would never do it at the same Frame, some NSFs did it after 3-6 loops. This leads me to think it's a side effect of my MainLoop's controller read frequency and the DPCM useage lining up at random (or very long cycle) points where I have two false reads in a row that are affected by the DMA. Bears more thought.

Anyway, here is the latest build preview. A new group of songs from the Famicomp Mini 10. NSF #3 is very experimental and 'beepy'; when I first listened to it in my build, I freaked out. The song REALLY does some weird tempo breaks and sounds like the NES is broken at some points :)
NSF #5 is the same song from last preview, Without random banking.
Attachment:
Main_vpMMC16.nes [256.02 KiB]
Downloaded 55 times

Yogi


Top
 Profile  
 
PostPosted: Thu Jul 24, 2014 4:06 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19238
Location: NE Indiana, USA (NTSC)
If you put the display list at $6000, some playback engine will probably end up trashing it there too. You might need to make it configurable per NSF.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 73 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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