Skip navigation
Welcome, Guest! Please Login or Join

Loading...

Nerdy Nights week 3 6502 ASM, first app

Dec 29, 2011 at 5:51:50 PM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
Line 2: Because it can still be triggered and will do bad things if your program is set up. You never do not initialize registers and just leave them what they are, you need the computer in a known state. Plus, on mappers that do have it, you have to do it anyway so nothing changes when moving to a better mapper.

Line 3: Yep, it doesn't have it because it's disabled. 

Line 4/5: On $4016 write it resets both controllers. On 4016 read and 4017 read it reads the controllers. On 4017 writes it write to the APU, registers don't exist in both states (read and write) all the time, they sometimes change "meaning" completely. 4017 is one of those registers that changes on reads and writes.

Line 9/10/11: It's when sound is playing samples. If they are playing you want to disable the sound and the acknowledging program.


Edited: 12/29/2011 at 05:54 PM by removed04092017

Dec 29, 2011 at 7:42:01 PM
thefox (0)
avatar
(Kalle Immonen) < Meka Chicken >
Posts: 532 - Joined: 07/08/2008
Finland
Profile
02: It's good practice to initialize everything to a known state in the beginning of the program.
03: Technically this isn't required on the NES CPU, but it's still a good practice to have it.
04-05: $4017 is connected to the APU when it's being written. I won't go into details about $40, but long story short it sets on bit in the APU register 4017 that makes sure frame IRQs won't happen
06-07: $FF (the actual memory location is $1FF) is actually the first location, because stack grows from top ($1FF) to bottom ($100). So when a value gets pushed, the stack pointer gets decreased.
08: That's right.
11: Once again, it's good practice to initialize everything to a known state, even though IRQs won't be actually triggered regardless because of the SEI instruction on line 2.
12-14: vblankwait1 is a label, BIT $2002 (in this case) copies the top bit of value read from $2002 to CPU's sign flag (plus/minus). This happens to be the bit that indicates whether vblank has started. BPL vblankwait1 jumps back to the label if the result is positive, in other words if the top bit of the value read from $2002 was 0.

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

Jan 1, 2012 at 8:02:07 AM
DoNotWant (1)

(Ham Sammich) < Eggplant Wizard >
Posts: 440 - Joined: 12/08/2011
Sweden
Profile
Ok, thanks guys! And thanks for the tutorials, will probably get through week 5 tonight.

-------------------------
 

Feb 12, 2012 at 7:35:49 PM
glenn101 (0)
avatar
(Glenn Kirilov) < Tourian Tourist >
Posts: 37 - Joined: 02/11/2012
Victoria
Profile
I'm just wondering is .bank2 always used for graphics storage via the PPU?
How does it know to access $0000 of PPU memory and not $0000 of CPU memory?

Also why is STA $0000, x used continuously inside the clrmem: label? isn't the contents of register X at this point 0 and hence doesn't modify the address accessed?

*Edit*
I know the answers to my questions now.


Edited: 02/16/2012 at 08:51 PM by glenn101

Oct 16, 2012 at 8:47:04 AM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
I have been doing my best to understand banking; however, I am still a little unclear about why explicitly specifying it is necessary. Here is my understanding and questions, let me know where I am messing up...

1. A bank is portion of memory that is set aside as a holding place for some kind of data (like CHR or PRG)
2. For the NESASM, banks occupy a space of 8KB
3. The .bank directive does what exactly? Couldn't you just get by using a .org directive to navigate to the portions of memory where CHR/PRG data is intended to be stored? Why do you have to specify the .bank?
4. How are you supposed to know if your PRG memory exceeds a 8KB bank? What would happen if it does?
5. Are all directives handled pre-assembling? Almost like C++ pre-processor directives?

Thanks,
Jarrod

Oct 16, 2012 at 11:06:16 AM
thefox (0)
avatar
(Kalle Immonen) < Meka Chicken >
Posts: 532 - Joined: 07/08/2008
Finland
Profile
Originally posted by: jarrodparkes

I have been doing my best to understand banking; however, I am still a little unclear about why explicitly specifying it is necessary. Here is my understanding and questions, let me know where I am messing up...

1. A bank is portion of memory that is set aside as a holding place for some kind of data (like CHR or PRG)
2. For the NESASM, banks occupy a space of 8KB
3. The .bank directive does what exactly? Couldn't you just get by using a .org directive to navigate to the portions of memory where CHR/PRG data is intended to be stored? Why do you have to specify the .bank?
4. How are you supposed to know if your PRG memory exceeds a 8KB bank? What would happen if it does?
5. Are all directives handled pre-assembling? Almost like C++ pre-processor directives?

Thanks,
Jarrod

1. Yes, "bank" can mean any arbitrary block of memory, depending on the context. NESASM bank is 8KB, MMC1 bank can be 16KB or 32KB, UxROM bank is 16KB, MMC3 uses 8KB banks, NSF uses 4KB banks, and so on.
2. Yes, this is an arbitrary restriction stemming from the fact that it was originally an assembler for the PC Engine/TurboGrafx-16, which has native support for 8KB banking.
3. It specifies the 8KB multiple of where the data should go in the output file. And yes, other assemblers use .org (and some other directives to reset the address, etc) or some other method (linker memory configuration file in CA65) for the same purpose.
4. The assembler is supposed to tell you. NESASM has bugs in it so it sometimes doesn't, and will overwrite the beginning of the bank instead.
5. Yes.


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

Oct 16, 2012 at 1:14:15 PM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
Thanks for the help. I have another question, and maybe this example will help...

Here is what the documentation (http://www.nespowerpak.com/nesasm...) says about BANK:
BANK - Select a 8KB ROM bank (0-127) and reset the location counter to the latest known position in this bank.

EXAMPLE ASM FILE:

; some header info...

.bank 0
.org $8000
SEI ; will each command after the .bank and .org be offset from memory location $8000 ?
{ ... } ; more opcodes

.bank 1
.org $FFFA
{ ... } ; commands to set NMI, IRQ, and RESET vectors...

.bank 0 ; does re-using this directive now set the location counter to where we left off in bank 0 ?



Edited: 10/16/2012 at 01:17 PM by jarrodparkes

Mar 13, 2013 at 9:10:14 AM
DamienC666 (15)
avatar
(Damien Cappello) < Little Mac >
Posts: 87 - Joined: 04/27/2010
New Jersey
Profile
Sorry to dig this up, but I had a question about the "clrmem" routine. I got everything to compile and run just fine.

I get why we're writing $00 to pages 0-7 of memory, but why are we writing $FE to page 3? Specifically, I don't get:

clrmem:
       LDA #$00
       STA $0000, x
       STA $0100, x
       STA $0200, x
       STA $0400, x
       STA $0500, x
       STA $0600, x
       STA $0700, x
       LDA #$FE               <------------- These two lines
       STA $0300, x          <----/
      INX
           BNE clrmem

Just trying to understand every part of the code before moving on.

-------------------------
  -Damien C.
 

Mar 13, 2013 at 11:08:22 AM
thefox (0)
avatar
(Kalle Immonen) < Meka Chicken >
Posts: 532 - Joined: 07/08/2008
Finland
Profile
Originally posted by: DamienC666

Sorry to dig this up, but I had a question about the "clrmem" routine. I got everything to compile and run just fine.

I get why we're writing $00 to pages 0-7 of memory, but why are we writing $FE to page 3? Specifically, I don't get:

clrmem:
       LDA #$00
       STA $0000, x
       STA $0100, x
       STA $0200, x
       STA $0400, x
       STA $0500, x
       STA $0600, x
       STA $0700, x
       LDA #$FE               <------------- These two lines
       STA $0300, x          <----/
      INX
           BNE clrmem

Just trying to understand every part of the code before moving on.
The code assumes that $300-$3FF is used for shadow OAM (that is copied to the real OAM later with OAM DMA, PPU register $4014). Initializing OAM to $FE causes all sprite Y positions to be 254, placing the sprites offscreen. Alternatively any other value between 239..255 ($EF..$FF) could be used to the same effect.

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

Mar 13, 2013 at 11:21:19 AM
DamienC666 (15)
avatar
(Damien Cappello) < Little Mac >
Posts: 87 - Joined: 04/27/2010
New Jersey
Profile
Originally posted by: thefox

The code assumes that $300-$3FF is used for shadow OAM (that is copied to the real OAM later with OAM DMA, PPU register $4014). Initializing OAM to $FE causes all sprite Y positions to be 254, placing the sprites offscreen. Alternatively any other value between 239..255 ($EF..$FF) could be used to the same effect.

I gotcha, that makes perfect sense. All these mirrored sections of memory kind of throw me off a bit.

Thanks.

-------------------------
  -Damien C.
 

Jun 24, 2013 at 7:54:23 PM
HiQConsoul (0)

< Cherub >
Posts: 3 - Joined: 06/21/2013
Profile
LDA #$0A   ; LoaD the value 0A into the accumulator A
           ; the number part of the opcode can be a value or an address
           ; if the value is zero, the zero flag will be set.

LDY #$FF ; LoaD the value $FF into the index register Y ; if the value is zero, the zero flag will be set.

*** Im pretty nubby at this..
ok so... can u see my question forming?

above, lda and ldy have a #$ before the hex value ..

lda #$22 would seem to load 22 into a ...
(rephrase.. lda #$22 LoaD into A the value 22)
ldy #$22 would seem to load $22 into y ...
(rephrase.. ldy #$22 LoaD into Y the value $22)

.. why does y get the $ before 22, and why does a not get the $ before 22?

a and y are different thingies and work differently, it could be something like that I guess - but the way things are worded I also seem to think it may just as well be a typo from author altho probability is low cuz it's so old, yet it seems most who check it out are fairly skilled and thus just shrug at it if even noticing it.. and nubs like myself may just think "it's just me who's a nub".. so, I feel I should ask..

cheers

edit:

at the bottom it shows the 76543210 bits with lines to what they do.. after that it says:
"So if you want to enable the sprites, you set bit 3 to 1."

I just rechecked like 5 times and Im sure bit 3 on the 'drawing' is pointing to the background and bit 4 to the 'enable rendering sprites' .. so, basically same question: Am I just nub and will find out why it's right, or is it like.. typo ?

-------------------------
after seeing assembly + hex + f0 stuff, f-zero has taken on whole new dimension of awesome
f-zero is king of games cuz cant make awesome game without f0 !


Edited: 06/24/2013 at 08:01 PM by HiQConsoul

Jun 24, 2013 at 8:24:08 PM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
LDA and LDY work the same with the same right side, just different registers.

LDA #$22 puts #$22 ($22 is a memory location, NOT the number, big difference.) to A.

LDY #$22 puts #$22 to Y.

That's basically it. I don't understand your problem, as it just does what the text says. If it says #22, it gets decimal 22 loaded. If it says #$, it's hex, if it says #%, it's binary.

Jun 24, 2013 at 10:42:24 PM
MODERATOR
KHAN Games (88)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 7758 - Joined: 06/21/2007
Florida
Profile
I think he's getting confused by the notes on the side. He just forgot to put #$ before 0A.

Oct 12, 2013 at 8:40:31 AM
MODERATOR
Vectrex28 (120)
avatar
(A Metroid) < Bowser >
Posts: 7141 - Joined: 07/28/2012
Switzerland
Profile
Three questions:
1.What's so special about #$40?
2.What is up with
STA $0000, x
STA $0100, x
STA $0200, x
STA $0400, x
STA $0500, x
STA $0600, x
STA $0700, x
LDA #$FE
STA $0300, x
I know it's about loading the value in the accumulator (#$00) to these addresses, but why do we have to do it?
3.Why do we have to set up stack with TXS (which here means transfering hex value FF to register S) in the beginning?
Thanks


Edited: 10/12/2013 at 08:41 AM by Vectrex28

Oct 12, 2013 at 9:13:02 AM
NESHomebrew (20)
avatar
(Brad Bateman - Strange Brew Games) < King Solomon >
Posts: 4200 - Joined: 04/28/2008
Saskatchewan
Profile
All these answers exist in this thread already.

Oct 12, 2013 at 9:42:04 AM
MODERATOR
Vectrex28 (120)
avatar
(A Metroid) < Bowser >
Posts: 7141 - Joined: 07/28/2012
Switzerland
Profile
I still don't understand question 3, and I still don't know why we have to do this

STA $0000, x
STA $0100, x
STA $0200, x
STA $0400, x
STA $0500, x
STA $0600, x
STA $0700, x

Oct 12, 2013 at 12:43:37 PM
DoNotWant (1)

(Ham Sammich) < Eggplant Wizard >
Posts: 440 - Joined: 12/08/2011
Sweden
Profile
You don't have to reset the RAM, some even say it's bad.

S is the Stack pointer. The stack always resides in page 1, so RAM addresses $0100-$01FF. The value
you transfer with TXS tells you where in page 1 the stack pointer will point to.

-------------------------
 

Oct 12, 2013 at 1:26:43 PM
Shiru (0)

(Shiru Shiru) < Meka Chicken >
Posts: 677 - Joined: 06/08/2011
Russian Federation
Profile
Setting up stack pointer is not really needed if you don't plan to use the stack page ($100..1ff) for anything else. But if you place something else there, you have to set up stack pointer to be sure the stack is always in the same place and does not overlap your other data.

Sep 30, 2014 at 7:26:58 PM
Jazzmarazz (1)
avatar
(Jordan Appleton-Joslin) < Eggplant Wizard >
Posts: 471 - Joined: 06/23/2014
Michigan
Profile
Found a tiny typo:

"Accumulator
The Accumulator (A) is the main 8 bit register for loading, storing, comparing, and doing math on data. Some of the most frequent operations are:
LDA #$FF ;load the hex value $FF (decimal 256) into A
STA $0000 ;store the accumulator into memory location $0000, internal RAM"

It should read decimal 255, not 265. great TUT so far.

-------------------------

Sep 15, 2015 at 4:58:26 PM
Cockroachcharlie (0)
avatar
< Cherub >
Posts: 19 - Joined: 09/05/2015
Pennsylvania
Profile
Ok. I think I have figured out where my major roadblock is on 6502 design. I am going to write an excerpt in BASIC (we should all recognize this one)

10: Print "Hello World"

20 Goto 10

It's obvious here why the words "Hello World" appear on the screen. The command "Print" told them to. I think that's where I am running into trouble here. In 6502 all I am STILL seeing is storing numbers in memory locations (after various tutorials and two books), but I am not understanding how all this number movement adds up to telling the processor to print "Hello World" to the screen. From this weeks tutorial

LDA %10000000 ;intensify blues

STA $2001

I don't get how that storage is any different than storing at any other location, yet produces a different result. Can somebody explain what I am missing here or guide me to a place that would help me wrap my head around this part. I am actually becoming pretty educated in assembly, but still fail to see how to APPLY all of it to produce an intended result other than moving numbers around.


Edited: 09/15/2015 at 04:59 PM by Cockroachcharlie

Sep 15, 2015 at 6:17:41 PM
dra600n (287)
avatar
(Adym \m/) < Bonk >
Posts: 15796 - Joined: 09/16/2010
Connecticut
Profile
Originally posted by: Cockroachcharlie

Ok. I think I have figured out where my major roadblock is on 6502 design. I am going to write an excerpt in BASIC (we should all recognize this one)

10: Print "Hello World"

20 Goto 10

It's obvious here why the words "Hello World" appear on the screen. The command "Print" told them to. I think that's where I am running into trouble here. In 6502 all I am STILL seeing is storing numbers in memory locations (after various tutorials and two books), but I am not understanding how all this number movement adds up to telling the processor to print "Hello World" to the screen. From this weeks tutorial

LDA %10000000 ;intensify blues

STA $2001

I don't get how that storage is any different than storing at any other location, yet produces a different result. Can somebody explain what I am missing here or guide me to a place that would help me wrap my head around this part. I am actually becoming pretty educated in assembly, but still fail to see how to APPLY all of it to produce an intended result other than moving numbers around.

Different parts of RAM are utilized by the hardware, which use those values to control their inputs/outputs. 
 

-------------------------
Proud owner of post #1800 in Inner Circle HQ thread

Sep 15, 2015 at 6:17:45 PM
MODERATOR
KHAN Games (88)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 7758 - Joined: 06/21/2007
Florida
Profile
http://wiki.nesdev.com/w/index.ph...

As you can see from this wiki, the $2001 address is the address where the color emphasis is located.

If you wanted to write actual text on the screen, as in HELLO WORLD, (assuming you were writing to the background, and not using sprites), first you would load $2002 to get the PPU ready, and then you would be using the $2006/$2007 registers to tell it where the text goes, and what background tiles contain those letters.

You'll find out that you are basically using the same registers all the time when it comes to the NES.  Some for sprites, some for background, etc.


Edited: 09/15/2015 at 06:18 PM by KHAN Games

Sep 15, 2015 at 6:24:35 PM
Cockroachcharlie (0)
avatar
< Cherub >
Posts: 19 - Joined: 09/05/2015
Pennsylvania
Profile
LOL. Man. I can see why people wanted to simplify it. Assembly is seriously a lot different than anything I have ever worked with so far. Again. It's just hard to grasp how number transferring produces these results. Almost like trying to visualize in pure binary. So now that I have the actual coding a little more in place, I should probably work more on the architecture and the specifics of memory locations?

Sep 15, 2015 at 6:27:38 PM
Lincoln (133)
avatar
(Frank W. Doom) < Bowser >
Posts: 5571 - Joined: 12/19/2008
California
Profile
Originally posted by: Cockroachcharlie

Ok. I think I have figured out where my major roadblock is on 6502 design. I am going to write an excerpt in BASIC (we should all recognize this one)

10: Print "Hello World"

20 Goto 10

It's obvious here why the words "Hello World" appear on the screen. The command "Print" told them to. I think that's where I am running into trouble here. In 6502 all I am STILL seeing is storing numbers in memory locations (after various tutorials and two books), but I am not understanding how all this number movement adds up to telling the processor to print "Hello World" to the screen. From this weeks tutorial

LDA %10000000 ;intensify blues

STA $2001

I don't get how that storage is any different than storing at any other location, yet produces a different result. Can somebody explain what I am missing here or guide me to a place that would help me wrap my head around this part. I am actually becoming pretty educated in assembly, but still fail to see how to APPLY all of it to produce an intended result other than moving numbers around.


on the NES, $2001 isn't really storage- it's like a set of switches the system provides you to interact with the graphics system. flipping the first switch does blue intensity, second switch is red, third is green (or vice versa on those last two), and whatever else the other 5 bits control. there are several addresses like this in the $2000 range that affect ppu activities, and there are more in the $4000 range that handle controller communication and audio, etc. 

I still don't know how to put hello world on the screen though. someone else can explain that.

-------------------------
ebay auctionsrunning FS thread famiROM updates and download thread for .nes info and splitting

Sep 15, 2015 at 6:47:49 PM
MODERATOR
Vectrex28 (120)
avatar
(A Metroid) < Bowser >
Posts: 7141 - Joined: 07/28/2012
Switzerland
Profile
Originally posted by: Cockroachcharlie

LOL. Man. I can see why people wanted to simplify it. Assembly is seriously a lot different than anything I have ever worked with so far. Again. It's just hard to grasp how number transferring produces these results. Almost like trying to visualize in pure binary. So now that I have the actual coding a little more in place, I should probably work more on the architecture and the specifics of memory locations?

You'll get used to the registers, there aren't too many so you'll get a good grasp on how they work the more you program.

Also, here's how I would do a "Hello World" program if you're interested (Basically what KHAN said in code form). It's covered in a later tutorial, because even simple things like that need to have you understand the registers and what they do.

  
  LDA $2002       ;wake up PPU
  LDA #$22
  STA $2006       ;Write the hi part of the starting address to $2006
  LDA #$00
  STA $2006       ;and the second part.
  LDX #$00
.hwloop
  LDA helloworld,x       ;Draws h, e, l, l, o, etc. on the background with $2007
  STA $2007
  INX                    ;x register makes the writing possible
  CPX #$0B               ;Do it 11 times
  BNE .hwloop

helloworld:
  .db $11,$0E,$15,$15,$18,$2F,$20,$18,$1B,$14,$0D
                                                              ;The CHR goes like that.______0123456789ABCDEF
                                                              ;That's just my way of using__GHIJKLMNOPQRSTUV
                                                              ;using fonts on the CHR tho.__WXYZ.,-!?©:;'() 

 


Edited: 09/15/2015 at 06:50 PM by Vectrex28