8x16 and whatever else unreg wants to know

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tokumaru wrote:
unregistered wrote:Honestly, I made the mistake of just looking at the .lst file and it showed the values written to $6000 just like it always shows the values written to ROM.
Yeah, the listing will show $6000 because you told the assembler that the PC for that part was $6000, but that doesn't mean the code will actually end up at $6000.

Contrary to what may seem at first, commands like .org and .base don't force data into a particular address, they just let the assembler know where the code will be loaded so that labels and stuff have the correct values during execution.

NES programs don't start with .org $8000 because that causes the code to be put at $8000. The code will be loaded into $8000 no matter what, even if you write .org $3A9B instead, but all the labels will be wrong and the program won't function correctly.

EDIT: BTW, I said that .base wasn't doing anything in the code you posted, but now that I think of it, it's probably causing your ROM to be 256 bytes longer than it should, making it invalid. I believe that's the case because later you reset the PC to the value it had before the table, so the table is inserted into the ROM but the space it takes is not taken into consideration by the assembler since you manipulated the PC for that part.

Thank you so much tokumaru; that is extremely helpful to learn. :D

Returned early in the morning because I wanted to say that the code has been moved into its own file and I placed the .incsrcs at the top of each bank so that there wouldn't be 240 bytes of nothing between the end of that code I posted above (the beginning of page $BF) and the start of -reset_stub. And I also wanted to say that while laying in my bed I remembered this very helpful post where booker did a superb job of helping me to grasp the RAM/ROM issue that you, tokumaru, explained to me again.

edit: tokumaru, here is where you recommended me to use -reset_stub. If you scroll up there is the code found on the nesdev wiki, a link to that page, and some conversation about the problem I was having. This is linked here to help y'all to fully understand this post. I'm sure the linked post can't be found using this fourm's search function because it refuses to search through old (2012) posts. Hope you see this edit. :)


edit2 20171006: thought it would be good to say that the code I mentioned "posted above" was reduced to

Code: Select all

.rept 256
  .db <$
.endr
because the beginning of the first 15 banks in our game always start at $8000
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

this page wrote:CLV clears V. Simple enough. It is most frequently used in conjunction with a BVC to simulate a forced branch (a.k.a a branch always) in relocatable routines.
What is a relocatable routine? jmp is 3 bytes big and takes 3 cycles, while clv bvc + is 3 bytes big and takes 4 cycles, I think (if it doesn't branch to different page). So a relocatable routine must be pretty useful? :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:What is a relocatable routine? jmp is 3 bytes big and takes 3 cycles, while clv bvc + is 3 bytes big and takes 4 cycles, I think (if it doesn't branch to different page). So a relocatable routine must be pretty useful? :)
A relocatable routine is one that doesn't use hardcoded/absolute addresses (this rules out JMP), so it can be placed anywhere in memory.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

Are macros relocateable routines then? I'm using a jmp +endmR inside a macro and I guess that works because + and - lables can be repeated. :) (It only takes 3 cycles! :D )
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 and whatever else unreg wants to know

Post by tepples »

Macros are inlined routines. If a macro contains a self-reference with absolute addressing mode, the subroutine it is used in is not relocatable. An example of a macro with such a self-reference is a macro for generating a bus-conflict-compliant bank switch:

Code: Select all

.macro set_imm_bank value
  lda #value
  sta *-1  ; overwrite the instruction byte with itself
.endmacro
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:Are macros relocateable routines then?
No, macros are just a convenience for programmers so they don't have to type common sequences of commands over and over. Each time you use a macro, the code it contains is written to the ROM in full, and any labels defined inside it will be absolute for the specific place where you used the macro.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tepples wrote:Macros are inlined routines. If a macro contains a self-reference with absolute addressing mode, the subroutine it is used in is not relocatable. An example of a macro with such a self-reference is a macro for generating a bus-conflict-compliant bank switch:

Code: Select all

.macro set_imm_bank value
  lda #value
  sta *-1  ; overwrite the instruction byte with itself
.endmacro
Thanks tepples, I didn't know the word 'inline'. :oops: And would your code, in asm6, be:

Code: Select all

.macro set_imm_bank value
  lda #value
  sta $-1 ;overwrite the instruction byte with itself
.endm
? After searching asm6's README.TXT there was only one * character so I don't know what the * symbol means. If it should be '$' that would overwrite the third byte of the macro, how would this macro switch banks? :?

tokumaru, thanks, I guess I should search the wiki for 'relocatable routine'... I can't grasp why or how a relocatable routine would work. :oops: edit: the wiki doesn't contain "relocatable code"
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:And would your code, in asm6, be:
Yes, $ in ASM6 is the equivalent of * in ca65. It translates to the current value of the program counter. For example, this:

Code: Select all

  .org $8000
  .db $00
  .dw $
Assembles into:

Code: Select all

$00, $01, $80
If it should be '$' that would overwrite the third byte of the macro, how would this macro switch banks? :?
Nothing gets overwritten, because it's ROM. Several discrete logic mappers (U*ROM, A*ROM, and many others) switch banks on writes to PRG-ROM, and to avoid bus conflicts, the ROM location being written to must contain the same value that's being written. Using $-1 is just a clever way to address such a location, since the argument for the instruction that loaded the value into the accumulator is stored at that address.
tokumaru, thanks, I guess I should search the wiki for 'relocatable routine'... I can't grasp why or how a relocatable routine would or should work. :oops:
Don't worry about relocatable code, it's very unlikely that you'll ever need it for NES development. I can't think of any scenario where it would be useful in NES games.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

After thinking about your words for a long while: Ahha! The program counter must, after each instruction, increase by the number of bytes of the previous instruction. So if the code was:

Code: Select all

.macro set_imm_bank value
  lda #value
  sta $-1
.endm

.pad $c100
set_imm_bank 3
It would try to assemble to some rom with A5 03 85 03 at $c100, because the PC started at $C100, the first instruction was assembled, the PC increased by 2... $C100 + 2 = $C102, and then the second instruction is assembled with a 03 at $C103 because the PC, $C102, -1 ($C101) holds 03, and then the PC increases to $C104. Right? :D

MMC1 isn't one of those discrete mappers right? It takes a lot of code to switch banks on MMC1, I believe.

Thank you so much tokumaru!! :D :mrgreen: I won't worry about relocatable code. :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

You got some of that right. If I'm not mistaken, the assembled binary at $c100 would actually be A9 03 8D 01 C1. LDA immediate is $A9, followed by an 8-bit value, while STA absolute is $8D, followed by a 16-bit address (low byte first).
unregistered wrote:MMC1 isn't one of those discrete mappers right?
No, and it's not subject to bus conflicts, so there's no need for the whole "write value to a location that contains the same value" thing.
It takes a lot of code to switch banks on MMC1, I believe.
I personally think the MMC1 is one of the worst mappers ever created... it's so awkward and slow to write to, and offers little advantage over the common discrete logic mappers. The CHR switching sucks (4KB banks, really? If you can only change ALL sprite or ALL background tiles at once, that pretty much means it can only be done on screen transitions, so you might as well use CHR-RAM and have the freedom to mix and match tiles or even animate them during gameplay), the mirroring switch is hardly useful (you can code even 8-way scrolling with hardwired mirroring if you know what you're doing, and that's more versatile than 4-way scrolling), and the battery-backed PRG-RAM can be added to any cartridge with just a few discrete components.

If discrete logic mappers aren't enough for a project I'm working on, I'd rather make the jump to MMC3-level mappers than working with that abomination that's the MMC1.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 and whatever else unreg wants to know

Post by tepples »

I get the impression from "Why Your Game Paks Never Forget", an article in the third year of Nintendo Power, that Nintendo wanted to save pins, presumably to reduce PCB space and soldering time. The article compares "Logic Gates" to a buffet dinner and Memory Management Controllers (MMCs) to skipping to dessert.
  • UNROM + WRAM is three narrow DIPs: a 74161 (16 pins), a 7432 (14 pins), and a 7420 (14 pins). That's a total of 44 pins to solder down.
  • MMC1 is a 24-pin shrink DIP.
  • A hypothetical parallel MMC1 would need 27 pins, replacing the CPU D7 connection with D4-D1.
The 4K mode of MMC1 lets you do CHR rotation on the background but not on the sprites. Or if the background doesn't use all 256 tiles, it lets you stash some level-specific 8x16 sprites in the background side of the pattern table. while keeping the general sprites in the sprite side.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: 8x16 and whatever else unreg wants to know

Post by lidnariq »

tepples wrote:A hypothetical parallel MMC1 would need 27 pins, replacing the CPU D7 connection with D4-D1.
And we'd call it the VRC1.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tokumaru wrote:You got some of that right. If I'm not mistaken, the assembled binary at $c100 would actually be A9 03 8D 01 C1. LDA immediate is $A9, followed by an 8-bit value, while STA absolute is $8D, followed by a 16-bit address (low byte first).
Oh, another mistake on my part. Sorry. :( A9 03 8D 03 C1 would be correct? (I don't understand why $c103 would be #$01 :oops: )
tokumaru wrote:
unregistered wrote:MMC1 isn't one of those discrete mappers right?
No, and it's not subject to bus conflicts, so there's no need for the whole "write value to a location that contains the same value" thing.
It takes a lot of code to switch banks on MMC1, I believe.
I personally think the MMC1 is one of the worst mappers ever created... it's so awkward and slow to write to, and offers little advantage over the common discrete logic mappers. The CHR switching sucks (4KB banks, really? If you can only change ALL sprite or ALL background tiles at once, that pretty much means it can only be done on screen transitions, so you might as well use CHR-RAM and have the freedom to mix and match tiles or even animate them during gameplay), the mirroring switch is hardly useful (you can code even 8-way scrolling with hardwired mirroring if you know what you're doing, and that's more versatile than 4-way scrolling), and the battery-backed PRG-RAM can be added to any cartridge with just a few discrete components.

If discrete logic mappers aren't enough for a project I'm working on, I'd rather make the jump to MMC3-level mappers than working with that abomination that's the MMC1.
Well, my sister has already designed our game's graphics knowing about the 4KB CHR banks so I think MMC1 will work just fine for us. :) Our game uses just 2-way scrolling, horrisontal. And it's not subject to bus conflicts! That's good to know, thank you tokumaru! :)


tepples, that's a lot of interesting info and I don't understand all the numbers and that's ok, your brain is tremendous! :D The MMC1 was efficently built; it isn't very user friendly, but it is great for our game. :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:
tokumaru wrote:You got some of that right. If I'm not mistaken, the assembled binary at $c100 would actually be A9 03 8D 01 C1. LDA immediate is $A9, followed by an 8-bit value, while STA absolute is $8D, followed by a 16-bit address (low byte first).
Oh, another mistake on my part. Sorry. :( A9 03 8D 03 C1 would be correct? (I don't understand why $c103 would be #$01 :oops: )
When you use $ or *, that translates to the PC value at the beginning of the current line, since the PC doesn't change until the instruction is output. Your example started at $c100. The first instruction, lda #3, uses 2 bytes, so the PC for the next line is $c102. So when you do sta $-1, $-1 evaluates to $c102-1, or $c101.
The MMC1 was efficently built; it isn't very user friendly, but it is great for our game. :)
I'm not against other people using the MMC1, it's just that I don't like it, mainly because of the time it takes to switch banks, since some of my engines have to do it dozens of time per frame.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tokumaru wrote: When you use $ or *, that translates to the PC value at the beginning of the current line, since the PC doesn't change until the instruction is output. Your example started at $c100. The first instruction, lda #3, uses 2 bytes, so the PC for the next line is $c102. So when you do sta $-1, $-1 evaluates to $c102-1, or $c101.
I agree, that makes sense. :oops: Thank you tokumaru.
tokumaru wrote:
The MMC1 was efficently built; it isn't very user friendly, but it is great for our game. :)
I'm not against other people using the MMC1, it's just that I don't like it, mainly because of the time it takes to switch banks, since some of my engines have to do it dozens of time per frame.
That's cool; I didn't even know that was possible. Sounds extravagant! :D We're only going to have to switch banks during a few of the levels when changing floors. So the longer bank switch time won't be too bad, I think. Changing floors takes like 2 frames so it definitly won't happen multiple times in one frame.

edit (@ ~11pm here): Was talking about switching prg banks... and maybe it will have to be done more often if we run out of room for prg code in our fixed prg bank #15. Chr banks will have to be switched every level change and for some other things. But, that's in-between levels so it should be ok. :)
Post Reply