It is currently Fri Aug 23, 2019 12:30 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 39 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject: Re: Writing a NSF player
PostPosted: Tue Dec 11, 2018 2:55 am 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
So in other words if bank swapping is not used the loading part consists only of loading the actual file to memory so that the code can read it?
In one NSF I have exported the load address is $98D5. I'm assuming that this is the address in ROM where LOAD is located (but what is actually there and do I need to run that code at some point?). Also, is the 0x80 address in the NSF file that is the start of music and program data the start point of the "ROM" in it which I should start mapping from $8000 onward?


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Tue Dec 11, 2018 6:32 am 
Offline
NESICIDE developer
User avatar

Joined: Mon Oct 13, 2008 7:55 pm
Posts: 1089
Location: Minneapolis, MN
SusiKette wrote:
Using .dll seemed to be useless effort.

In what sense?


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Tue Dec 11, 2018 6:45 am 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
cpow wrote:
SusiKette wrote:
Using .dll seemed to be useless effort.

In what sense?


the program didn't sort of know it is there. It did display in the project tree and it did recognize some information about it, but you couldn't use it for some reason. It just didn't recognize it when I tried to actually include it into a script. I'm not sure if it was a bug or if it wasn't fully compatible


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 1:37 am 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
So here is a question about the carry flag. If I'm testing for overflow to set the carry flag, do I have to clear it if the condition to set it was not met (this might be relevant if carry was already set before the operation). Of course with ADC the carry flag would be used in the addition if it was set (is it cleared after?).

EDIT: Does the carry flag stay set if an overflow happens after adding the carry flag?

Code:
//cv.A = Accumulator
//cv.A_temp = Value of accumulator before operation

    public void OverflowTest()
    {
        if(cv.A_temp > cv.A)
        {
            Set_C();
        }
        else    //Is this part necessary?
        {
            Clear_C();
        }
    }


Secondly, do I have to code interrupts to the player? If I have to, which interrupts do I include and how should they be handled?


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 5:17 am 
Offline
NESICIDE developer
User avatar

Joined: Mon Oct 13, 2008 7:55 pm
Posts: 1089
Location: Minneapolis, MN
SusiKette wrote:
cpow wrote:
SusiKette wrote:
Using .dll seemed to be useless effort.

In what sense?


the program didn't sort of know it is there. It did display in the project tree and it did recognize some information about it, but you couldn't use it for some reason. It just didn't recognize it when I tried to actually include it into a script. I'm not sure if it was a bug or if it wasn't fully compatible


Yeah looks like I've some work to do since I only use it in C++ applications. :roll:


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 6:27 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21561
Location: NE Indiana, USA (NTSC)
SusiKette wrote:
If I'm testing for overflow to set the carry flag, do I have to clear it if the condition to set it was not met

Yes. Every instruction that changes a flag can set it to 1 or clear it to 0. There aren't really any instructions where the flag output from an instruction is OR'd with the existing flag value. But many instructions leave a flag unchanged: off the top of my head, only ADC, SBC, BIT, and PHP affect V. If an instruction does not modify a particular flag, such as AND and ORA not affecting C, then programs will expect its value to be preserved across the instruction.

SusiKette wrote:
Does the carry flag stay set if an overflow happens after adding the carry flag?

Yes. This means that if carry is set, ADC #$FF or SBC #$00 leaves both A and carry unchanged.

SusiKette wrote:
Secondly, do I have to code interrupts to the player?

Only for the experimental timer support in NSF version 2. Otherwise, the only thing resembling an interrupt is the one that calls the PLAY routine.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 6:48 am 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
tepples wrote:
Only for the experimental timer support in NSF version 2. Otherwise, the only thing resembling an interrupt is the one that calls the PLAY routine.


Do I have to detect the ending of the PLAY (and INIT) routines somehow or is there a infinite loop at the end that waits until I call the PLAY routine again? (basically change the program counter there or is there some other method to do it?)


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 7:04 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21561
Location: NE Indiana, USA (NTSC)
The INIT and PLAY routines end with an rts instruction. But because they may themselves call subroutines, you need to wait for an rts instruction to move the stack pointer into the area of the stack that you have reserved for the player.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 7:11 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7565
Location: Canada
SusiKette wrote:
So in other words if bank swapping is not used the loading part consists only of loading the actual file to memory so that the code can read it?
In one NSF I have exported the load address is $98D5. I'm assuming that this is the address in ROM where LOAD is located (but what is actually there and do I need to run that code at some point?). Also, is the 0x80 address in the NSF file that is the start of music and program data the start point of the "ROM" in it which I should start mapping from $8000 onward?


A LOAD of $98D5 means put the data from the NSF at $98D5. (If not bankswitching.)

Yes, the data begins at $80 in the file.


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 8:09 am 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
tepples wrote:
...you need to wait for an rts instruction to move the stack pointer into the area of the stack that you have reserved for the player.


Can you explain this a bit further?


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 8:51 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21561
Location: NE Indiana, USA (NTSC)
An NSF player is allowed to reserve the end of the stack page for memory used by the NSF player itself as opposed to memory used by the NSF being played. This is done to allow for NSF players that run on an NES, such as the NSF player in the PowerPak, which need to keep track of state such as current song, controller presses, and/or elapsed time. Suppose for example that an NSF player reserves memory addresses $01F1 through $01FF for its own use. Then when calling the INIT or PLAY routine of the NSF being played, the NSF player will push a return address within the NSF player's code, which address is stored at $01F0 (high byte) and $01EF (low byte), leaving the stack pointer (register S) at $EE before the CPU jumps to the INIT or PLAY routine. When the INIT or PLAY routine executes the rts instruction, it pulls the program counter from $01EF and $01F0, leaving the stack pointer at $F0. This would cause an NES-based NSF player to enter a routine that performs tasks such as input reading and waiting for the next opportunity to run the PLAY routine. An emulator-based NSF player, such as the one you are writing, would instead detect the end of the INIT or PLAY routine in one of two ways: the stack pointer (register S) has entered the area reserved for the player's use or the PC has taken on a particular reserved value denoting completion. You might choose $4100 or the like for this value.

In the preceding, which was the first word you failed to understand?

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Wed Dec 12, 2018 3:26 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7565
Location: Canada
You don't have to put anything on the stack for an NSF player emulator, maybe let's take one step back from this.

INIT and PLAY are both subroutines, that could normally be called via JSR. The subroutine runs, possibly calling its own subroutines, but eventually it finishes with an RTS like all subroutines do.

When a subroutines is finished, the stack register will be returned to the position it started by that RTS. Your NSF player could detect that the routine has finished just by checking the stack position, but there are other ways to do it as well.


Some NSF players, especially hardware ones, push a bit of extra stuff to the stack to help manage this. This is what tepples is talking about. Because according to the spec the NSF is allowed to use all RAM in the system the way it likes, except the stack region, the stack is the only safe place for a hardware NSF player to use for its own memory storage. Emulators don't have to do this, though they can. (It can be convenient for the implementation.)


One more thing: the PLAY routine does not necessarily have to return. Usually this is for NSFs that play recorded PCM samples over the DMC channel. Not all NSF players support this properly, but to support the NSF player should continue to produce sound in step with the CPU's actions, whether or not PLAY returns.


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Thu Dec 13, 2018 12:02 pm 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
I think I got the basic idea on how this works now. I think what I'll do is that when I call INIT or PLAY I'll push a return address to the stack, change the program counter to the routine's address and enable the CPU. The return address points to a part of the memory the program counter normally doesn't have any business begin at and this is tested after each opcode is executed. If it is within that area, I'll disable the CPU until I need to call PLAY again.


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Fri Dec 14, 2018 9:31 am 
Offline
User avatar

Joined: Fri Mar 16, 2018 1:52 pm
Posts: 93
Location: Finland
Can I run one frame's code (one PLAY routine) all at once or should I be waiting the appropriate amount of time between every instruction based on how long each instruction takes to process (559 ns per cycle iirc)? Since the player has to wait for the next call for PLAY routine anyway to continue even if it finished the routine sooner than what it would have if the wait between instructions was implemented. Could this cause any serious issues with the player?


Top
 Profile  
 
 Post subject: Re: Writing a NSF player
PostPosted: Fri Dec 14, 2018 10:48 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21561
Location: NE Indiana, USA (NTSC)
Non-returning PLAY routines, particularly those that play raw PCM through writes to $4011, depend on each instruction taking as many cycles as it actually takes.

_________________
Pin Eight | Twitter | GitHub | Patreon


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

All times are UTC - 7 hours


Who is online

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