Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

Nerdy Nights week 5 multiple sprites, reading controllers, more instructions

Mar 3, 2016 at 7:55:07 AM
thefox (0)
avatar
(Kalle Immonen) < Meka Chicken >
Posts: 533 - Joined: 07/08/2008
Finland
Profile
Another way of doing that is to make a 256-byte lookup table containing values 0..255, then you can do "CMP lut,Y" to compare A to Y. The same lookup table can be reused for various other things also.

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

Mar 3, 2016 at 10:10:43 PM
SomeGuy#27 (0)

< Cherub >
Posts: 3 - Joined: 12/01/2015
Profile
Okay, that shouldn't even add too much to my code, Vectrex! Thanks! The lookup table might be used if I need one for something else, but thanks anyways.

Apr 26, 2017 at 11:02:58 AM
Piputkin3 (0)
avatar
< Cherub >
Posts: 6 - Joined: 04/23/2017
Poland
Profile
I have a problem because when using BEQ, if the button is not pressed then this code is executed below

ButtonA:
LDA $4016
AND #%00000001
BEQ ButtonB
LDA $0210
CLC
ADC #$01
STA $0210
;Works regardless of the status of the button
ButtonB


Edited: 04/26/2017 at 11:03 AM by Piputkin3

Apr 26, 2017 at 11:10:58 AM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: Piputkin3

I have a problem because when using BEQ, if the button is not pressed then this code is executed below

ButtonA:
LDA $4016
AND #%00000001
BEQ ButtonB
LDA $0210
CLC
ADC #$01
STA $0210
;Works regardless of the status of the button
ButtonB
Last line needs a colon.

ButtonB:

 

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 26, 2017 at 11:21:49 AM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: Mega Mario Man
 
Originally posted by: Piputkin3

I have a problem because when using BEQ, if the button is not pressed then this code is executed below

ButtonA:
LDA $4016
AND #%00000001
BEQ ButtonB
LDA $0210
CLC
ADC #$01
STA $0210
;Works regardless of the status of the button
ButtonB
Last line needs a colon.

ButtonB:

 


Can you post your enitre Read Controller code for all buttons? I don't think this is giving me enough information.

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 26, 2017 at 11:28:54 AM
Piputkin3 (0)
avatar
< Cherub >
Posts: 6 - Joined: 04/23/2017
Poland
Profile
Here:
ButtonA:
LDA $4016
AND #%00000001
BEQ ButtonB
LDA $0210
CLC
ADC #$01
STA $0210
ButtonB:
LDA $4016
AND #%00000001
BNE SelectButton

SelectButton:
LDA $4016
AND #%00000001
BNE StartButton

StartButton:
LDA $4016
AND #%00000001
BNE UpButton

UpButton:
LDA $4016
AND #%00000001
BNE DownButton
LDA $0200
CMP #$DF
BEQ DownButton
LDA $0200
CLC
ADC #$01
STA $0200

DownButton:
LDA $4016
AND #%00000001
BNE LeftButton
LDA $0200
CMP #$00
BEQ LeftButton
LDA $0200
SEC
SBC #$01
STA $0200

LeftButton:
LDA $4016
AND #%00000001
BNE RightButton
LDA $0203
CMP #$F0
BEQ RightButton
LDA $0203
CLC
ADC #$01
STA $0203


RightButton:
LDA $4016
AND #%00000001
BNE NotRightButton
LDA $0203
CMP #$00
BEQ NotRightButton
LDA $0203
SEC
SBC #$01
STA $0203

NotRightButton:
JMP Here

Apr 26, 2017 at 12:08:31 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Do you have this before ButtonA:

LatchController:
LDA #$01
STA $4016
LDA #$00
STA $4016 ; tell both the controllers to latch buttons

All of those BNEs need to be BEQs on buttons B, Select, Start, Up, Down, Left, Right. Button A looks correct.

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 26, 2017 at 12:23:28 PM
Piputkin3 (0)
avatar
< Cherub >
Posts: 6 - Joined: 04/23/2017
Poland
Profile
I had a latch controller.
But I did't know that everywhere had to be BEQ. Thank you very much for your help.

Apr 26, 2017 at 12:40:41 PM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: Piputkin3

I had a latch controller.
But I did't know that everywhere had to be BEQ. Thank you very much for your help.
Yup.

We only care about Bit 0 of $4016. Every time you read $4016 (LDA $4016), it automatically jumps to the next button. If that button is pressed, $4016 will be equal to %00000001. If the button is not pressed, it will be equal to %00000000. This is why we do the AND %00000001. We only check if the Bit 0 is equal to 1.

So, if the button is pressed, this it what will happen:
LDA $4016                ;$4016=%00000001 because the button is pressed.
AND #%00000001      ; ANDing $4016 and %00000001 = %00000001
                               ;whenever there is no CMP before a Branch, then CPU sees it as CMP #$00 (compare to #$00 or #%00000000)
BEQ NextButton          ;Jump to Next Button if Equal to %00000000. In this case, it is not equal because our value is #%00000000, so we continue to the Run Code.
       ;Run Code
NextButton:

To move on the next button, we simply just read LDA $4016 again. Do this until you have read all 8 buttons on the controller.

 

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Dec 29, 2017 at 1:49:24 AM
think1st (0)

(asdf asdf) < Cherub >
Posts: 2 - Joined: 12/28/2017
Alabama
Profile
Hi, first post here.

Can you store things in CPU ram using .org and .db directives? Like placing the sprite data directly in ram.

.org $0200
.db #128,#0,#0,#128
.db #128,#1,#0,#136

etc.?

On that note, I notice I'm a bit confused how the assemblers decides where to put stuff in memory when you use .org. Is the address you hand to .org relative to the current .bank you're working on? Otherwise, the way mario.chr is included looks like you're writing the first 8 KB of CPU memory, including mirrored sections of RAM (since the code does .org $0000 followed by include). On the other hand, the entire previous code section looks as if its absolutely addressing all of the 64kb memory space the CPU has, even though the PRG ROM is only 16kb if you specify .inesprg 1. If I understand correctly, .bank 1 should be the second 8kb memory block from PRG ROM so for example all code I would expect to be .org-ed to $2000 instead of $C000 like it is at the top of the file.

Also, how does the assembler know that .bank 2 belongs to PPU memory? I guess NESDEV just knows that you're targeting NES, but how do you handle stuff like that with a more generic assembler like ca65 or asm6?

Hope I'm not dumping too many questions.

Dec 29, 2017 at 3:58:16 AM
think1st (0)

(asdf asdf) < Cherub >
Posts: 2 - Joined: 12/28/2017
Alabama
Profile
I found the answer. Seems the INES file format only contains ROM data, so the answer to my first question would be a simple NO. And after some experimentation with some other assemblers I figured that out, too. The assemblers don't care what goes to the PPU and what not, they just output the raw data as you define it using .org statements. Then, when the assembled .nes file is 16 bytes (header) + 16kb (1x prg rom) + 8kb (1x chr rom), the emulator is actually responsible for realizing that the first 16kb after header is for prg rom and the 8kb after is for chr rom.

Dec 29, 2017 at 8:28:00 AM
Mega Mario Man (63)
avatar
(Tim ) < Ridley Wrangler >
Posts: 2743 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: think1st

I found the answer. Seems the INES file format only contains ROM data, so the answer to my first question would be a simple NO. And after some experimentation with some other assemblers I figured that out, too. The assemblers don't care what goes to the PPU and what not, they just output the raw data as you define it using .org statements. Then, when the assembled .nes file is 16 bytes (header) + 16kb (1x prg rom) + 8kb (1x chr rom), the emulator is actually responsible for realizing that the first 16kb after header is for prg rom and the 8kb after is for chr rom.
I know you found the answers, but I just wanted to assure you.

No, .db cannot be used in RAM. You can only use .db to build tables in ROM.

The address you associate with the .org directive is relative to the bank you are in. That's how bank switching works. Small example from my code. Whatever bankSource I am current using, the CPU will use the proper code from that address. This is all PRG Data as I program in UNROM, so I don't use CHRROM. I have 15 banks that look like this below that can swap out $8000-$BFFF and 1 fixed bank that never swaps out in addresses $C000-$FFFF. Essentially, the concept is the same with CHR Data as well, that's why the Mario.chr is in $0000 at that the start of CHRROM. This confused me for the longest time as well. Just remember, you have PRGROM and CHRROM in NROM, so you have 2 sets of addresses to deal with.

;----------------------------------------------------------
;-----------------------BANKS------------------------------
;----------------------------------------------------------
;;;;;;;;;;;;;;;;;bankSource=00;;;;;;;;;;;;;;;;;;;;
  .bank 0        
  .org $8000  
  .include "maincode2.asm"
    
  .bank 1
  .org $A000
  .include "maincode3.asm"     

;;;;;;;;;;;;;;;;;bankSource=01;;;;;;;;;;;;;;;;;;;;
  .bank 2    
  .org $8000
    .include "SpriteData.asm"
    
  .bank 3
  .org $A000
 
;;;;;;;;;;;;;;;;;bankSource=02;;;;;;;;;;;;;;;;;;;;  
  .bank 4                                                
  .org $8000
TitleGraphics:  
  .incbin "CHRfiles\titlesprites.chr"
  .incbin "CHRfiles\titlegraphics.chr"
 
  .bank 5
  .org $A000
RoomGraphics:
  .incbin "CHRfiles\MainCharacterSprites.chr"
  .incbin "CHRfiles\RoomGraphics.chr"

 

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Dec 29, 2017 at 8:52:32 AM
GradualGames (39)
avatar
(Derek Andrews) < El Ripper >
Posts: 1128 - Joined: 10/09/2009
Pennsylvania
Profile
I'd add that, basically the way an assembler works under the hood is it has a variable called the "program counter." This is not the same thing as the pc or program counter in the cpu while running your game---this concept I'm about to describe is only for the assembler.

It basically starts at 0, but if you say .org $8000, that will effectively set the assembler's program counter to that value. Then, if you do some .db's

.org $8000
some_data:
.db 1, 2, 3

more_data:
.db 1, 2, 3

Each byte output to your rom will increment the program counter by 1. When the assembler sees "more_data", the program counter will now be $8003. So if you use the address "more_data" somewhere in your code, it'll know to use the address $8003.

The program counter does the same thing in ram, only you are not outputting any data, you're just reserving space. So you go:

.org $0000 ;or it might actually be .rsset in nesasm. every assembler has small differences with these commands. but it's still going to affect the program counter as the assembler creates your rom file. In the case of variables, nothing gets output, it's just counting using how many bytes you're reserving, so when you use "variable1" or "variable2" etc. in your code, it knows the right address to use.
variable1:
.ds 1

;program counter is now at $0001
variable2:
.ds 2

;program counter is now at $0003
variable3:

 

-------------------------
Creators of: Nomolos: Storming the CATsle, and The Legends of Owlia.


Edited: 12/29/2017 at 09:00 AM by GradualGames