Obligatory newbie questions

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

tepples
Posts: 22052
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Wed Jun 08, 2011 9:36 am

Bellum wrote:Hmm, not sure what segment does at all, actually. :P
Please see segments in ca65 Users Guide. If you don't understand something in that section, please ask.
I understand what say_hello does, but I don't understand why you store the numbers $21 and $CA in memory.
That's something you'll learn more about once you start to learn about the PPU. For now, suffice it to say that VRAM addresses are formed $2000 + $20*y + x, and $21CA represents (x=10, y=14).
So, for instance, I could say...

Code: Select all

astring				.byt "This is a string!"
						LDA astring,0				;loads astring[0] into a
No, that's a syntax error. You must use comma only for index registers (e.g. astring,x or astring,y); you can use + for constant offsets from the start of an array (e.g. astring+0 or astring+3).


thefox: In which version of ca65 was .charmap introduced?

User avatar
noattack
Posts: 147
Joined: Tue Feb 13, 2007 9:02 pm
Location: Richmond, VA
Contact:

Post by noattack » Wed Jun 08, 2011 10:12 am

Just to clarify what tepples said, you're actually feeding an address to the PPU one byte at a time via $2006.

Thus

Code: Select all

lda #$21
sta PPUADDR
lda #$08
sta PPUADDR
is saying, 'Hey PPU, I'm setting the VRAM address to $2108.' Then you loop data into that address via $2007.

See the relevant wiki section for reference:

http://wiki.nesdev.com/w/index.php/PPU_registers

The trickier part of learning the NES is not ASM, but how its registers are mapped to its various hardware components.

User avatar
tokumaru
Posts: 11859
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Wed Jun 08, 2011 10:15 am

noattack wrote:The trickier part of learning the NES is not ASM, but how its registers are mapped to its various hardware components.
Which is precisely why I said he should get more comfortable with the CPU before trying to mess with the PPU.

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Post by thefox » Wed Jun 08, 2011 10:16 am

tepples wrote:thefox: In which version of ca65 was .charmap introduced?
Not sure, but it's in the current release version. I remember using it 4 years ago. :)

3gengames
Formerly 65024U
Posts: 2277
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Wed Jun 08, 2011 10:36 am

tokumaru wrote:
3gengames wrote:To find NESASM3, just google it.
The guy said he already has ca65 working, please don't make him downgrade to NESASM!
NESASM is by far the easiest assembler to use out there. I think it's one of the top 2-3. Why not use it? Please give details on why it's such of a downgrade.

tepples
Posts: 22052
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Wed Jun 08, 2011 10:40 am

tokumaru wrote:
noattack wrote:The trickier part of learning the NES is not ASM, but how its registers are mapped to its various hardware components.
Which is precisely why I said he should get more comfortable with the CPU before trying to mess with the PPU.
tokumaru: The NES PPU and the Apple II Monitor ROM are the only character outputs on 6502-based systems that I'm familiar with.

Bellum: Which 6502 simulator are you using, so that I can tailor my examples to its specific method of character output?

Bellum
Posts: 17
Joined: Sat Jun 04, 2011 8:04 pm

Post by Bellum » Wed Jun 08, 2011 11:08 am

http://home.pacbell.net/michal_k/6502.html

Also downloaded the samples last night, which I somehow missed before. I understand how they make use of the terminal. Kinda. Sorta. If I'm looking at the examples for reference. :P

EDIT:
Ok, so is .segment a location in memory designated for specific tasks that the assembler understands?

User avatar
tokumaru
Posts: 11859
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Wed Jun 08, 2011 11:57 am

3gengames wrote:Please give details on why it's such of a downgrade.
There have been several cases of people showing up here with problems that ended up being NESASM's fault. Line length issues, generation of corrupt binaries, absurd lack of error report (it generated bad binaries instead of telling you your source code had errors!), things like that. I believe some of those problems were already fixed, but the fact it uses non-standard syntax for some 6502 instructions/addressing modes is still really annoying. Also, in spite of its name, it was originally made for the PC Engine I believe, and there are a few leftovers from that platform that are not necessarily relevant to the NES, such as the obligatory bank size of 8KB.

User avatar
Grumskiz
Posts: 79
Joined: Sat Mar 26, 2011 1:06 pm
Location: Germany

Post by Grumskiz » Wed Jun 08, 2011 12:43 pm

In case you (Bellum) want to stick with ca65 and still read and use the Nerdy Nights tutorials which I highly recommend, I'd say check this out:
https://bitbucket.org/ddribin/nerdy-nights/src

It might not be perfect, but it's a good way to see how ca65 can be used while you're learning how to actually program for the NES.
It helped me a lot and I'm very happy now that I chose to switch to ca65 after using nesasm for a short time.
I agree, it can be easy to start with, but there is nothing really "hard" about ca65 if you ask me.
Today, I would say it is a lot more comvenient to use than nesasm, but that is a personal preference.

Bellum
Posts: 17
Joined: Sat Jun 04, 2011 8:04 pm

Post by Bellum » Wed Jun 08, 2011 10:08 pm

Thanks, Grumskiz. I've read the first few NN tutorials so far and they seem helpful. :)

Can I get you guys to look at this example for looping through strings?

Code: Select all

		*= $1000

stLength   = $2000		;Pointer to $2000 for length of stStore string argument
initString = $F000		;Pointer to beginning of Strings
curString  = $F000		;Pointer to last character in array
				;In this case, the array is dynamic with absolutely no regard to what it may overwrite.
				;LIVE ON THE WILD SIDE




stStore		.MACRO st		;Macro stStore - Store a string in memory - Param: string
				LDY #0				;y = 0
stLoop		LDA %st, y		;a = st[y]
				BEQ stReturn	;if st[y] == null: return
				INY					;y++
				STA curString	;put a at curString
curString = curString + $08	;increment curString 1 byte
				BNE stLoop		;goto stLoop
stReturn
		.ENDM

		
		
main
stringOne	.BYTE "This is the first string.",0
stringTwo	.BYTE "This is the second string.",0
stringThree	.BYTE "This is the last string.",0

				stStore stringOne
				stStore stringTwo
				stStore stringThree
				.END
It wont let me pass stringOne to stStore. Is this just a syntax error or something else?

EDIT: yeeegh, the formatting for the macro was way off. What gives, code tag?
EDIT2: Hm. Reformatting it in notepad++ seems to have helped a little, this time.

User avatar
Dwedit
Posts: 4352
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Wed Jun 08, 2011 10:16 pm

You lost me at the first 3 equates, not sure what $2000, $F000, and $F000 are doing here. Are those just for the 6502 simulator?
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

Bellum
Posts: 17
Joined: Sat Jun 04, 2011 8:04 pm

Post by Bellum » Wed Jun 08, 2011 10:24 pm

Yeah, those are just some meaningless addresses just so I have someplace to put things.

EDIT:
Actually, the first one isn't even used anymore. :P

Bellum
Posts: 17
Joined: Sat Jun 04, 2011 8:04 pm

Post by Bellum » Mon Jun 13, 2011 8:36 pm

Coming back to this (I've got a few other projects sucking up big chunks of my time), I think I've come up with something very slightly less terrible. :P

Labels are constants? (like #define?) It makes sense, but for some reason it hadn't occurred to me before. I keep wanting to translate this into something a little higher level and more manageable.

My rewrite is very similar, but it assembles past the first call to stStore. The problem is, in the second call, it apparently tries to re-define stLoop, which doesn't work. Is there a better way to go about loops in macros, or should I be using jumping to a "subroutine" instead?

Code: Select all

		*=1000
		
stLength = $2000	;Store the length of the string for indexing
initString = $2500	;The beginning of the string


stStore		.MACRO st 		;stStore - store a string in memory
				LDX stLength		;put the length of string array in x
				LDY #0				;init y as index of st
stLoop		LDA st,y			;store st[y] in a
				STA initString,x	;Store a in initString+x
				INX
				INY					;Increment Y and X
				BNE stLoop
				STX stLength		;Store new array size at stLength
				.ENDM
		
		
		

stringA		.BYTE "This is a string."
stringB		.BYTE "This is another string."

				stStore stringA
				stStore stringB
				.END

User avatar
Memblers
Site Admin
Posts: 3880
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers » Mon Jun 13, 2011 9:11 pm

What you will need to do is use a local label in your macro. Usually this is done by beginning the label with at (@), but some assemblers use a period (.). Otherwise it is global.

Bellum
Posts: 17
Joined: Sat Jun 04, 2011 8:04 pm

Post by Bellum » Mon Jun 13, 2011 9:17 pm

Thanks, that assembled. Now to see if it actually does anything remotely similar to what I think it's supposed to do. :lol:

Post Reply