Best source for learning about asm?

Kasumi

New member
I actually recommend easy6502 first: https://skilldrick.github.io/easy6502/ It's kind of aimed more at people who have programmed before (just not in ASM), but if you're able to follow it it's a really good start. I recommend it because 6502 assembly language is not the hard part. NES is the hard part. It helps to get a solid grasp of 6502 without NES quirks getting in the way.

The Nerdy Nights tutorials are NES Specific and aren't really aimed at people who have programmed before: http://nintendoage.com/pub/faq/NA/index.html?load=nerdy_nights_out.html#

Dougeff has a few tutorials (primarily for C, but there are some assembly language ones further down in the page): https://nesdoug.com/

If you ever have any questions, I recommend asking on the nesdev forums: https://forums.nesdev.com/

6502 assembly language's challenge comes in an unexpected way, I think. There are only 56 instructions, maybe 12 of which are used regularly. And all of them (except maybe BIT, and adc/sbc/cmp) have a very simple and immediate result. In a single line of a higher level language, you can create something immensely confusing. In a single line of 6502, you... almost can't.

The challenge in it comes from using such simple things to do the complicated things you want done. The challenge in something higher level comes from how much there is to learn.
 

FrankenGraphics

New member
Assembly varies a lot from one CPU family to another. If you want to write code for apple II, c64, the NES, SNES and PC Engine, you start with 6502 assembly and go from there. I can recommend:

Machine Language for Beginners by Richard Mansfield (especially this one, it's really good explaining all the computer science concepts you need for understanding assembly and by extension how the NES and other 6502 computers work).

6502 Assembly Language Programming by Lance A. Leventhal, and
Machine Language for the Commodore 64 and other Commodore computers by Jim Butterfield

get a used copy from amazon or find a scan.

6502.org is a great resource, i always have their instruction table in a browser tab for reference when i code.

wiki.nesdev.com is super important. Especially the CPU and PPU register maps.


A word of reassurance:
I find assembly to be very hands-on and tactile. Unlike modern, hi-level languages, you actually know exactly what's going on behind the instructions and are in full control. In that sense, i think it is a lot easier to grasp than, say, java for example. The difference is that if you wanted to paint your hall with assembly you do it yourself, while in a high-level language you instruct a professional (the interim layer) to do it by speaking through the intercom, so to speak.

Understanding the NES architecture is, like Kasumi says, real work, but i think it is also necessary to make the most out of a tool like NESmaker. On the other hand, it is also simple in a way: It helps if you think about all the register calls ie (lda/sta someaddress) as a powerful, hardware-accelerated library. Each load or store is in that way a call to a practical, prefixed function, much like in any high-level language. It just takes time to learn how these functions interact. Especially the PPU registers can sometimes behave in ways that aren't always intuitive the first time.

for example
lda #$0E ;this is equivalent to binary 00001110
sta $2001 ;this is the ppu control register
will send a message to the PPU that you want to enable background rendering but diasable sprite rendering, for whatever reason.

How do i know that?

A byte (ie range 00 to FF) has enough states to hold 8 toggle switches (flags). In this case, we use 0E which is hex for 00001110 (or in human speak, off off off off on on on off).
Then consider this chart, taken from the nesdev wiki:

7 bit 0
---- ----
BGRs bMmG
|||| ||||
|||| |||+- Greyscale (0: normal color, 1: produce a greyscale display)
|||| ||+-- 1: Show background in leftmost 8 pixels of screen, 0: Hide
|||| |+--- 1: Show sprites in leftmost 8 pixels of screen, 0: Hide
|||| +---- 1: Show background
|||+------ 1: Show sprites
||+------- Emphasize red*
|+-------- Emphasize green*
+--------- Emphasize blue

This means:
0 - no blue emphasis
0 - no green emphasis
0 - no red emphasis
0 - don't show sprites
1 - but show background
1 - if we had shown sprites, also let them be shown leftmost on the screen (standard)
1 - if we show background (which we do), don't mask the leftmost 8 pixels.
0 - no grayscale mode

Pretty much every hardware register address works either something like that or holds a value for a single parameter ranging 0-255.

*these two bits are unfortunalely switched between NTSC and PAL region consoles. Idk why they decided to do that (seems like a mistake) but it is what it is. Either stay away from setting them individually, or do it within a function that "knows" what version of a console you're using.

Another thing that anyone wanting to do 6502asm will quickly learn is that a high % of all bugs (until you've learned how to avoid it) is due to you assuming one of the arithmetic registers has some value, but it has another. Since there are only three of them (accumulator, x and y), and all data has to be processed through these three "channels" , it's easy to overwrite a value by mistake/without knowing and clobber some other function. Just yesterday, this still happened to me and i didn't understand why a tileset was offset by 8 pixels until i realized that register y wasn't 0 anymore (a value you use quite often) at a critical point because of some other code.

So:
lda #$95
sta ptr+1
sty ptr+0

became
lda #$95
sta ptr+1
ldy #$0 ;assures 0 will be written to the least significant byte of pointer
sty ptr+0

in this particular instance. Ideally, you want it like in the first example, but since this code isn't reiterated in a tight loop, you can get away with the extra safety. Else, you may need to do some juggling whether to use a, x, or y and make sure the functions don't clobber each other. In z80 you have a lot more arithmetic registers like these to spare/use so it is much easier in that sense to code.

Another high % of all bugs (and this will be true throughout 6502asm coding) are when a variable is wrong at the boundaries, maybe it should be #$00 but instead is #$01 or #$FF.
 

stevenshepherd

New member
Thanks for the posts. This is all very overwhelming. I am hoping I can avoid asm as much as possible and get what I want be being creative with what nesmaker natively offers. From there, maybe seeing the code that nesmaker creates and making sense of it and editting it when necessary. These resources ought to help, thanks!
 

FrankenGraphics

New member
I think my post may be the worst didactics i've ever managed to produce, though, please don't be alarmed by it. I can see that it skips a lot of concepts that needs to be known to be able to follow.

anyway "machine language for beginners" is a good start. Skip the chapter about "monitors" and you're fine.

Modifying existing code and see what it does is an excellent way to start.
 

Kasumi

New member
There are 3 locations that hold a number on the 6502 CPU that you regularly interact with. Those are:
1. The accumulator, usually shortened to A.
2. X
3. Y
These three "number storage locations" are called "registers".
Then, there is a set of "flags". Just about every time you do something, those flags are affected by the result of what you do. I'll cover those a bit later. These are the first three 6502 instructions to learn.
LDA = LoaD a value into the Accumulator.
LDX = LoaD a value into X.
LDY = LoaD a value into Y.

LDA #0 makes the value stored in the accumulator equal to 0.
LDX #4 makes the value stored in X equal to 4.
LDY #254 makes the value stored in Y equal to 254.

Because most computing needs to keep track of much more than 3 numbers, the NES also has access to RAM. Just like A, X and Y, all RAM does is hold a number. NES has 2048 locations that hold a number for RAM. (By default.)

6502 programming at its most basic is loading a value into one of the registers, then storing it in RAM. If you need the value again, you can copy the value from RAM back into the register. Then you can modify the value, and copy it from the register back to RAM.

There are three more instructions to learn.
STA = STore the value in A (the accumulator) into a location in RAM (or ROM, but let's ignore ROM for now).
STX = STore the value in X into a location in RAM.
STY = STore the value in Y into a location RAM.

Let's say A, X, and Y are all 0 at the start. Now let's say RAM location 0, and RAM location 1 are also 0 at the start. We'll call them R0 and R1 for simplicity.
So...
A = 0
X = 0
Y = 0
R0 = 0
R1 = 0
Now, let's write an instruction and see how these numbers change.
LDA #8
A = 8
X = 0
Y = 0
R0 = 0
R1 = 0
Because we loaded 8, the value 8 is now the value the accumulator holds. As I said, each instruction has an simple and immediate result. Now let's store the value in A to a location in RAM.
STA R0
A = 8
X = 0
Y = 0
R0 = 8
R1 = 0
Once again, simple and immediate. The value that was in A (which was 8) is now copied (or stored) to RAM Location 0. That it is a copy is important! Let's see what happens when we change the value in A:
LDA #27
A = 27
X = 0
Y = 0
R0 = 8
R1 = 0
You'll note that A now holds 27. But R0 is still 8. RAM is for long term storage of values. Usually nothing will change unless you change it. Let's try a different register!
LDX #82
A = 27
X = 82
Y = 0
R0 = 8
R1 = 0
Just like LDA, LDX simply changes the value that X holds.
STX R1
A = 27
X = 82
Y = 0
R0 = 8
R1 = 82
Just like STA, STX simply stores a copy of X to RAM.
LDX #43
A = 27
X = 43
Y = 0
R0 = 8
R1 = 82
I did the above just so none of the numbers we've been following match.
Now... let's say I want to load a value from RAM, instead of just a number? You're notice that everywhere above, the '#' character has preceded the value that gets loaded for LD instructions. If you omit that '#' character, you load from RAM (or ROM) instead.
LDA R1
A = 82
X = 43
Y = 0
R0 = 8
R1 = 82
Notice that A is now equal to 82. Because this was the value stored at R1. Y Seems lonely. Let's use it!
LDY R0
A = 82
X = 43
Y = 8
R0 = 8
R1 = 82
Once again, the value is simply copied from R0 to Y.
LDY #1
A = 82
X = 43
Y = 1
R0 = 8
R1 = 82
And once again, when you precede the value with a '#', you just copy the given number rather then getting something from RAM (or ROM).

Does that make any sense so far? If not, ask questions!
 

FrankenGraphics

New member
I haven't done too much language/construction checking but might a style like this be beneficial?

What is a Register?
It's a really tiny bit of memory (usually 8 or rarely 16 bits on the nes) with a very specific task, unlike RAM which you've got plenty of (well... 2kB) but is general purpose for your convenience. Registers are usually physically situated within some processor, microcontroller and so on. There are all kinds of registers. They are a bit like synapses in that they pass on tiny bits of information or react to certain situations, which your game can be on the lookout for at your option.

What is the arithmetic and what are the index registers:
It may help to think about the arithmetic register (A for Accumulator) and index registers (X, Y) as hands.

The CPU has 3 hands. It can grab (actually copy) a piece of information from one bowl, manipulate it some, and/or place (again, copy) it to another bowl. Just like your real-life hands, you'll use these three hands all the time when executing 6502 code.

You instruct the hands to do different things with instructions. When viewing assembly code, you see lots of mnemonics like LDA (LoaD A), STA (STore A), CMP (CoMPare). These instruct the hands to do different things. Other instructions instruct other parts of the CPU than the hands though. For example, a BRK (BReaK) will instruct the CPU to stop doing whatever it is doing at that very instant and turn attention to something else (which the programmer has pre-defined is something called a vector, for those who are curious).

(curiosity fact box: historically, this specific instruction (BRK) was used a lot to "escape" a program and enter a debugging program called a "monitor". None of that is relevant today, though, as the NES doesn't have any programs built-in and it's far easier to debug your code in an emulator on a modern computer anyway. If you see any old book mentioning a [debugging] monitor, this was what they meant - not the screen. BRK can still be useful for other things, for example auto-reset the game when something goes awry or pause game playback to show the programmer the current value of some variables on-screen).

A (short for accumulator) is where you'll try to do most of your math and "message delivery" between bowls (it might make sense to call them mail boxes as this point, because every bowl/mail box has an address, That's how you know from where to load and where to store).

X is often used as a counter when you need to iterate a task a number of times or do something called indexed addressing. That's for another day.
Y is in practice kind of a spare register for when you need to juggle a lot of information at once or want to preserve or pass a value between functions without needing to fetch it again and again from ROM or RAM.

X and Y actually are nearly identical though X has some additional obscure functionality which is too nerdy to mention right now.

What are status registers?
The CPU (and PPU - that's the picture processor) also has(have) an assortment of different "flags". They work a bit like when you try to remember something by holding out a finger or tie a rubber band around it, Unlike hands (arithmetic/index registers), these flags can only hold the simplest kind of information: if something is or isn't, and just like fingers they have specific names.

Many of these flags are super useful for making decisions (should the game/code do this or that? Well, let's check the PPU status register. Aha, this Sprite Overflow flag for example says there's more than 8 sprites on a scanline, so maybe we should enable the priority cycling/flicker routine so that the 9th sprite and so on isn't invisible. (curiosity fact box: a lot of games actually have sprite cycling turned on all the time for the sake of simplicity). The sprite overflow flag can say if there's an overflow or if there isn't. It can't say how many sprites there are on a line. It can't hold a value other than 1 or 0.
This is status flag, and 8 status flags comprise a status register. There are two pure-bred status registers internal to the NES: CPUSTATUS and PPUSTATUS.

What is a control register?
Some flags are meant to be read and are updated automatically by the CPU or PPU. Still others can actually also be manipulated (written to) by the programmer. This category of flags are more like flip switches for various modes, settings, and preferences of the system. These are called control registers. PPUCONTROL is one where you can turn background and sprites on and off and tint the whole screen in a few colours and so on.

What is a hardware register?
Basically any register that controls or returns the status of some hardware, for example a controller. In that sense, a hardware register can be about status or control.

What is a stack?
The CPU has one rucksack (comprised of a so-called stack register (more exactly called stack pointer), and a storage space situated in RAM called stack page). In practice, it works just like a rucksack. A hand can put stuff in it or take something out. If you take something out of it, it will be the last thing you put in. Then the item you put in after that, and so on.

What is the program counter?
The program counter is a special register which keeps track of where in the code the program currently is (so that it knows what line of code to execute next). It is like a teachers' pointer in the classroom going word for word across a phrase in a foreign language on the whiteboard, ie. it instructs the pupils what word to pronounce next. When the code doesn't go straight from top to bottom (ie instructions tell it to momentarily jump to some other function and then return to where it were), it interacts a lot with the stack (rucksack) to remember where to return. The stack register is therefore adequately called the stack pointer, much like the teachers' pointer.

Why do i need to know all this?
With NESmaker, you can principially do what it says on the tin. Press click and assemble a game. But if you want to get the most out of it, it is good knowing what building blocks on the hardware you're actually working with and how they interact.

tl;dr (but not really a summary)
Bottom line: Arithmetic registers (hands) are for loading, manipulating and storing a grab of data in different bowls. Flags are bundled in groups of 8 and one such group is also called a register, but their function is different from the arithmetic or index ones.

New words to look up:
Registers
 

Godzil

New member
It is a toy, but to play a bit with the 6502 asm in a simple machine, I do recommend that website:

http://www.6502asm.com/
 
I have been using this book and making a video series on it.... https://archive.org/details/6502_Assembly_Language_Programming
but it seems there are plenty of useful sites. I do like that 6502asm.com and it looks like Frankengraphics will be teaching me lots.
As much as I learn I'm still a simple idea and graphic guy (kind of music), even with NESmaker and some ASM knowledge I still expect I will need a more technical mind to help smooth out the finished game.
 

EyE6SoLoMoN

New member
There's a lesson plan, called "Nerdy Nights", that can be found online, and completely free. Many homebrew developers have learned from those lesson plans. It's by Brian Parker; a.k.a. BunnyBoy, the developer of the AVS. It's very helpful and could get you started.
 

digit2600

Member
I found a whole audio book on YouTube this morning, been listening to it on and off all day. Definitely worth checking out.

For some reason, my phone won't let me copy and paste. Go on you tube and search: NuvYou 6502 programming. There's a whole 15 chapters.
 

Mihoshi20

Member
You'll probably pickup 6502 assembly pretty quickly or at least the basic concepts of registers and jumping around in the code. If you have the chance, studying 6502 assembly along with playing human resource machine to grasp some concepts. So much so that I wish you could rename the commands to match their asm ones.

The problem you'll probably struggle with the most is the NES hardware, least I sure did. Understanding all the addresses and registries, what they do, what you need to write/read into them, when, and why was the biggest frustrations as most of the tutorials were outdated, not very detailed or consistent and the rest was all technobabble. Understanding the most common assemblers and their differences from each other took a while.

NESMaker even in it's current beta form takes so much mystery and frustrations out of it.
 
Top Bottom