It is currently Thu Nov 23, 2017 1:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Sat Sep 24, 2016 9:36 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1467
The readme file of FamiTone says the following:
Quote:
DPCM samples (*.bin file) are a special case.
They should be placed at $c000 or above, with steps of 64 bytes, and
they always should be in CPU address space to be accessible by the DPCM
hardware.


According to that statement, I declared the ROM space for my sample like this:
Code:
SAMPLES: load = PRG_ROM, type = ro, align = $0040, define = yes;


But I'd like to know why this is the case. If I remove the alignment, the sample is still played correctly.

What's the specific reason that a digitized sample should start at a memory location that's a multiple of 64?

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Sat Sep 24, 2016 9:48 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
DRW wrote:
What's the specific reason that a digitized sample should start at a memory location that's a multiple of 64?

It's because the register used to set the sample address is only 8 bits wide. To get more range out of those bits they decided to address units larger than a byte, so they ended up going with blocks of 64 bytes. The same thing happened to the sample length, which is also specified using a single byte, so it counts blocks of 16 bytes instead of single bytes.

As for why they still play fine when not properly aligned, I guess you're probably using a high enough playback rate that skipping a little bit of the sample of playing a little bit of garbage before it doesn't cause any audible problems.


Last edited by tokumaru on Sat Sep 24, 2016 9:50 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sat Sep 24, 2016 9:50 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
This is due to the how the DMC implementation in the CPU works, specifically for register $4012 (sample address start). The "starting" or "base" address is calculated by the circuitry with 64-byte offsets in mind (e.g. $C000, $C040, $C080, $C0C0, etc.; the address itself is $C000+(value*64)).

References:

https://wiki.nesdev.com/w/index.php/APU_DMC
https://emudocs.org/NES/nestech.txt
viewtopic.php?f=10&t=11550


Top
 Profile  
 
PostPosted: Sat Sep 24, 2016 11:39 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
tokumaru wrote:
As for why they still play fine when not properly aligned, I guess you're probably using a high enough playback rate that skipping a little bit of the sample of playing a little bit of garbage before it doesn't cause any audible problems.

Or getting lucky that it ends up being aligned even if not explicitly specified as so.

It's a good idea to include an .assert to verify that the alignment is correct:
Code:
.assert sample .mod 64 = 0, error
sample: .incbin "sample.dmc"

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


Top
 Profile  
 
PostPosted: Sun Sep 25, 2016 3:39 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1467
Alright, thanks for the information.

thefox wrote:
It's a good idea to include an .assert to verify that the alignment is correct

Thanks for the tip, but that's not necessary here. The configuration file has the align property that ensures this:
Code:
SAMPLES: load = PRG_ROM, type = ro, align = $0040, define = yes;


The NES Space Checker tool tells me which parts of the ROM are non-zero and which are zero. With this, I can confirm that the samples indeed always align to 64 bytes when set like this in the config.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Sun Sep 25, 2016 5:28 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
DRW wrote:
The configuration file has the align property that ensures this:

.assert is another layer of verification, it shields you from bugs that could arise from future modifications (like changing the linker configuration, or accidentally putting some other data in the SAMPLES segment, or forgetting about the alignment requirement and moving the data to another segment, or ...).

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


Top
 Profile  
 
PostPosted: Sun Sep 25, 2016 9:10 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
thefox wrote:
.assert is another layer of verification, it shields you from bugs that could arise from future modifications (like changing the linker configuration, or accidentally putting some other data in the SAMPLES segment, or forgetting about the alignment requirement and moving the data to another segment, or ...).

...or being paranoid. :roll:

When I first started using ca65 I found asserts really cool, so I started putting all sorts of validations in my macros and in almost everything I was doing. In the end that just made my code look really bloated and harder to maintain, so I decided to stop being so paranoid and got rid of much of it, keeping only what was absolutely necessary. Worrying about every possible little thing that could maybe happen in the future was kinda holding me back, actually.


Top
 Profile  
 
PostPosted: Sun Sep 25, 2016 9:25 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
tokumaru wrote:
...or being paranoid. :roll:

When I first started using ca65 I found asserts really cool, so I started putting all sorts of validations in my macros and in almost everything I was doing. In the end that just made my code look really bloated and harder to maintain, so I decided to stop being so paranoid and got rid of much of it, keeping only what was absolutely necessary. Worrying about every possible little thing that could maybe happen in the future was kinda holding me back, actually.

Yeah it's definitely possible to go overboard with this. I usually add asserts only when it's immediately obvious to me how to construct the assertion expression (so I don't feel like I'm wasting much time on it).

Overall, I think it's much more important if you're writing library code (which I guess not that many people are doing on 6502), rather than if you're writing code that you're only using by yourself.

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


Top
 Profile  
 
PostPosted: Sun Sep 25, 2016 10:11 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5833
Location: Canada
The canonical way to align something in ca65 is to give the segment an align property (which you've already done), and then use .align in the code that fills the segment.
Code:
.align $40
sample: .incbin "whatever.dmc"

At that point there's no need for an assert, unless you think the assembler has a bug in it. Without using .align you haven't actually specified a specific location for that code and are relying on the link order. You're probably only using that segment in one place, and you're probably making it the first thing in that segment, but if you want to actually tell ca65 where to put the code, that's what .align is for.

There's actually a valid reason to use .assert instead of .align too. The function of .align is to add any necessary padding to reach the next aligned address (or emit an error if the segment isn't aligned). If you want to specify that nothing extra should be added, and it should only appear where you expect it to be, then .assert is correct instead.

tokumaru wrote:
being paranoid...

I think asserts are an essential language feature. I put them anywhere I think I might make a mistake. They don't often trigger, but when they do I'm very glad they're there. The point is to catch yourself when you make an error. It's easy to make mistakes. It's easy to accidentally put an extra byte in a segment. It's easy to accidentally leave out a comma somewhere. It's easy to accidentally type into your text editor when you think you're controlling your game. It's not paranoid to think these things might happen. They do! (This probability is magnified immensely if more than one person is working on the project.)

I don't know what you were doing in your code, maybe you were doing it in places that were totally unnecessary, but the point of asserts is to have less maintenance by catching errors before they become runtime errors which will take up a lot of debugging time.

You can go further with it, too. The original assert comes from C and is a runtime check. Even better than a runtime check is an automated unit testing that runs and tests the code for you, with every build or periodically, etc. How much error-checking code is worth writing depends on the project, but this kind of stuff is often mandatory on large professional projects.

I actually use BRK as a form of runtime assert in my project. ;) It's caught a number of bugs with a bluescreen of death I stuck in the IRQ handler.


Anyhow, in this particular case the .assert is actually a good suggestion. It's actually more important to put .align or .assert next to the actual sample definition in the code than it is to remember to align the segment. The align property in the segment is useless unless the code gets actually gets generated at the correct place!


Top
 Profile  
 
PostPosted: Sun Sep 25, 2016 10:53 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
rainwarrior wrote:
I think asserts are an essential language feature. I put them anywhere I think I might make a mistake. They don't often trigger, but when they do I'm very glad they're there. The point is to catch yourself when you make an error. It's easy to make mistakes. It's easy to accidentally put an extra byte in a segment. It's easy to accidentally leave out a comma somewhere. It's easy to accidentally type into your text editor when you think you're controlling your game. It's not paranoid to think these things might happen. They do!

I agree, and the little verification I left was precisely for these cases.

Quote:
I don't know what you were doing in your code, maybe you were doing it in places that were totally unnecessary

I was doing it excessively, like I was coding a library and users could screw up in the most grotesque ways when using it. But it wasn't a library, it was my own personal code and I wasn't going to make any grave mistakes using it... and if I did, it would be really obvious, it wouldn't go unnoticed. I agree with thefox that for libraries and such you do have to think of everything that could possibly go wrong, but being extremely anal about code you write for yourself might end up slowing you down and creating unnecessary bloat.

Quote:
but the point of asserts is to have less maintenance by catching errors before they become runtime errors which will take up a lot of debugging time.

Yes. The problems I had with maintenance was when things were still being changed a lot (back when I got started with ca65 and still wasn't sure what kind of framework I wanted to build for myself) and all the asserts and validations needed changing as well. They never triggered anyway, so I started feeling like I was just wasting my time adjusting them. Maybe it was premature to implement those validations so early on, but to be honest, even now I still make drastic changes occasionally, and refactoring small macros is still simpler than if I had to also go through tons of IFs and ASSERTs making sure they were still correct.

Quote:
I actually use BRK as a form of runtime assert in my project. ;) It's caught a number of bugs with a bluescreen of death I stuck in the IRQ handler.

That's interesting. I haven't felt the need for anything like that yet, but it's something to think about.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: Donqustix, Pokun and 11 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