I have been interested in NESMaker, yet I didn't feel like buying it after looking into the files, which is kind of preused.
Can anyone recommend me the best software to start off? Obviously, Bunnyboy seems best by people's standard, and I am wondering if there's the best tool list to do, so I made a list if anyone could help me out:
-Writing : Notepad ++
-Music : Famitracker
- Graphic : YY-CHR or Aseprite
I am not sure if there is more, so helping me find more tools would be nice.
And NES Screen Tool. and it's RLE compression system.
And I prefer asm6 to NESASM3. Some use ca65.
And famitone2 to convert famitracker to a more game friendly music format.
Another program for graphics is Damian Yerrick's "8ted" and "8Name" programs. There is also my own Farbfeld Utilities programs "ffbit" which can convert graphics into NES/Famicom format (and "ff-uniq" if you want to get rid of duplicate tiles).
For text editing I use vim, although you can use any text editor.
Another program for using is ppMCK, although that is intended for writing .NSF files rather than music for the game. Another program for music is Pently, which I believe is suitable to make music for a game, as well as for NSF.
For assembler many prefer ca65 or asm6, although I still like NESASM.
I don't see NESASM recommended much these days. Everyone has moved to ca65 and asm6.
Also, it's very common to write your own tools, even if they're just little 10-line scripts.
I have to remind you that for nesmaker you probably don't want to use CHR graphics. Nesmaker uses its own base files.
So what is the difference between ca65 and ASM6? Is there ever will be ASM7?
I look over Bunnyboy, and I am not so sure if they support both assembly.
The Bunnyboy Nerdy Nights tutorials are intended to be used with NESASM. Version 2.x and 3.x are different. I cannot remember what version was used in his tutorials.
asm6 is the name of the assembler/program; it's just a name, it is not a version or version number.
NESASM, ca65, and asm6 are different assemblers. ca65 is generally for experienced programmers; you will spend days trying to configure it to assemble/link a program.
Please do not ask people to do long write-ups comparing assemblers; nobody here knows what your existing experience level is, or if you're even familiar with programming (and how low level).
Respectfully, please so some research on your own now that people have given you more information than you had before. You'd better get in the habit of researching stuff if you truly plan on doing nesdev stuff. You're gonna spend a lot of time reading + studying. Download them, read READMEs/documentation, see what you think.
Here's my post in another topic:
viewtopic.php?f=2&t=16761&p=209020&hilit=credits#p209020 (But also read everyone else's posts in said other topic)
I still use nesasm, but I recommend asm6.
Edit 2: Here's my post in that topic's sister topic:
viewtopic.php?f=21&t=16642&p=207068&hilit=credits#p207068 (But also read everyone else's posts in said other topic)
Edit: Why not, I'll post my own program I-CHR:
https://kasumi.itch.io/ichrIt requires a bit less manual prep for image->NES graphics. (NES Screen Tool lets you massage the data better once you've got it in, though.) I need to make it export some more (and padded) data for better interoperability with NES Screen Tool... I hope to update it soon, it has gotten a lot of neat stuff since the public version.
koitsu wrote:
The Bunnyboy Nerdy Nights tutorials are intended to be used with NESASM. Version 2.x and 3.x are different. I cannot remember what version was used in his tutorials.
asm6 is the name of the assembler/program; it's just a name, it is not a version or version number.
NESASM, ca65, and asm6 are different assemblers. ca65 is generally for experienced programmers; you will spend days trying to configure it to assemble/link a program.
Please do not ask people to do long write-ups comparing assemblers; nobody here knows what your existing experience level is, or if you're even familiar with programming (and how low level).
Respectfully, please so some research on your own now that people have given you more information than you had before. You'd better get in the habit of researching stuff if you truly plan on doing nesdev stuff. You're gonna spend a lot of time reading + studying. Download them, read READMEs/documentation, see what you think.
Alright.. I am not sure if that feels..aggresive or offensive.
Kasumi wrote:
Here's my post in another topic:
https://forums.nesdev.com/viewtopic.php ... ts#p209020 (But also read everyone else's posts in said other topic)
I still use nesasm, but I recommend asm6.
Edit 2: Here's my post in that topic's sister topic:
https://forums.nesdev.com/viewtopic.php ... ts#p207068 (But also read everyone else's posts in said other topic)
Edit: Why not, I'll post my own program I-CHR:
https://kasumi.itch.io/ichrIt requires a bit less manual prep for image->NES graphics. (NES Screen Tool lets you massage the data better once you've got it in, though.) I need to make it export some more (and padded) data for better interoperability with NES Screen Tool... I hope to update it soon, it has gotten a lot of neat stuff since the public version.
Ah, thanks!
It's realistic. There's a lot of information out there. If you want to use nesmaker you need to wait for its release. If you want to program on your own you can look at tutorials such as dougeff's
https://nesdoug.com/Either way it's going to take a while. Get to work and when you have a technical question that you can't solve you can ask here for clarification. But be ready to get responses like this if it's clear that you haven't been reading enough. This is a rewarding hobby that takes a lot of time from reading and trying things out yourself.
I think Koitsu's point is that even though we are a helpful community, there are no private teachers here. We will gladly help beginners make sense of all the stuff that's out there, but we expect them to do some research and show that they're putting effort into learning all this new stuff, so we know that the effort we put into explaining things isn't going to waste.
You might want to try out NESICIDE. It's a whole IDE with editor, emulator, debugging tools. It includes ca65/cc65, you can develop in assembly or C. There are example sources for it, so you could base your program on that if you don't want to mess with setting up ca65.
Memblers wrote:
You might want to try out NESICIDE. It's a whole IDE with editor, emulator, debugging tools. It includes ca65/cc65, you can develop in assembly or C. There are example sources for it, so you could base your program on that if you don't want to mess with setting up ca65.
NESICIDE looks good and professional to me, but I am not sure which tutorial is the best for NESICIDE. I don't know if bunnyboy would cover NESICIDE tutorial.
Personally I think ca65 is just fine for beginners too, especially if you have an example to work from.
...which is why I created this example:
http://forums.nesdev.com/viewtopic.php?t=11151
I think any NES tutorial is good for nesicide, asm6 or ca65. At least for me, translating the excercises from nesasm3 to asm6 helped me understand better what was going on and what it was to assemble a program. I should add that before 6502 assembly, my prior programming experience was *very* limited. Just BASIC and various small scripts, essentially. So i don't think it's too rough to try to make his example code work with another example, even if it is *slightly* more uphill.
If you're going for asm6, you'll find everything you need in the short readme file that comes included to be able to translate the tutorial as an excersise in-itself.
If you're going for ca65 or NESICIDE (which as others have pointed out is built on ca65), the example rainwarrior posted plus the (very large) reference guide of the cc suite will help you achieve the same. Link to the ca65 chapter here:
https://cc65.github.io/doc/ca65.htmlI've read it over and over and still have a lot to learn. Only a fraction of what is described in the reference is required to build a simple program. it's just a very versatile assembler that offers a lot of extra functionality beside the basics. Some of it is only relevant to other systems than the NES, so you can safely skip those parts for now.
rainwarrior wrote:
Personally I think ca65 is just fine for beginners too, especially if you have an example to work from.
...which is why I created this example:
http://forums.nesdev.com/viewtopic.php?t=11151It said the system can't find the path specified.
EDIT: Wait, sorry, I'll see about bunnyboy..
DocWaluigean wrote:
It said the system can't find the path specified.
If you open example.txt it will explain that you need to get cc65 and where to put it.
Honest question about the NES coding.
I apparently found this
viewtopic.php?p=58138#p58138 and I been thinking about the one found in the bunnyboy version about background.asm.
I am wondering is 100% complete base of NES with no codes or templates found from anyone possible? I am looking what code to put in where it's completely enough to consider NES compatibility.
There's the iNES part from Bunnyboy but the
viewtopic.php?p=58138#p58138 one doesn't have iNES part in the beginning, and other forms of LetterROM.
I'm not sure that I understand your question but the ines header is only necessary so the emulator knows what hardware you are trying to use. A nes cartridge doesn't have any such thing so when creating the rom for a real nes, this header wont be necessary.
Since you are starting developing for the nes, it is best if you start with a very basic configuration (NROM) because for learning you don't need much memory or don't have any hardware specific requirements yet. Once you will understand more about the hardware, you will be able to ask more question on how to set the INES header for something that suits your needs.
I never used the bunnyboy tutorial myself but my guess is the ines header should be NROM based. As for the compiler, don't worry much about which one to use at first: just use the one that is suggested with the tutorial. Once you get enough experience switching to another compiler doesn't take much time.
edit:
And at first, just don't try to think too much. I would suggest to try to compile the existing example and check if they do works. Once this part is done, just try to modify the example and see what happens. Experiment is a important part of learning, especially for the nes.
If you're going to follow a tutorial, and have no previous experience with the programming language in question, it's better to use the same assembler used in the tutorial. If you're new to this, you'll have a hard time compensating for all the differences in tools if you pick software not covered in the lessons.
Once you understand the basics well, you'll be able to see the shortcomings in the tools you've been using, so you'll be better equipped to make the decision to change tools yourself, rather than relying on what others say is best.
Banshaku wrote:
I'm not sure that I understand your question but the ines header is only necessary so the emulator knows what hardware you are trying to use. A nes cartridge doesn't have any such thing so when creating the rom for a real nes, this header wont be necessary.
Since you are starting developing for the nes, it is best if you start with a very basic configuration (NROM) because for learning you don't need much memory or don't have any hardware specific requirements yet. Once you will understand more about the hardware, you will be able to ask more question on how to set the INES header for something that suits your needs.
I never used the bunnyboy tutorial myself but my guess is the ines header should be NROM based. As for the compiler, don't worry much about which one to use at first: just use the one that is suggested with the tutorial. Once you get enough experience switching to another compiler doesn't take much time.
edit:
And at first, just don't try to think too much. I would suggest to try to compile the existing example and check if they do works. Once this part is done, just try to modify the example and see what happens. Experiment is a important part of learning, especially for the nes.
What tutorial did you learn beside bunnyboy?
And also, it's pretty impossible for me to not think too much, as I'm often feel like missing out important details, like what everything does in the background / sprite.asm. but I kind of understand your point.
tokumaru wrote:
If you're going to follow a tutorial, and have no previous experience with the programming language in question, it's better to use the same assembler used in the tutorial. If you're new to this, you'll have a hard time compensating for all the differences in tools if you pick software not covered in the lessons.
Once you understand the basics well, you'll be able to see the shortcomings in the tools you've been using, so you'll be better equipped to make the decision to change tools yourself, rather than relying on what others say is best.
I have minor experiences in BASIC languages, from PRINT and INC through partially on DATA and GOTO / @ symbols.
DocWaluigean wrote:
I have minor experiences in BASIC languages, from PRINT and INC through partially on DATA and GOTO / @ symbols.
If you have zero experience with any kind of assembly language, and plan on following an NES programming tutorial, better use the tools the tutorial uses. When starting out, we often don't know what tools do what and how, so it's very hard to make substitutions on our own. Once you're more acquainted with how things work and how everything is put together, you can try other tools if you think any of the ones you're using aren't as good as they could be.
DocWaluigean wrote:
What tutorial did you learn beside bunnyboy?
And also, it's pretty impossible for me to not think too much, as I'm often feel like missing out important details, like what everything does in the background / sprite.asm. but I kind of understand your point.
I started to be interested in nes programming around, hmmmm, 2007/2008, just before joining nesdev. At the time, I think Bunnyboy was writing those tutorials so the only thing I had was the current documents available on nesdev. I may have use some other online tutorials but today they would be inadequate since we know more about the inner working compare to was avaible before 2008.
I know what you mean that you want to not miss out, that is normal and will react the same too
But with your current background and the fact that a the nes is a little bit complicated to grasp from the beginning, the best thing is to follow the current tutorials, one by one, play with the code inside it and see what it does. The thing you will have the most fun with is when you can modify one and it does what you expect.
At first you won't understand all the code, which is expected. The more you will play with them, the more you will be able to ask questions regarding what you don't understand. For now, just don't rush and have fun playing with the samples with the tutorial!
Banshaku wrote:
DocWaluigean wrote:
What tutorial did you learn beside bunnyboy?
And also, it's pretty impossible for me to not think too much, as I'm often feel like missing out important details, like what everything does in the background / sprite.asm. but I kind of understand your point.
I started to be interested in nes programming around, hmmmm, 2007/2008, just before joining nesdev. At the time, I think Bunnyboy was writing those tutorials so the only thing I had was the current documents available on nesdev. I may have use some other online tutorials but today they would be inadequate since we know more about the inner working compare to was avaible before 2008.
I know what you mean that you want to not miss out, that is normal and will react the same too
But with your current background and the fact that a the nes is a little bit complicated to grasp from the beginning, the best thing is to follow the current tutorials, one by one, play with the code inside it and see what it does. The thing you will have the most fun with is when you can modify one and it does what you expect.
At first you won't understand all the code, which is expected. The more you will play with them, the more you will be able to ask questions regarding what you don't understand. For now, just don't rush and have fun playing with the samples with the tutorial!
Thanks.
Hmmm, well I'm on Week 3 right now, and I am still fuzzed about A X and Y on how does register works. I understood about Opcodes and Oprahand [like DIM / DEF and PRINT / GOTO stuff] but the register still puzzled me.
Is it like a temporary data to hold the specific mathematics up to 3 times during any changes?
DocWaluigean wrote:
Hmmm, well I'm on Week 3 right now, and I am still fuzzed about A X and Y on how does register works. I understood about Opcodes and Oprahand [like DIM / DEF and PRINT / GOTO stuff] but the register still puzzled me.
Is it like a temporary data to hold the specific mathematics up to 3 times during any changes?
General purpose registers on the NES are A, X, and Y. They are all 8bit boxes that can hold any value from:
Decimal: #0 to #255
Hexidecimal: #$00 to #$FF
Binary: #00000000b to #11111111b; <asm6 (or: #%00000000 to #%11111111)
The three formats listed above can be explored further, pretty easily, with Windows Calculator in Programmer mode.
tepples told me that registers A, X, and Y, on the NES, never lose their value unless an instruction changes it. So you can store a value in X, jsr a function that doesn't change X, and then use X confidently knowing that X still holds the value. This reduces, pointless, stores (stx, sta, sty) and loads (ldx, lda, ldy) and you save 4 bytes and 7 cycles, for zeropage addresses, for each pair you can eliminate!
For me, the 6502's creator, MOS Technology,'s programming manual's appendicies are so helpful. They show each instruction and its bytes and cycles used, among other things. I don't remember the pdf's name, but you can find it easily with a duckduckgo.com search.
(I printed the appendicies out for easy searching, but there are other webpages with the info too.) The NES' 2A03 is a special type of 6502 processor.
edit:
msc6500_family_programming_manual.pdf that's a later edition than the 1st edition appendicies I printed out a long time ago, but this edition's appendicies are more correct and understandable.
Small tip: print this pdf's page 198 in landscape mode.
A is a more general purpose register. Math and bit operations are done with A.
X and Y are more for an index to an array, or counting a loop. LDA array, X gets the Xth element of an array.
dougeff wrote:
A is a more general purpose register. Math and bit operations are done with A.
X and Y are more for an index to an array, or counting a loop. LDA array, X gets the Xth element of an array.
"General purpose" was supposed to say that you can load/store/"do math with" those registers. Unlike the Stack Pointer and Processor Status registers; though you can (carefully) load/store them with tsx/txs and plp/php; but, they have to be used carefully, especially the Stack Pointer, or your nes game
will can perish instantly until you fix it. A,X, and Y don't need to be used very carefully, but, as dougeff teaches, each of them (A, X, and Y) are different (can/must be used in different ways/for different purposes).
edit: Sorry. The word should be "can", I think, because editing the Processor Status register incorrectly would probably not make a game "perish"; nevertheless, it is definitly possible.
unregistered wrote:
DocWaluigean wrote:
Hmmm, well I'm on Week 3 right now, and I am still fuzzed about A X and Y on how does register works. I understood about Opcodes and Oprahand [like DIM / DEF and PRINT / GOTO stuff] but the register still puzzled me.
Is it like a temporary data to hold the specific mathematics up to 3 times during any changes?
General purpose registers on the NES are A, X, and Y. They are all 8bit boxes that can hold any value from:
Decimal: #0 to #255
Hexidecimal: #$00 to #$FF
Binary: #00000000b to #11111111b; <asm6 (or: #%00000000 to #%11111111)
The three formats listed above can be explored further, pretty easily, with Windows Calculator in Programmer mode.
tepples told me that registers A, X, and Y, on the NES, never lose their value unless an instruction changes it. So you can store a value in X, jsr a function that doesn't change X, and then use X confidently knowing that X still holds the value. This reduces, pointless, stores (stx, sta, sty) and loads (ldx, lda, ldy) and you save 4 bytes and 7 cycles, for zeropage addresses, for each pair you can eliminate!
For me, the 6502's creator, MOS Technology,'s programming manual's appendicies are so helpful. They show each instruction and its bytes and cycles used, among other things. I don't remember the pdf's name, but you can find it easily with a duckduckgo.com search.
(I printed the appendicies out for easy searching, but there are other webpages with the info too.) The NES' 2A03 is a special type of 6502 processor.
edit:
msc6500_family_programming_manual.pdf that's a later edition than the 1st edition appendicies I printed out a long time ago, but this edition's appendicies are more correct and understandable.
Small tip: print this pdf's page 198 in landscape mode.Thanks for PDF!
But this is what I don't understand.
Is it a separate engine, like the Address? Or is it a form of abilities like RAM or DATA styles?
Like how does the register of A X Y [and P Z ] works? Or they work as a special form of variables like, a temporary placement of " A = X + Y" until the new replacement happens like "STA" or "LDA"?
I don't like to say this much, but can you explain like if I'm in Elementary School to help me understand about register? [It's very owned variables, like no other regular variables can use?]
Or it's like a "magic effects" but in programming, like the A represent the stages of Mario Bros. your in, X represent your health, and Y represent your Mario life?
Quote:
Is it a separate engine, like the Address? Or is it a form of abilities like RAM or DATA styles?
Like how does the register of A X Y [and P Z ] works? Or they work as a special form of variables like, a temporary placement of " A = X + Y" until the new replacement happens like "STA" or "LDA"?
these registers exist inside the CPU.
It holds a value, 8 bits each.
This value can be whatever your program wants it to be. As a temporary variable. As an address (pointer). As a counter.
And when I say temporary, I mean very very briefly. As the program runs the A register will change values hundreds of times a second, depending on what the program is doing.
Quote:
like the A represent the stages of Mario Bros. your in, X represent your health, and Y represent your Mario life?
Ok, let's say you've chosen RAM address 31 to hold the health of Mario. Let's say Mario gets injured, so his health goes down 1. You can decrease the value of 31 by loading it into the A register and subtracting 1, then storing it again at RAM 31.
LDA 31 ;load from 31
SEC ;set the carry flag, for subtraction
SBC #1 ;subtract 1
STA 31 ;store to 31
(There is another way to do this, but I chose to use the A register for example)
The health only is used by A for a brief moment, then A goes on to do other things.
dougeff wrote:
Quote:
Is it a separate engine, like the Address? Or is it a form of abilities like RAM or DATA styles?
Like how does the register of A X Y [and P Z ] works? Or they work as a special form of variables like, a temporary placement of " A = X + Y" until the new replacement happens like "STA" or "LDA"?
these registers exist inside the CPU.
It holds a value, 8 bits each.
This value can be whatever your program wants it to be. As a temporary variable. As an address (pointer). As a counter.
And when I say temporary, I mean very very briefly. As the program runs the A register will change values hundreds of times a second, depending on what the program is doing.
Quote:
like the A represent the stages of Mario Bros. your in, X represent your health, and Y represent your Mario life?
Ok, let's say you've chosen RAM address 31 to hold the health of Mario. Let's say Mario gets injured, so his health goes down 1. You can decrease the value of 31 by loading it into the A register and subtracting 1, then storing it again at RAM 31.
LDA 31 ;load from 31
SEC ;set the carry flag, for subtraction
SBC #1 ;subtract 1
STA 31 ;store to 31
(There is another way to do this, but I chose to use the A register for example)
The health only is used by A for a brief moment, then A goes on to do other things.
Is register is inside everything programming-wise? Or it's selective?
So it's the same as:
JOE = 10
ROB = 5
JUMP = JOE + ROB
IF JOE == ROB
GOTO @NAME
???
Or is it pretty much the same, except the difference is the NES CPU can only do 3 to 5 variables instead of infinite? I learn this kind of program styles in SmileBASIC.
DocWaluigean wrote:
Thanks for PDF!
But this is what I don't understand.
Is it a separate engine, like the Address? Or is it a form of abilities like RAM or DATA styles?
Like how does the register of A X Y [and P Z ] works? Or they work as a special form of variables like, a temporary placement of " A = X + Y" until the new replacement happens like "STA" or "LDA"?
I don't like to say this much, but can you explain like if I'm in Elementary School to help me understand about register? [It's very owned variables, like no other regular variables can use?]
Or it's like a "magic effects" but in programming, like the A represent the stages of Mario Bros. your in, X represent your health, and Y represent your Mario life?
I'm sorry I can't explain registers to you in elementary school logic because I didn't learn about registers until college. But, I can try.
The processing chip that the NES uses is called the 2A03. The 2A03 is a special type of the 6502 processing chip. (For instance, it doesn't have the b flag in its status register and its d flag is pointless too, but those aren't important now.) The three 6502 registers I'm attempting to explain are A, X, and Y. Each of the registers are created with 8 bits. Every bit comes from a transistor. If a bit's transistor holds an electrical charge, the bit is set and that translates into a 1. Otherwise, the bit's transistor lacks an electrical charge then the bit is clear and so we have a 0. Ever hear of computers being all 1s and 0s?
The numeral system Binary is an easy, but lengthy way, of telling the NES's 2A03's A register what to hold. If your program tells the NES:
lda #%00000001 that will set bit0 of register A and clear register A's bits 1 through 7.
Bits in a register are named
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1| bit0 |. Yes, that's right to left, but use it enough an you'll get used to it.
There are two other ways of describing the value, you want loaded into register A, to the assembler: Hexidecimal and Decimal.
Before you click on this link read the paragraph sections above carefully.
https://betterexplained.com/articles/numbers-and-bases/Now I will close by saying that the three 8bit-wide registers A, X, and Y are located on the NES's 2A03 processing chip. There is the simplest way I can fully explain a register. Perhaps someone else can help you more.
unregistered wrote:
DocWaluigean wrote:
Thanks for PDF!
But this is what I don't understand.
Is it a separate engine, like the Address? Or is it a form of abilities like RAM or DATA styles?
Like how does the register of A X Y [and P Z ] works? Or they work as a special form of variables like, a temporary placement of " A = X + Y" until the new replacement happens like "STA" or "LDA"?
I don't like to say this much, but can you explain like if I'm in Elementary School to help me understand about register? [It's very owned variables, like no other regular variables can use?]
Or it's like a "magic effects" but in programming, like the A represent the stages of Mario Bros. your in, X represent your health, and Y represent your Mario life?
I'm sorry I can't explain registers to you in elementary school logic because I didn't learn about registers until college. But, I can try.
The processing chip that the NES uses is called the 2A03. The 2A03 is a special type of the 6502 processing chip. (For instance, it doesn't have the b flag in its status register and its d flag is pointless too, but those aren't important now.) The three 6502 registers I'm attempting to explain are A, X, and Y. Each of the registers are created with 8 bits. Every bit comes from a transistor. If a bit's transistor holds an electrical charge, the bit is set and that translates into a 1. Otherwise, the bit's transistor lacks an electrical charge then the bit is clear and so we have a 0. Ever hear of computers being all 1s and 0s?
The numeral system Binary is an easy, but lengthy way, of telling the NES's 2A03's A register what to hold. If your program tells the NES:
lda #%00000001 that will set bit0 of register A and clear register A's bits 1 through 7.
Bits in a register are named
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1| bit0 |. Yes, that's right to left, but use it enough an you'll get used to it.
There are two other ways of describing the value, you want loaded into register A, to the assembler: Hexidecimal and Decimal.
Before you click on this link read the paragraph sections above carefully.
https://betterexplained.com/articles/numbers-and-bases/Now I will close by saying that the three 8bit-wide registers A, X, and Y are located on the NES's 2A03 processing chip. There is the simplest way I can fully explain a register. Perhaps someone else can help you more.
I thought 2A03 is primary used for default sound and audio creations engine inside NES.
So it's just an on and off switch like 0s and 1s? What is the differences or limitations compare to other engine like PS2 or PC or C#?
I think you current issue right now is that before getting into understanding the nes you will need first to understand what is the 6502 and how to use it with assembler. Without that knowledge it will make it difficult to get to the interesting stuff, which is programming a game for the nes.
I did a quick search regarding some basic tutorial about 6502 and this page seems quite interesting:
http://skilldrick.github.io/easy6502/It is a tutorial that allows to test online some assembler and see the result with their simulated machine. The concept is interesting since you can see the results right away and don't need to worry about how to use any compilers, linkers, nes architecture etc and can just focus on studying the 6502. I think this page will help you get a step further to programming for the nes. Once you understand about registers (A is the accumulator, X/Y are the index) and basic addressing, the nerdy nights should be a lot easier to follow.
Yeah, it can be hard to learn everything at once: 6502 assembly, the NES architecture, the iNES file format, game logic... If you're feeling overwhelmed, starting out with pure 6502 assembly like Banshaku suggested is a good alternative.
When I first tried to learn 6502 assembly some 20 years ago I too was confused as hell... registers and status flags made no sense to my brain, which was only familiar with BASIC and Pascal. I was able to make a couple of NES demos with a bit of animation but it was a lot of trial and error, so I kinda gave up on that. It wasn't until I tried
this 6502 simulator that everything finally made sense to me. I tried all the instructions and watched how they affected the processor's status, and once I understood what all the instructions did, I was able to code a few subroutines that performed actual tasks, such as multiply 2 numbers and return the result. That way I got the hang of how to use those simple instructions to perform more complex tasks, and felt ready to learn more about the NES architecture and everything else.
Quote:
JOE = 10
ROB = 5
JUMP = JOE + ROB
IF JOE == ROB
GOTO @NAME
In Assembly, JOE, ROB, and JUMP could be RAM address, and @NAME is a label that the assembler will give a value to at assembly time. (Omitting some assembly directives to make it easier)
LDA #10 ;load A with 10
STA JOE ;store it to JOE
LDA #5 ;load A with 5
STA ROB ;store it to ROB
LDA JOE ;load A with JOE
CLC ;clear the carry flag, for addition
ADC ROB ;add ROB to A
STA JUMP ;store the result to JUMP
LDA ROB ;load A with ROB
CMP JOE ;compare A with JOE
BEQ @NAME ;branch to the label @NAME if equal
tokumaru wrote:
Yeah, it can be hard to learn everything at once: 6502 assembly, the NES architecture, the iNES file format, game logic... If you're feeling overwhelmed, starting out with pure 6502 assembly like Banshaku suggested is a good alternative.
When I first tried to learn 6502 assembly some 20 years ago I too was confused as hell... registers and status flags made no sense to my brain, which was only familiar with BASIC and Pascal. I was able to make a couple of NES demos with a bit of animation but it was a lot of trial and error, so I kinda gave up on that. It wasn't until I tried
this 6502 simulator that everything finally made sense to me. I tried all the instructions and watched how they affected the processor's status, and once I understood what all the instructions did, I was able to code a few subroutines that performed actual tasks, such as multiply 2 numbers and return the result. That way I got the hang of how to use those simple instructions to perform more complex tasks, and felt ready to learn more about the NES architecture and everything else.
I'll try the 6502 Simulator, do I put the .nes or the .asm in it?
dougeff wrote:
Quote:
JOE = 10
ROB = 5
JUMP = JOE + ROB
IF JOE == ROB
GOTO @NAME
In Assembly, JOE, ROB, and JUMP could be RAM address, and @NAME is a label that the assembler will give a value to at assembly time. (Omitting some assembly directives to make it easier)
LDA #10 ;load A with 10
STA JOE ;store it to JOE
LDA #5 ;load A with 5
STA ROB ;store it to ROB
LDA JOE ;load A with JOE
CLC ;clear the carry flag, for addition
ADC ROB ;add ROB to A
STA JUMP ;store the result to JUMP
LDA ROB ;load A with ROB
CMP JOE ;compare A with JOE
BEQ @NAME ;branch to the label @NAME if equal
I'm starting to get it little.
So it would be "store #10 to JOE, confirming it into variable like JOE = 10"?
What about X and Y? So the A X and Y is like "three same variables, only purpose is to keep organized in human mentalities on which one is more important than others or certain things"???
My thoughts:
DIM ROOM
BED = 100
LAMP = 10
END ROOM
'===
DIM MAN
TIRE = 0
STR = 0
LVLSTR = STR + 1
HEALTH = 20
IF HEALTH == TIRE
GOTO @GAMEOVER
==================.[[dim?]] $0001
ROOM:
LDA #100 ; Meaning? : Load as in "put" # 100 into variable / register A
STA BED ; Store the variable / Register A, which is stated as # 100 [like A = 100] into BED, which now turns into " BED = 100 " but in style of #100
LDA #10 ; in style of " A = 10 "
STA LAMP ; in style of "LAMP = 10"
ENA ROOM ; [End ROOM?????]
[[org. /dim.???]] $0002
MAN:
LDX #0
LDY #0
STX TIRE
STY STR
INC STR ; [[ INC X??? ]]
[[I'm a little fuzzed afterward about IF THEN part.]]
DocWaluigean wrote:
I'll try the 6502 Simulator, do I put the .nes or the .asm in it?
NES code won't work, because this emulates just the 6502 (and a rudimentary I/O system). It can load ASM files, but since each assembler is different, code written for other assemblers won't work on it without modifications. It has an integrated editor, so you'd normally type code in the program itself rather than in a separate text editor.
Banshaku's suggestion is probably a better place to start if you want an accompanying tutorial.
DocWaluigean wrote:
unregistered wrote:
DocWaluigean wrote:
Thanks for PDF!
But this is what I don't understand.
Is it a separate engine, like the Address? Or is it a form of abilities like RAM or DATA styles?
Like how does the register of A X Y [and P Z ] works? Or they work as a special form of variables like, a temporary placement of " A = X + Y" until the new replacement happens like "STA" or "LDA"?
I don't like to say this much, but can you explain like if I'm in Elementary School to help me understand about register? [It's very owned variables, like no other regular variables can use?]
Or it's like a "magic effects" but in programming, like the A represent the stages of Mario Bros. your in, X represent your health, and Y represent your Mario life?
I'm sorry I can't explain registers to you in elementary school logic because I didn't learn about registers until college. But, I can try.
The processing chip that the NES uses is called the 2A03. The 2A03 is a special type of the 6502 processing chip. (For instance, it doesn't have the b flag in its status register and its d flag is pointless too, but those aren't important now.) The three 6502 registers I'm attempting to explain are A, X, and Y. Each of the registers are created with 8 bits. Every bit comes from a transistor. If a bit's transistor holds an electrical charge, the bit is set and that translates into a 1. Otherwise, the bit's transistor lacks an electrical charge then the bit is clear and so we have a 0. Ever hear of computers being all 1s and 0s?
The numeral system Binary is an easy, but lengthy way, of telling the NES's 2A03's A register what to hold. If your program tells the NES:
lda #%00000001 that will set bit0 of register A and clear register A's bits 1 through 7.
Bits in a register are named
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1| bit0 |. Yes, that's right to left, but use it enough an you'll get used to it.
There are two other ways of describing the value, you want loaded into register A, to the assembler: Hexidecimal and Decimal.
Before you click on this link read the paragraph sections above carefully.
https://betterexplained.com/articles/numbers-and-bases/Now I will close by saying that the three 8bit-wide registers A, X, and Y are located on the NES's 2A03 processing chip. There is the simplest way I can fully explain a register. Perhaps someone else can help you more.
I thought 2A03 is primary used for default sound and audio creations engine inside NES.
The 2A03 does include an APU (Audio Processing Unit) for default sound and audio creations, but the 2A03's meat and potatoes is its 6502 processing architecture.
DocWaluigean wrote:
So it's just an on and off switch like 0s and 1s?
Yes, registers on the NES are just groups of 8 "on and off" switches.
DocWaluigean wrote:
What is the differences or limitations compare to other engine like PS2 or PC or C#?
I've never programmed on the PS2, but every computer (i.e. PS2 or PC) has at least one processing chip that contains a number of registers. After you write a program in BASIC you have to "compile" it in order to run your program. A compiler takes your programming code (i.e. BASIC code) and translates it into assembly language
that's able to run on the processing chip(s) that your compiler is working with and then into 1s and 0s so that it can be run on whatever computer-type-machine you compile it on. Some of those 1s and 0s are fed into registers that are within whatever processing chip(s) your computer-type-machine uses. C# is a programming language that needs to be translated by a compiler.
The NES is different, for me, because I try to write code for the NES using assembly language. Assembly language is already assembly language; it doesn't need to be translated by a compiler. Assembly language does, however, need to be assembled into 1s and 0s by an assembler. But, assembling is much more precise than compiling because:
1.) a compiler
translates programming code (i.e. BASIC code) into assembly language
2.) and assembly language gets to skip the inefficient compiler translation process entirely.
Hope that helps you understand how the 2A03 compares with "PS2 or PC or C#".
edit.edit2: fixed all of my mispellings of machine (was "machiene", sorry
)
final edit: You asked for elementary school teaching so here is a translation of:
Quote:
2.) and assembly language gets to skip the inefficient compiler translation process entirely.
Using a compiler to translate programming code (i.e. programming languages such as BASIC or C or C++ or C#) *can* create a much slower and larger program than if you spent the time needed to understand and make wise use of the assembly language that runs on the processing chip(s) in the machine you are trying to program for.
I just read that some compilers try to focus on things like speed or for the generated program being useable on many different kinds of machines. Compilers create 1s and 0s based on what they are focusing on. I don't know anything about using compilers to create NES games, I'm sorry.
So judging by what I wrote, did it look alright by using A X Y register examples? Or I did the wrong way of examples of A X Y Register?
DocWaluigean wrote:
TIRE = 0
STR = 0
...
LDX #0
LDY #0
STX TIRE
STY STR
INC STR ; [[ INC X??? ]]
ldx #0 means load a value of 0 into the X index register. Same goes for
ldy #0 but into the Y index register.
stx TIRE means store (write) the current X index register value into the memory location represented by
TIRE. If
TIRE was declared as being equivalent to memory location $1234, then this would become
stx $1234 (in English: write value 0 to memory location $1234).
But in your code, you've said
TIRE = 0, which essentially means
TIRE = $00 or
TIRE = $0000 (there's of a difference between these two, sort of, but don't worry about that right now), so in this case the result would be
stx 0, which is the same as
stx $00 (in English: write value 0 to memory location $0000).
Same situation for
sty STR but with the Y index register, etc..
Then, in the same code, you also say
STR = 0. So now literally
TIRE and
STR both refer to memory location 0. This is probably not what you want (see below).
inc STR increments the value at memory location
STR by 1. So this is the same as
inc $00 basically. Under the hood, the CPU does the equivalent of "read value from memory location $00, increment it by one, write it back to memory location $00" (but without using a register). You could do the exact same yourself in code by doing something like:
lda STR clc adc #1 sta STR.
I believe when you wrote
TIRE = 0 and
STR = 0, you were thinking "how can I pre-assign a value of a variable", because that's what other programming languages let you do -- they hide what goes on under the hood, instructions that are generated internally by the compiler or interpreter. In assembly language, these are called
EQUates, which is why you can say something like
TIRE = 0 or
TIRE EQU 0 -- they mean the same thing. Equates are only expanded at
assemble time, not at run-time. Understanding the difference is important!
Equates can be used in many different ways, not just as "memory locations". They can be used as literal values, or even pre-calculated values. I'll give an example below.
It just so happens that on the NES, memory location $00 happens to be RAM (in fact, it's something called zero page, but that's still advanced so ignore that for now).
RAM on the NES ranges from memory locations $0000 to $07FF (so that's 2KBytes).
If you wanted to give all of your variables their own unique memory locations, you'd do something like this:
Code:
TIRE = $00 ; Memory location $00
STR = $01 ; Memory location $01
MAN = $02 ; Memory location $02
SNAKE = MAN+1 ; Memory location $03
; Initialise all the above variables to 0
lda #0
sta TIRE
sta STR
sta MAN
sta SNAKE
; Increment MAN by 1 (MAN now contains value 1)
inc MAN
; Load the literal address of SNAKE into the accumulator, i.e. lda #$03
lda #SNAKE
The last line will probably confuse you. Note the
# (hash mark). It indicates what's called an "immediate value" (a.k.a. literal value). This is how you tell the assembler what kind of access method to use, a.k.a. addressing mode. Here's a better way to demonstrate it with regards to what I said. Note the difference between the
lda lines:
Code:
MYVAR = $1e
lda MYVAR ; Load the contents of memory location $1E into the accumulator (i.e. A = whatever memory location $1e contains)
lda #MYVAR ; Load literal value $1e into the accumulator (i.e. A = $1e)
These literally become the following lines:
Code:
lda $1e
lda #$1e
...and as such, the assembler assembles these into two completely different results:
lda $1e assembles into bytes
a5 1e, while
lda #$1e assembles into bytes
a9 1e. See the difference? The instructions are identical (
lda), but the opcodes (due to addressing modes) differ. The former addressing mode is called "zero page addressing", while the latter is called "immediate addressing". That's how the CPU knows what to do with each subsequent byte (operand).
That's probably enough for one day. Real-time comparisons are a whole other subject (e.g. trying to do
if HEALTH == TIRE, but in 6502). I think understanding the above is more important, as well as understanding addressing modes (there are several, and many limitations! Some instructions can only use certain addressing modes or certain registers, for example).
Edit: lots of them.
^
DocWaluigean wrote:
I'm starting to get it little.
So it would be "store #10 to JOE, confirming it into variable like JOE = 10"?
Yes.
DocWaluigean wrote:
My thoughts:
DIM ROOM
BED = 100
LAMP = 10
END ROOM
'===
DIM MAN
TIRE = 0
STR = 0
LVLSTR = STR + 1
HEALTH = 20
IF HEALTH == TIRE
GOTO @GAMEOVER
==================
.[[dim?]] $0001
ROOM:
LDA #100 ; Meaning? : Load as in "put" # 100 into variable / register A
STA BED ; Store the variable / Register A, which is stated as # 100 [like A = 100] into BED, which now turns into " BED = 100 " but in style of #100
LDA #10 ; in style of " A = 10 "
STA LAMP ; in style of "LAMP = 10"
ENA ROOM ; [End ROOM?????]
Code:
;I haven't a clue what "DIM" is... but here is what I think you want (in asm6 format)
; iNES header
.byte "NES", $1a
; Number of PRG-ROM blocks
.byte $02 ;2 16kb blocks (32kb from $8000 to $FFFF)
; Number of CHR-ROM blocks
.byte $01 ;1 8kb space for character graphics (when using Mapper #00)
; ROM control bytes: Vertical mirroring, no PRG-RAM, no trainer, Mapper #00
.byte %00000001, $00
; Filler
.byte $00, $00, $00, $00, $00, $00, $00, $00
.enum $0000 ;declare names for variables starting at beginning of the zeropage (location $0000)
BED .dsb 1 ;BED is now at location $0000
LAMP .dsb 1 ;LAMP is now at location $0001
.ende ;ends this variable declaration section
.org $C000 ;start code following at location $C000
reset: ;code that runs when the power button is pressed (or when the game is loaded) and each time your game is reset
sei ;sets interrupt flag
cld ;clears decimal flag because decimal mode on the NES is pointless (a feature of the 2A03)
; Wait two VBLANKS.
- bit $2002
bpl -
; Clear out RAM.
lda $00
ldy $00
- sty $000, y
sty $100, y
;usually, RAM page 2 is used for the display list to be copied to OAM. OAM needs to be initialized to $EF-$FF, not 0, or you'll get a bunch of garbage sprites at (0, 0).
sta $300, y
sta $400, y
sta $500, y
sta $600, y
sta $700, y
iny
bne -
- bit $2002
bpl -
rti ;end reset
MainLoop:
jsr ROOM
jmp MainLoop
ROOM:
lda #100 ;yes, this loads the A register with #100 (A = #100)
sta BED ;$0000 = #100
lda #10
sta LAMP ; $0001 = #10
rts ;ends function ROOM
vblank:
rti ;ends vblank
nmi:
rti ;ends nmi
.pad $FFFA ; <will fill all the ROM from the byte (a byte is 8 bits of info) after NMI's rti up to $FFFA with 00s.
.word vblank, reset, irq ;these 3 words (a word is 16 bits of info) will close your program and cause the NES to know where to find your vblank, reset, and nmi code.
; CHR-ROM
.include "your4kb_backgroundFile.chr"
.include "your4kb_spritesFile.chr"
This program will just constantly
jsr ROOM over and over.
Could be made faster if you copied the contents of ROOM (everything between ROOM: and its rts and pasted them in place of jsr ROOM because jsr and rts each take 6 cycles and are pointtless because your NES file is really empty right now.When you have more experience:
1.) look at
http://wiki.nesdev.com/w/index.php/INES to read more about the iNES header at the top
2.) look at
http://wiki.nesdev.com/w/index.php/Mapper to maybe choose a different mapper; you are using mapper 000
http://wiki.nesdev.com/w/index.php?title=INES_Mapper_000I don't have time to use your second part but for the most part it looked ok to me.
Hope this helps your NES journey.
^Notes about code in my previous post:
1.) It's untested.
2.) The two chr files .incbin'ed at the end are pointless, right now, because that section of code doesn't have functions that draws the background and that draws the sprites. Just put them there so you would know where to place them when you get around to needing them.
3.) I don't think the Simulator that tokumaru recommends allows .include or .incbin so just comment those lines. Comments usually start with
; and the rest of the line following a
; isn't assembled. If you comment the two .incbin lines maybe you could add
.pad $12000, to the end, to fill that 8kb ($10000 to $12000) with 0s. That may help the Simulator, I don't know.
When using the Simulator you should also probably replace the "nameless"
- lables, those only work with asm6, I think.
4.) That code is written in asm6 format.
5.) You could try running that code, after assembling into a .nes file with asm6, in the Mesen emulator and click Options>Preferences then click the box at the bottom next to "Enable developer mode". After doing that, click Debug>"Memory Tools" and then, in the window that opens, the upper left corner should constantly be red because byte $0000 and byte $0001 are constantly being written to. The latest Mesen can be found here:
https://ci.appveyor.com/project/Sour/mesen/build/artifacts.
Sour's Mesen thread:
http://forums.nesdev.com/viewtopic.php?f=3&t=13844edit: about #3, just commenting those .incbin lines should be enough. When you get around to using them add labels before each file and then you can implement Sprite DMA. But, don't worry about that now. Sprite DMA isn't being used and so just commenting those two .incbin lines should work excellently and you don't need the .pad $12000, I think.
edit2: Those two .include should be .incbin because chr files are binary files
, not text files . Sorry, I made some mistakes
while trying to help you.
final edit.
Verrryyy much post and I'm confused easily, when I just want to know if I did the examples of A X Y register right.
But, what is the complete abilities or restrictions differs of A X Y [and other 2 registers?]
A, X, and Y can all hold a single value in the range of 0 to 255. (Edit: 128 to 255 can optionally be interpreted as -128 to -1.) They can all load their value from and store their value to a specific location in memory.
A value in A can be manipulated in many ways X and Y can't be. (Addition and subtraction of any value, division and multiplication by 2 and other "bitwise operations".) If you wanted to do those things to a value in X or Y, you'd have to transfer them to A first, manipulate them, then transfer them back.
You can add and subtract exactly 1 from the value in X or Y. (A allows for adding and subtracting of any value.)
A also has more power to load and store its value to neighbors of a specific location in memory. If you're familiar with arrays, the value in X and Y can be used as an offset to access a specific array element. Y specifically allows a convenient way to access an array through a pointer. If that doesn't mean anything to you right now, that's totally fine.
The other registers are
1. Program Counter, which a programmer doesn't really work with directly. (JMP directly changes it, I guess...)
2. Stack Pointer, which until one learns a bit more is touched once at the start of the program and then not worked with directly.
3. Processor Status Flags. These are individual bits that are updated after each instruction is run. You can "branch" conditionally based on whether individual bits are true are false, which is basically how "if statements" can be constructed.
DocWaluigean wrote:
Verrryyy much post and I'm confused easily, when I just want to know if I did the examples of A X Y register right.
unregistered wrote:
Code:
.enum $0000 ;declare names for variables starting at beginning of the zeropage (location $0000)
BED .dsb 1 ;BED is now at location $0000
LAMP .dsb 1 ;LAMP is now at location $0001
.ende ;ends this variable declaration section
...
ROOM:
lda #100 ;yes, this loads the A register with #100 (A = #100)
sta BED ;$0000 = #100
lda #10
sta LAMP ; $0001 = #10
rts ;ends function ROOM
...
I don't have time to use your second part but for the most part it looked ok to me.
Sorry DocWaluigean, too much post from me.
edited once to add some relevant code in my quote.
unregistered wrote:
DocWaluigean wrote:
Verrryyy much post and I'm confused easily, when I just want to know if I did the examples of A X Y register right.
unregistered wrote:
Code:
.enum $0000 ;declare names for variables starting at beginning of the zeropage (location $0000)
BED .dsb 1 ;BED is now at location $0000
LAMP .dsb 1 ;LAMP is now at location $0001
.ende ;ends this variable declaration section
...
ROOM:
lda #100 ;yes, this loads the A register with #100 (A = #100)
sta BED ;$0000 = #100
lda #10
sta LAMP ; $0001 = #10
rts ;ends function ROOM
...
I don't have time to use your second part but for the most part it looked ok to me.
Sorry DocWaluigean, too much post from me.
edited once to add some relevant code in my quote.
It's alright! I appreciate it though.
I'm going to see something else about it, I'm going toward Week 4 now.
Ok, I'm still on Week 4 because I just got NES Classic Editions, and I'm loving it so much. The fact I got Mario Adventure from DahrkDaiz [I wish xhe can tutor me xer style of 6502 programming] made me so happy, I didn't read any at all, just play play play.
Right now, I'm burned out from playing it, and I'm worried if that will affect my concentrations in trying to learn to make NES games. Anyone have tips?
DocWaluigean wrote:
Ok, I'm still on Week 4 because I just got NES Classic Editions, and I'm loving it so much. The fact I got Mario Adventure from DahrkDaiz [I wish xhe can tutor me xer style of 6502 programming] made me so happy, I didn't read any at all, just play play play.
Right now, I'm burned out from playing it, and I'm worried if that will affect my concentrations in trying to learn to make NES games. Anyone have tips?
After months of no responses of motivations here, I got it back as I saw the NESMaker and the RIKI Japanese home-brew game; it helps me get back in now...
Going to have to re-read the Nerdy Nights again, and this thread again...
Onto Night 3; This is going to be ridiculous because I may ask so many questions. I will try this one from background.asm in the Nerdy Nights Week 3.
Remember - the only dumb question is the question that remains unasked.---
Code:
.inesprg 1 ; 1x 16KB PRG code
.ineschr 1 ; 1x 8KB CHR data
.inesmap 0 ; mapper 0 = NROM, no bank swapping
.inesmir 1 ; background mirroring
-So the iNES header is an information. But I'm assuming this ines only works in the ASM6.
-Is there a limit to numbers for each codes beside inesmap? I'm sure you can go up to inesmap 255 something with Namco mapper, Konami mapper, Sunsoft mapper, etc.
-So PRG code is "assign scripts to sprites, by limit"? and CHR data "the amount of sprite and tile banks"? ineschr 1 = 1 bank of tiles/sprites? can it go up to over 128?
-Obviously a good idea to ignore for now, but is there importances for inesmir 1?
---
Universal question:
At which part is needed to show the entire gray screen? Up to ines? need bank 0, 1, and 2 to make a correct blank NES?
Code:
.bank 0
.org $C000
RESET:
SEI ; disable IRQs
CLD ; disable decimal mode
LDX #$40
STX $4017 ; disable APU frame IRQ
LDX #$FF
TXS ; Set up stack
INX ; now X = 0
STX $2000 ; disable NMI
STX $2001 ; disable rendering
STX $4010 ; disable DMC IRQs
vblankwait1: ; First wait for vblank to make sure PPU is ready
BIT $2002
BPL vblankwait1
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
STA $0300, x
INX
BNE clrmem
vblankwait2: ; Second wait for vblank, PPU is ready after this
BIT $2002
BPL vblankwait2
LDA #%10000000 ;intensify blues
STA $2001
Forever:
JMP Forever ;jump back to Forever, infinite loop
NMI:
RTI
-----
-Obviously the $C000 is in the cartridge ROM section, which is fine. But why is it in $C000 instead of $8000, which is more organize than in the middle of those code? I know in some sections, the address represent something for the NES "lever and buttons", like $3F10 - $3F1F is the address section for color palettes. But for the Cartridge ROM, why isn't there an overview for the entire Address beside PPU?
-I been looking further before reading back on Nerdy Nights,
LDX #$40
STX $4017 ; disable APU frame IRQ
LDX #$FF
Why is it arranged like this instead "LDX, LDX, STX"? Obviously high and low power style, but why? For new people, it could mess up a code like this... I don't want to be judgeful, but coding is one of the hardest things I ever got to learn in my life.
Code:
;;;;;;;;;;;;;;
.bank 1
.org $FFFA ;first of the three vectors starts here
.dw NMI ;when an NMI happens (once per frame if enabled) the
;processor will jump to the label NMI:
.dw RESET ;when the processor first turns on or is reset, it will jump
;to the label RESET:
.dw 0 ;external interrupt IRQ is not used in this tutorial
;;;;;;;;;;;;;;
.bank 2
.org $0000
.incbin "mario.chr" ;includes 8KB graphics file from SMB1
---
Because of "peer pressure" situations, I can't even ask any questions about .dw, .nmi, and other situations.
-------
I know you guys literally sick and tired of hearing this about anyone like me requesting for a private tutor, but there's people like me who has capacities to do something very complex, like 3D modelling, ideas, free-writing storytellings, etc. But can't understand forms of writings and tutorials that keeps backing away from learning NES assembly languages.
As for people who said, "please do some research on your own now.", there's people like me who literally tried to comprehend writings from Bunnyboy, Easy6502, etc. that literally needs help, whose real serious in learning about this stuff. I got lucky on understanding what binary, HEX, and decimals do, and nearly all forms of Codes Layout, but further readings just threw me off with words that I can't put two and two together. I'm even willing to make a tutorial that's more comprehend-able than BunnyBoy if I understand everything.
DocWaluigean wrote:
-So the iNES header is an information. But I'm assuming this ines only works in the ASM6.
The .ines*** directives only exist in NESASM. In most other assemblers people just create the header using .db/.byte statements. It's also possible to create macros that simulate NESASM's directives.
Quote:
-Is there a limit to numbers for each codes beside inesmap? I'm sure you can go up to inesmap 255 something with Namco mapper, Konami mapper, Sunsoft mapper, etc.
Mapper numbers are normally assigned by whoever discovers/creates them. The wiki has a list of the most popular mappers:
https://wiki.nesdev.com/w/index.php/List_of_mappersThe limits for the other fields will depend on the mapper. Each mapper supports different amounts of PRG and CHR stand use different techniques for bankswitching them.
Quote:
-So PRG code is "assign scripts to sprites, by limit"?
The PRG field is the amount of PRoGram-ROM, measured in units of 16KB. This is the memory used to hold the game program, the code that the CPU runs to make stuff happen. All the game logic is here, along with all the data used by the game (e.g. levels, music, etc.).
Quote:
and CHR data "the amount of sprite and tile banks"?
Yes, that's the amount of CHaRacter-ROM, measured in units of 8KB (512 tiles).
Quote:
ineschr 1 = 1 bank of tiles/sprites? can it go up to over 128?
Don't get too hung up on the term "bank" here, since the size of a bank varies from mapper to mapper. CHR-ROM banks can be any of 8KB, 4KB, 2KB or 1KB, but the INES header always measures the total amount in multiples of 8KB, regardless of the mapper.
How high you can go will depend on the mapper. 128 x 8KB would be 1MB, and not many mappers support that. Another thing to keep in mind is that even though the total amount of tiles can be significantly high, you can't use any tile you want whenever you want, because the NES still only sees a small number of them at a time. The way in which you select which tiles will be usable at any given time will depend on the mapper.
Quote:
-Obviously a good idea to ignore for now, but is there importances for inesmir 1?
The NES has a virtual background space of 4 screens arranged in a 2x2 grid, but it only has enough memory to hold 2 screens, which means that 2 of those 4 will have to be repeats. The mirroring setting selects whether the screens will repeat horizontally or vertically.
Quote:
Universal question: At which part is needed to show the entire gray screen? Up to ines?
I don't understand the question. What do you mean by "entire gray screen"?
Quote:
need bank 0, 1, and 2 to make a correct blank NES?
Memory chips are only manufacred in sizes that are powers of 2 (e.g. 8KB, 16KB, 32KB, 64KB, 128KB, etc.), so you need to have a number of banks that adds up to a power of 2 in order to represent a valid memory chip, even if they are empty.
Do note that NESASM's .bank directive creates banks that are 8KB in size, while the INES header counts banks that are 16KB. So in this case, NESASM banks 0 and 1 would be the one 16KB bank defined via .inesprg, and bank 2 is the one 8KB bank defined via .ineschr.
Like I said, don't focus too much on the work "bank" as used by NESASM and the INES header, because the actual size of the banks is defined by the bankswitching scheme of the mapper you use. Just think of INES banks as units for counting, and NESASM's banks as blocks of 8KB, which won't necessarily be manipulated individually.
Ninja'd by tokumaru, but the information presented is slightly different, so sure, I'll still post.
DocWaluigean wrote:
Code:
.inesprg 1 ; 1x 16KB PRG code
.ineschr 1 ; 1x 8KB CHR data
.inesmap 0 ; mapper 0 = NROM, no bank swapping
.inesmir 1 ; background mirroring
-So the iNES header is an information. But I'm assuming this ines only works in the ASM6.
On an actual NES catridge, hardware dictates behavior. An NES ROM mostly contains the software. Because there are so many different cartridge types with different hardware, an NES ROM also has a 16 byte "header" that describes the hardware so emulators can properly run it.
The .ines commands are for creating this header. They only work with NESASM, not ASM6. In ASM6 you have to build the header manually.
Quote:
-Is there a limit to numbers for each codes beside inesmap? I'm sure you can go up to inesmap 255 something with Namco mapper, Konami mapper, Sunsoft mapper, etc.
The limit is different for every cartridge type. I don't know of one offhand that allows 255. That's just shy of 4 Megabytes! (16 kilobytes * 255)
Quote:
-So PRG code is "assign scripts to sprites, by limit"? and CHR data "the amount of sprite and tile banks"? ineschr 1 = 1 bank of tiles/sprites? can it go up to over 128?
PRG is just bytes of data the CPU can easily access. You can store code there, levels/text/music/other data there, or even graphics there. (Assuming you are using CHR RAM.)
CHR is bytes of data the PPU can easily access. The amount of sprite and tile banks is a good way to think about it.
Quote:
-Obviously a good idea to ignore for now, but is there importances for inesmir 1?
NES has 4 screens worth of "tilemap" laid out in a 2 by 2 square. (That essentially repeats forever.) However, there can only be 2 unique screens usually. The other two are copies or "mirrors".
Super Mario Bros. has the top and bottom rows of the 2by2 square "mirrored" because it scrolls horizontally. This allows it to easily update the level offscreen to the right of the scroll edge.
Ice Climber has the left and right columns of the 2 by 2 square "mirrored" because it scrolls vertically. This allows it to easily update the level offscreen above the top of the scroll edge.
.inesmir 0 denotes Ice Climber Style.
.inesmir 1 denotes Super Mario Bros. style.
Some cartridge types effectively ignore this.
---
Quote:
Universal question: At which part is needed to show the entire gray screen? Up to ines? need bank 0, 1, and 2 to make a correct blank NES?
You need at least two NESASM banks to create a totally blank ROM, but you will probably want three, yes.
Code:
.inesprg 1
.ineschr 1
.inesmir 0
.inesmap 0
.code
.bank 0
.org $C000
.bank 1
.org $E000
.org $FFFA
.dw 0;This is where you'd put the label where the CPU should jump to when an NMI happens
.dw 0;This is where you'd put the label where the CPU should jump to when the console is reset
.dw 0;This is where you'd put the label where the CPU should jump to when an IRW happens
.bank 2
.org $0000
Should give you an entirely blank ROM. .org tells the assembler where in memory the bytes that follow are meant to go. $FFFA is where it expects certain addresses. This is how the CPU knows where the game starts on reset, for example. You don't technically
need that for a blank ROM, but you may as well have it.
DocWaluigean wrote:
But why is it in $C000 instead of $8000
Because this is probably a 16KB program, and the NES CPU can see 32KB of code, so the same code appears twice in that space. This means that either $8000 or $C000 will work fine, you can use whichever you like best, because in the end, THE CODE WILL APPEAR AT BOTH ADDRESSES. Most people like to think of the program as being aligned to the upper end of the address space though, because the CPU vectors are traditionally accessed at $FFFA-$FFFF, the very end of the ROM area. But like I said, you can use $8000 as the origin for your 16KB program if you prefer, because the vectors will appear at both $BFFA-$BFFF and $FFFA-$FFFF, where the CPU will actually look for them.
Quote:
But for the Cartridge ROM, why isn't there an overview for the entire Address beside PPU?
Here's the memory map for the CPU:
https://wiki.nesdev.com/w/index.php/CPU_memory_mapQuote:
LDX #$40
STX $4017 ; disable APU frame IRQ
LDX #$FF
Why is it arranged like this instead "LDX, LDX, STX"?
Because programming is basically moving numbers around and doing math operations on them. For moving data around, we need to use the CPU registers (A, X, Y). We need to send a number/code to the APU, telling it to disable frame IRQs, so we put this number in a register (LDX), and then store that register (STX) in the appropriate APU port. That part is done, we can now use X for other stuff, so we put the next value we'll use in it, $FF, that we'll use to initialize the stack pointer. This is just moving data around. If you mess up the order, you'll end up putting the wrong values in the wrong places.
Quote:
high and low power style
What is "high and low power style"?
DocWaluigean wrote:
I'm even willing to make a tutorial that's more comprehend-able than BunnyBoy if I understand everything.
You'd be surprised by how many people have said that, but either "forgot" or just gave up on NES development.
It's not easy to word this stuff in simpler terms, because this really isn't a simple subject. You can't replace terms like registers, mirroring, addressing, etc. by simpler ones because they describe unique things and behaviors that don't necessarily have counterparts that are easier to comprehend. We can EXPLAIN all the terms and behaviors individually so that when you see them at a later time they won't sound like alien concepts, but programming knowledge is something you build progressively, you have to understand one layer before moving on to the next, you can't skip to the topmost layer and expect things to be worded in a way that circumvents everything established in the layers below.
Tokumaru covered the other post WAY more succinctly than what I was working on.
Quote:
Because of "peer pressure" situations, I can't even ask any questions about .dw, .nmi, and other situations.
I think both Tokumaru and I covered this a bit.
.dw will add a 16byte number you give it to the ROM.
.db will add an 8 bit number you give it to the ROM.
I had mentioned that the CPU looks for addresses starting at $FFFA to know where to start executing code in certain situations. There's no further explanation beyond, "That's how the CPU was designed." It has to start
some known place or software couldn't be run reliably on it. You can use .dw with a label. So if your code looks like:
Code:
.org $E000
reset:
jmp reset
NMI:
rti
IRQ:
rti
.org $FFFA
.dw NMI
.dw reset
.dw IRQ
When you turn the NES on, it will start executing code at $E000. (The reset label.) The NMI (on NES) can happen once every 60th of a second if you have it enabled. This is one thing that allows games on NES to run at a consistent speed.
When a frame is about to start (every 60th of a second) the CPU will stop what it was doing, and go to the address (label) at $FFFA. The RTI will send it back to what it was doing before this happened. The NMI is an "interrupt" (Non Maskable Interrupt). Precisely because it interrupts whatever the CPU was doing and jumps somewhere else. And again, the RTI allows it to return to what it was doing before the interrupt happened.
If some of that doesn't make sense, that's okay for now. You mentioned easy6502. Is there some part you're stuck on in that tutorial? If so, feel free to ask about it. 6502 itself is way easier than the NES hardware, so if you can get working there you might have more progress. There's less to do to get visual output that shows the code is working on the easy6502 website.
Kasumi wrote:
6502 itself is way easier than the NES hardware, so if you can get working there you might have more progress.
I fully agree.
Back when I started, I only knew how to program in QBASIC, and assembly didn't make any sense to me. Learning about hardware architecture and the NES registers at the same time I was learning assembly ended up being way too confusing, and I actually did give up for a few years.
On my second try, I put the NES aside and studied only 6502 assembly, using a simulator, and I didn't move forward until I understood what every instruction did and I was able to code actual algorithms (multiplication, division, sorting, etc.) in that language. Only then did I try to make an NES ROM again.
You see, talking to the NES is like other kinds of communication. Say you are the manager in a company that makes boxes. You must know how boxes are made, so you can tell the workers what they have to do, and you must speak the same language as the workers, so you can effectively communicate the instructions to them. If you don't speak the same language, and you don't know how to make boxes, it will be extra hard to end up with something that resembles a box in the end.
So yeah, learn assembly first of you can, without the specificities of the NES getting in the way. Then, when you know HOW to communicate, focus on learning WHAT to say to the NES so it does what you want.
And don't forget that in order to make games, you not only need to know the language and the architecture of the environment you're coding for, but also the general concepts of game programming, which are universal to any programming language, such as animation, object management, physics, collision, and so on.
tokumaru wrote:
DocWaluigean wrote:
I'm even willing to make a tutorial that's more comprehend-able than BunnyBoy if I understand everything.
You'd be surprised by how many people have said that, but either "forgot" or just gave up on NES development.
It's not easy to word this stuff in simpler terms, because this really isn't a simple subject. You can't replace terms like registers, mirroring, addressing, etc. by simpler ones because they describe unique things and behaviors that don't necessarily have counterparts that are easier to comprehend. We can EXPLAIN all the terms and behaviors individually so that when you see them at a later time they won't sound like alien concepts, but programming knowledge is something you build progressively, you have to understand one layer before moving on to the next, you can't skip to the topmost layer and expect things to be worded in a way that circumvents everything established in the layers below.
As sadly as I have to agree on the term, there is a form of ambitions in certain people that made them attempt to do those kinds. For many people on "forgot" or just gave up, they didn't find motivations or ambitions, since "it's a waste of time to make tutorial for a dead old program" beliefs or other things.
For me, I have big one, that every time I felt quitting, I only went to sleep to calm myself down, because I feel upset so much for a while since no tutor or any road is there for me. I waited time to try again, and try to explain much differently. The road I always get stuck is 6502 Processor Overview in Week 3.
As I'm predicting you hear this term also, I'm not like any people who have said those kinds. I find much more values in NES programming than before more and more, especially NIKI homebrew games, Mario Adventure 3: Mushroom Mayhem, yet I often struggles with coding without forms of learning styles like mnemonics. It's odd that I understand partially in BASIC, Java[Script], and C#, yet I struggle the most in 6502, even though I feel it's one of hard-to-learn coding languages and it's obvious.
There's a learning styles called VARK where it shows some kind of learning styles for people who learns best of: Visual, Aural, Read/Write, and Kinesthetic. For me, it's possible for, at most, all 4 of it.
Maybe I can't explain well or get you guys to understand where I come from because despite my native tongue is Spanish, I use English majority of my life, and I can't use grammar terms correctly many times. But I can tell ya, I'm a fast learner when I understand something, I really strive for good qualities on something.
As I know tutor is highly discourages or not possible much here because "they have lives" or "they do it for money for teaching", I want to let ya know I'm serious on tutoring, and I'm willing to record and understand details by details to make NES tutorials so good, even children can learn more than what they could do in NESMaker.
It just a good communications between student and tutors for support is really needed to help me understand as "God-Tier" as Shiru, NIKI, and DahrkDaiz, who got me into this homebrew business in the first place.
If you feel I'm not even trying. despite the fact that to other eyes, I may be another person who doesn't care or gives up easily:
-I understood completely with basics of Binary, HEX, and decimals/ natural numbers.
-I understood that the address $ is like a room where you place the codes, and certain "rooms" inside does specific jobs, like the sprite-color decision "room."
-I at least know what Mapper does in certain types, from increasing tile size, to the abilities of making beautiful music using N106.
-INC means increment, which is mathematical technique in increasing number by 1, unless stated.
-I understood that graphic limit is set to 13 colors, with one transparent for each "4" colors, which is 3 colors and 1 transparent, and the screen is 256 X 240, but issues in vertical lines is 256 X 224
and other things about 8X8, 16X16 Sprite limit, where vertical mirror is possible, but not horizontal mirror.
- $ and # symbol is different, where $ is the address, and # is the number-number.
-I somewhat partially understood that A, X, Y is a type of register that "allows you to store numbers [Address? Digits/HEX?] temporary" like forms of transport from one address to another, OR some kind of math abilities that allows you to carry the number using "LDA" and "STA" stuff.
-I partially understood about high-power and low-power byte like what they said on Nerdy Night Week 4:
Code:
The palettes start at PPU address $3F00 and $3F10. To set this address, PPU address port $2006 is used. This port must be written twice, once for the high byte then for the low byte:
LDA $2002 ; read PPU status to reset the high/low latch to high
LDA #$3F
STA $2006 ; write the high byte of $3F10 address
LDA #$10
STA $2006 ; write the low byte of $3F10 address
If I understand the code from BASIC languages with certain opcodes on what it does, like DEC and INC, the same way with the C# programming beginners where they did the "Application > NameSpace > Assembly > Codes", then I have compatibility to understand 6502 languages, but I tend to struggle with certain information that doesn't comprehend to me because it isn't explain well for me, or because, dare I say it, "It's boring to try and read it and remember it."
I just want to put this down just to tell ya what kind of person I am. You could think I'm "autistic moron" or anything like that, or anything that people who has elitist personality could put me down, but I just want to let ya know I'm really trying hard to figure out on codes yet struggle on obstacles, and I'm serious and determined to learn, that I'm willing to be perfect attendances for tutors. Discord, other ways, I'm in.
Even though I know it's high chance that response is very obvious that no tutors is here, or potentially discourages to try to tutor. If there isn't any forms of tutor that can help me learn in very well styles that I could rival Shiru and/or DahrkDaiz in terms of creative codes, I might as well ask so many ridiculous questions on something that's potentially easy here like I did.
It's getting late here atm. So I hope I don't make any errors to explain.
EDIT: I don't ever want anyone, young or old, to go through struggles what I gone through that gives up easily.
I haven't been following this thread closely, but it's not like us to call anyone a moron or anything of the kind. We're always willing to help those who demonstrate they're making progress. What nobody here likes is when we do our best to explain something to someone, taking time from other things we could be doing for ourselves (e.g. working on our own projects, spending time with our families, etc.), and the person's reply makes it clear they didn't even read it all.
What we don't like is when people try to take shortcuts. There are no shortcuts... quite the opposite, really! If you're reading a post or a document, and all the information is flying over your head, you don't just skip and go "yeah, this is not working for me, let's see what's next". You can't go forward if you don't understand what came before. You have to keep reading, over and over until something makes sense. Once something makes sense, read again and more things will make sense.
We're here to help, we can explain things in a different way, we just don't have the time to rewrite every document and tutorial so they're perfect for everyone, and we don't have time to private tutor each person that comes to the forum saying that the information that currently exists is not in line with their favorite way of studying.
Coding games is not an easy task, you'll have to adapt and overcome several hardships, so consider this the first of many problems to overcome. You'll have to adapt and make do with the documentation that exists, because no one will rewrite it all overnight. We'll be here to help when things don't make sense.
tokumaru wrote:
I haven't been following this thread closely, but it's not like us to call anyone a moron or anything of the kind. We're always willing to help those who demonstrate they're making progress. What nobody here likes is when we do our best to explain something to someone, taking time from other things we could be doing for ourselves (e.g. working on our own projects, spending time with our families, etc.), and the person's reply makes it clear they didn't even read it all.
https://forums.nesdev.com/viewtopic.php?f=5&t=6313 I obviously know this person is acting...disrespectfully strange, but I am feeling a little offended when I think about the people calling offensive terms, where despite being on internet, and expect to be civilized, it just gives me impressions where people would just attack me if I was in similar position as him and I was trying to talk what I want to say, like uncomfortable term koitsu gave me, just because I tried to get straight-of-straight information instead of reusing the same answers everyone gets; bunnyboy and Easy6502. Until I signed up, I don't feel comfortable asking for help or try to learn NES by asking. Call me or anyone autism who feel the same way, but I rather never let it be exposed on my appearances.
tokumaru wrote:
What we don't like is when people try to take shortcuts. There are no shortcuts... quite the opposite, really! If you're reading a post or a document, and all the information is flying over your head, you don't just skip and go "yeah, this is not working for me, let's see what's next". You can't go forward if you don't understand what came before. You have to keep reading, over and over until something makes sense. Once something makes sense, read again and more things will make sense.
The thing about this is when I/anyone were to read documents like "Programmanual" and come across sentences that confuses the 6502 with other reference things, it could throw off easily with certain grammar or pronunciations. The only shortcuts I can think of is using mnemonics or "cheat sheets" that tells you what the code does and copy-paste the specific code to make things faster.
Also, if I tried to re-reading in the same place, it will feel like I ain't progressing and demotivation increases as I get stuck. I'm not like average person who could easily understand it; it could take them 2 weeks at most to understand, this could take me about 8 months at most. Maybe I'm wrong or right, but the fact I'm stuck in Week 3 for many times, rarely going to Week 4 or 5, but revert back to week 3, just made me upset.
tokumaru wrote:
We're here to help, we can explain things in a different way, we just don't have the time to rewrite every document and tutorial so they're perfect for everyone, and we don't have time to private tutor each person that comes to the forum saying that the information that currently exists is not in line with their favorite way of studying.
Coding games is not an easy task, you'll have to adapt and overcome several hardships, so consider this the first of many problems to overcome. You'll have to adapt and make do with the documentation that exists, because no one will rewrite it all overnight. We'll be here to help when things don't make sense.
I'm a little unsure about this. It's either I feel I refused to accept this paragraph, or I'm trying too hard to accept and understand, that the fact I tried to learn on something I'm stuck on for long time. I could say, "Maybe I want to be the one who'll rewrite it all overnight if I get real tutor and help.", but it'll just be repeating myself and encourages frown against me.
If that's true about help, where did the "elitist" and "strict" ideologies come from...?
So what if I write to write a storyboard / script of how to learn NES 6502 programming, and I need some form of clarifications?
I responded to one of your posts at 1:10 am. At 1:50 am, was my second response. That's 40 minutes to write just the second post. I also had to read your posts in order to respond. (Maybe obvious, but I feel like people often forget this.) Probably at least an hour of work went into those posts. I could have done anything else in that time.
I've helped people who post source code with basically no context, which means I have to read all their source code which usually does not take a small amount of time.
You have trouble believing some people are here to help? It's a mixed bag of personalities, sure. But that's the only way it can work. I'm not trying to guilt you too much, but I think it's worth
really thinking about the collective time we all spent to create about 35 posts worth of guidance. Imagine if one person decided to do that for you, for free.
If you want a tutor without paying, well, you've got it. You've got
pages of help you didn't pay for. Maybe some of it's a little tough love, but again. Really think about what you've received here already.
This is extra! This is
in addition to the
free resources that already exist. Like that often repeated answer of easy6502. You think it's bad when we recommend easy6502 a lot? The alternative is rewriting easy6502! It's much easier to answer your questions about it than rewrite it.
What are your questions about it? Where are you stuck? These are not rhetorical questions!
Quote:
Also, if I tried to re-reading in the same place, it will feel like I ain't progressing and demotivation increases as I get stuck.
Then ask. If there's anything about my posts you don't understand. ASK! I spent the hour because I want to help. If you don't understand the help, do you really think I'd rather have you struggle in silence after already investing in you? Ask!
And the beauty of this is that if I ever start to feel drained by the time spent, there's an army of people just as knowledgeable or more knowledgeable who can fill my shoes while I recharge. Tokumaru and I were basically
racing to help you first! Think about it!
I'll leave you with this:
viewtopic.php?f=10&t=7451&start=1290&hilit=metatile This is a 97 page thead spanning 7 years that primarily serves the purpose of helping just one person. I'll even say I've lost my patience in the thread
, but honestly we mostly really do just want to help.
DocWaluigean wrote:
I'm even willing to make a tutorial that's more comprehend-able than BunnyBoy if I understand everything.
I have never read Nerdy Nights, so I might be completely wrong about this, but is it possible that it was never a particularly good tutorial to begin with? Either way, programming for the NES is not so much about programming, as it's about understanding the hardware, and it's hard for any tutorial to cover this. You need documentation if you don't want to end up with more questions than you have answers.
To be honest, I never even heard of Nerdy Nights before I had already learned what it attempts to teach. But whenever it's brought up, it's usually among newcomers who have been following it, and have a ton of questions based on it. Questions which are all answered on the Nesdev wiki, too.
As far as I'm aware, it was written quite some time ago, and doesn't really follow a lot of the standards that are usually recommended procedure (such as separating game logic from NMI), as well as relying on Nesasm, which a lot of people aren't fans of (I am not familiar with this either, but I like CA65 well enough to never move away from it).
I think a big source of the problem is that people open up the tutorial and expect to learn everything from it. It's no wonder they come out with questions. I can't imagine any tutorial being thorough enough to make you understand everything going on in a piece of video game hardware, but what do I know.
Here's what I did.
My approach might not be good for everyone, but it worked for me. I basically familiarized myself with every major aspect of the NES hardware (aside from sound generation) before picking up an assembler. That doesn't mean knowing all the ins and outs, but it meant being familiar with the concepts before eventually running into them. If you don't know what a nametable, OAM buffer or attributes are, you're not gonna get far. I browsed through all the most interesting pages of the Nesdev wiki, learning how stuff worked. This was primarily video output, but the NMI and controller reading was of course important too. I just did this here and there in my spare time, over a few days. At the point, this was my end goal, so maybe that made it easier for me, but it wasn't until I realised how basic the hardware actually was that I figured I should take it further and try making something.
Then I learned 6502 independently from the NES hardware, which was pretty much required, but also pretty simple (
this guide is excellent), and finally I just downloaded a blank template of a working NES game, and mucked about in it for a few hours.
Those last two steps was just one evening, but depending on how familiar you are with programming in general, it can take however long you feel is necessary. And of course it took me probably another week to get something really working and playable, but at that point the thing I had made was entirely my own thing, not following somebody's tutorial. And I never had any questions, because everything I made was based on individual and well documented examples from the Nesdev Wiki. Ok, so I did have a lot of stuff that I needed to look up, but nothing that hadn't already been discussed in details, so it was pretty easy to search for older forum threads.
That said, everyone here is happy to answer questions, and like you said yourself - the only stupid question is the one that remains unasked. People don't mock people for their lack of knowledge, unless said people act like they know it all despite of it.
Kasumi wrote:
I responded to one of your posts at 1:10 am. At 1:50 am, was my second response. That's 40 minutes to write just the second post. I also had to read your posts in order to respond. (Maybe obvious, but I feel like people often forget this.) Probably at least an hour of work went into those posts. I could have done anything else in that time.
I've helped people who post source code with basically no context, which means I have to read all their source code which usually does not take a small amount of time.
You have trouble believing some people are here to help? It's a mixed bag of personalities, sure. But that's the only way it can work. I'm not trying to guilt you too much, but I think it's worth
really thinking about the collective time we all spent to create about 35 posts worth of guidance. Imagine if one person decided to do that for you, for free.
If you want a tutor without paying, well, you've got it. You've got
pages of help you didn't pay for. Maybe some of it's a little tough love, but again. Really think about what you've received here already.
This is extra! This is
in addition to the
free resources that already exist. Like that often repeated answer of easy6502. You think it's bad when we recommend easy6502 a lot? The alternative is rewriting easy6502! It's much easier to answer your questions about it than rewrite it.
What are your questions about it? Where are you stuck? These are not rhetorical questions!
Quote:
Also, if I tried to re-reading in the same place, it will feel like I ain't progressing and demotivation increases as I get stuck.
Then ask. If there's anything about my posts you don't understand. ASK! I spent the hour because I want to help. If you don't understand the help, do you really think I'd rather have you struggle in silence after already investing in you? Ask!
And the beauty of this is that if I ever start to feel drained by the time spent, there's an army of people just as knowledgeable or more knowledgeable who can fill my shoes while I recharge. Tokumaru and I were basically
racing to help you first! Think about it!
I'll leave you with this:
https://forums.nesdev.com/viewtopic.php ... t=metatile This is a 97 page thead spanning 7 years that primarily serves the purpose of helping just one person. I'll even say I've lost my patience in the thread
, but honestly we mostly really do just want to help.
For people with difficulties to explain well, one part of me say it's very aggressive, and I should give up. Another part is I deserve this replies, and another say it's tough love, like you said, and so on and so on.
Let me try and explain. Even though my reaction has partial negativity reading it, it's somewhat difficult to explain it, because I could just not reply it, but in turn, gives the feeling that I'm like everyone who gives up so easily, which I never want to be those.
I have one of the biggest questions where it's incredibly obvious to know, yet I chose to ask it, and go deeper. I could tell you that I may get offended or criticized just for leeching or pulling many strings just to finally understand something. I'm not saying you do or something, but you want me to try and go full on questions and expect offensive replies about my knowledge or something, when I want to understand much deeper than before? There's a Japanese communities with more love on NES/FCU and they go ironman on everything, especially this 3 videos:
https://youtu.be/FuQc1xpx78c?t=0s https://www.youtube.com/watch?v=hi4MM1E5f7E https://www.youtube.com/watch?v=xMB5FK2YMVA yet I do not see super friendly tutorials that can work with even a toddler worldwide[?].
It made me feel so ashamed that no one feels the love to put enjoyment in coding as those communities, and I really want to boost the qualities of games, especially NES, by making 6502 much easier to learn. But the way of explaining has chances of criticizing me. It could made me feel demotivated to even figure out making tutorials about it. Even though I know chances of ignorance may shown about what I'm talking about.
I'm a little confused on how to explain well to you.
---
Sumez wrote:
DocWaluigean wrote:
I'm even willing to make a tutorial that's more comprehend-able than BunnyBoy if I understand everything.
I have never read Nerdy Nights, so I might be completely wrong about this, but is it possible that it was never a particularly good tutorial to begin with? Either way, programming for the NES is not so much about programming, as it's about understanding the hardware, and it's hard for any tutorial to cover this. You need documentation if you don't want to end up with more questions than you have answers.
To be honest, I never even heard of Nerdy Nights before I had already learned what it attempts to teach. But whenever it's brought up, it's usually among newcomers who have been following it, and have a ton of questions based on it. Questions which are all answered on the Nesdev wiki, too.
As far as I'm aware, it was written quite some time ago, and doesn't really follow a lot of the standards that are usually recommended procedure (such as separating game logic from NMI), as well as relying on Nesasm, which a lot of people aren't fans of (I am not familiar with this either, but I like CA65 well enough to never move away from it).
I think a big source of the problem is that people open up the tutorial and expect to learn everything from it. It's no wonder they come out with questions. I can't imagine any tutorial being thorough enough to make you understand everything going on in a piece of video game hardware, but what do I know.
Here's what I did.
My approach might not be good for everyone, but it worked for me. I basically familiarized myself with every major aspect of the NES hardware (aside from sound generation) before picking up an assembler. That doesn't mean knowing all the ins and outs, but it meant being familiar with the concepts before eventually running into them. If you don't know what a nametable, OAM buffer or attributes are, you're not gonna get far. I browsed through all the most interesting pages of the Nesdev wiki, learning how stuff worked. This was primarily video output, but the NMI and controller reading was of course important too. I just did this here and there in my spare time, over a few days. At the point, this was my end goal, so maybe that made it easier for me, but it wasn't until I realised how basic the hardware actually was that I figured I should take it further and try making something.
Then I learned 6502 independently from the NES hardware, which was pretty much required, but also pretty simple (
this guide is excellent), and finally I just downloaded a blank template of a working NES game, and mucked about in it for a few hours.
Those last two steps was just one evening, but depending on how familiar you are with programming in general, it can take however long you feel is necessary. And of course it took me probably another week to get something really working and playable, but at that point the thing I had made was entirely my own thing, not following somebody's tutorial. And I never had any questions, because everything I made was based on individual and well documented examples from the Nesdev Wiki. Ok, so I did have a lot of stuff that I needed to look up, but nothing that hadn't already been discussed in details, so it was pretty easy to search for older forum threads.
That said, everyone here is happy to answer questions, and like you said yourself - the only stupid question is the one that remains unasked. People don't mock people for their lack of knowledge, unless said people act like they know it all despite of it.
I see. I got almost no replies about hardware understanding, since I want to make NES programs first before hardware. Possibly obvious replies from every beginner. only replies is if anyone from outside Japan ever make usage of custom sound chips made?
http://wiki.nesdev.com/w/index.php/Nesdev_Wiki NESDev Wiki has so many unfinished content, it's very frustrating to do things myself, "to be written"... I been NESDev for around decade, and it almost never changes.....
Possibly, those people got big dreams to achieves, yet failed short after certain issues. Life? Emotions? other things. I agree on what you said though.
Nametable is [the final ingredients before converting into usable applications?] And I'm sort of understanding what you said.
Your literally lucky you understand things that I don't.
I'm jealous.
I see.. tell me if it's alright to go overboard. Because maybe I have to draw pictures and everything I can so I can see if it looks correct.
Quote:
You think it's bad when we recommend easy6502 a lot? The alternative is rewriting easy6502! It's much easier to answer your questions about it than rewrite it.
What are your questions about it? Where are you stuck? These are not rhetorical questions!
Seriously! I don't think you should expect offensive replies, but say one person is mean and one person gives you an answer. You've won!
We could go deep about the philosophical nature of public question asking, but I'd rather just answer your 6502 questions.
DocWaluigean wrote:
I see. I got almost no replies about hardware understanding, since I want to make NES programs first before hardware.
But see, here's the thing. Making NES programs is
all about understanding the hardware.
This is very different from modern programming, where you abstract yourself from everything you don't strictly need to worry about.
Even if you're making a game designed to only run on an emulator, the purpose of an emulator is to, well, emulate the hardware. Making an NES game do anything, is a question about sending numbers around directly in the NES hardware, which eventually puts graphics on the screen.
Of course, you don't need to know the details about how that hardware works aside from things that directly affect your interaction with it. You need to know the basics about how the PPU processes its memory for each individual scanline, but you don't need to know how its registers are accessed internally, as long as you know the best practice of interacting with it.
Personally I don't know crap about hardware, but I know enough to create a functional NES game. That is what you also need.
Quote:
Possibly obvious replies from every beginner. only replies is if anyone from outside Japan ever make usage of custom sound chips made?
I don't know if any popular homebrew games use it (most people wouldn't be able to make use of it on a real NES, so relying on it would be a bit of a gamble), but it's
very popular among Famitracker users.
You'd need your sound engine to support it though, and my suggestion would be, for your first NES project, either use someone else's sound engine, or refrain from having sound at all. Don't overstretch yourself!
Quote:
Nametable is [the final ingredients before converting into usable applications?] And I'm sort of understanding what you said.
I don't understand this? Nametable is just the NES's name for the data that tells the video chip how the background graphics are laid out. Think about it as a grid of tiles, because that's exactly what it is.
Quote:
I don't know if any popular homebrew games use it (most people wouldn't be able to make use of it on a real NES, so relying on it would be a bit of a gamble), but it's very popular among Famitracker users.
You'd need your sound engine to support it though, and my suggestion would be, for your first NES project, either use someone else's sound engine, or refrain from having sound at all. Don't overstretch yourself!
Yeah, i know of no such homebrew game either. Another point is that the only currently available expansion synth is the one used with the Sunsoft 5b mapper, but they cost a premium price, so it's hard to break even if you were to use it in a game. Currently, only the "new" Famitracker beta supports it, i think? Maybe also FT-0CC. So that's a block in the road - being restricted to using Famitracker as your primary audio driver in a game means your game needs to be quite modest in what else it can do, because FT eats quite a bit of resources. Also, we don't really know exactly how the Sunsoft synth works, so emulation may be off. This is because no historical game really used all of its features. If you want to play it safe, you need to stay away from using the hardware envelope it has.
Abandoning expansion sound altogether, there is still a good option.
If you need to use more than 2 pulses, 1tri, 1 noise, your best bet is the DPCM channel as that is compatible with all NES units without modification.
Famitracker itself, FamiTone2 and GGsound are three good drivers you can use that support DPCM. Pently and Penguin are two other good drivers that don't, but have other merits. Each has its usecase, and it takes some time getting into. If you rule out using Famitracker in your game, writing songs for the other four is similar enough that you can make your songs more or less driver agnostic and as a last step add in the special features you like with each of them once you've learned more and decided what you really want.
Simple rules to keep a song agnostic - the most important ones first:
-stay away from the volume column, always.
-obviously stay away from expansion chips.
-in your tracks; always assign instruments to notes, always assign notes to instruments (at least FamiTone2 converter will ignore entries that doesn't come in note+instrument tuples).
-you may use the loop effect (Bxx), but avoid the other famitracker effects for now. only do backward references when using the loop effect. Once you've locked in a decision on a driver, some more effects may become available.
-don't use DPCM samples if you want to keep pently and penguin as options
-don't use the pitch envelopes if you want to keep pently as an option
-don't loop duty envelopes if you want to keep pently as an option
-don't use duty envelopes longer than 1 entry if you want to keep FamiTone2 as an option.
-don't accumulate pitch changes over envelope loops (at least not more than 63 units in either direction) if you want to keep FamiTone2 as an option.
-don't use hi-pitch envelopes if you want to keep GGsound as an option (also goes for Pently, see above).
Dude, let me tell you a story.
Back in 2006, I spent several weeks, if not months, banging my head into a wall trying to learn assembly language. No matter how much I tried, and no matter how I read, nothing made sense. I made zero progress.
It was demoralizing. I felt stupid and hopeless.
The solution I found was not to keep at it. Instead, I picked something easier to learn: GameMaker. And you know what? I was good at GameMaker! And after a year or two of that, I moved to C! And then to C++! I was climbing a set of stairs, rather than leaping over a building.
10 years later, in 2016, I finally returned to assembly. And you know what? Everything made sense! All the pieces fell into place and I was able to understand everything in just a few days. It was super easy. 6502 took a few hours to learn, and the hardware took about 3 days.
So here's my advice: find something easier. Come back to the NES when you're ready. No tutor or tutorial can make up for a lack of experience.
Kasumi wrote:
Quote:
You think it's bad when we recommend easy6502 a lot? The alternative is rewriting easy6502! It's much easier to answer your questions about it than rewrite it.
What are your questions about it? Where are you stuck? These are not rhetorical questions!
Seriously! I don't think you should expect offensive replies, but say one person is mean and one person gives you an answer. You've won!
We could go deep about the philosophical nature of public question asking, but I'd rather just answer your 6502 questions.
????????????????????????????
-------
Quote:
But see, here's the thing. Making NES programs is all about understanding the hardware.
This is very different from modern programming, where you abstract yourself from everything you don't strictly need to worry about.
Even if you're making a game designed to only run on an emulator, the purpose of an emulator is to, well, emulate the hardware. Making an NES game do anything, is a question about sending numbers around directly in the NES hardware, which eventually puts graphics on the screen.
Of course, you don't need to know the details about how that hardware works aside from things that directly affect your interaction with it. You need to know the basics about how the PPU processes its memory for each individual scanline, but you don't need to know how its registers are accessed internally, as long as you know the best practice of interacting with it.
Personally I don't know crap about hardware, but I know enough to create a functional NES game. That is what you also need.
-
I don't know if any popular homebrew games use it (most people wouldn't be able to make use of it on a real NES, so relying on it would be a bit of a gamble), but it's
very popular among Famitracker users.
You'd need your sound engine to support it though, and my suggestion would be, for your first NES project, either use someone else's sound engine, or refrain from having sound at all. Don't overstretch yourself!
Quote:
I don't understand this? Nametable is just the NES's name for the data that tells the video chip how the background graphics are laid out. Think about it as a grid of tiles, because that's exactly what it is.
Application > Assembly >
Namespace > Class > Data/Methods.
Isn't it an architecture of universal applications?
Your right though. It's too much pressure to put sounds at this time.
on the first quote, I pretty much am capable to understand the NES hardware.
DocWaluigean wrote:
If you feel I'm not even trying. despite the fact that to other eyes, I may be another person who doesn't care or gives up easily:
-I understood completely with basics of Binary, HEX, and decimals/ natural numbers.
-I understood that the address $ is like a room where you place the codes, and certain "rooms" inside does specific jobs, like the sprite-color decision "room."
-I at least know what Mapper does in certain types, from increasing tile size, to the abilities of making beautiful music using N106.
-INC means increment, which is mathematical technique in increasing number by 1, unless stated.
-I understood that graphic limit is set to 13 colors, with one transparent for each "4" colors, which is 3 colors and 1 transparent, and the screen is 256 X 240, but issues in vertical lines is 256 X 224
and other things about 8X8, 16X16 Sprite limit, where vertical mirror is possible, but not horizontal mirror.
- $ and # symbol is different, where $ is the address, and # is the number-number.
-I somewhat partially understood that A, X, Y is a type of register that "allows you to store numbers [Address? Digits/HEX?] temporary" like forms of transport from one address to another, OR some kind of math abilities that allows you to carry the number using "LDA" and "STA" stuff.
-I partially understood about high-power and low-power byte like what they said on Nerdy Night Week 4:
If I understand the code from BASIC languages with certain opcodes on what it does, like DEC and INC, the same way with the C# programming beginners where they did the "Application > NameSpace > Assembly > Codes", then I have compatibility to understand 6502 languages, but I tend to struggle with certain information that doesn't comprehend to me because it isn't explain well for me, or because, dare I say it, "It's boring to try and read it and remember it."
[/quote]
Like you said about understanding function NES game creation.
-------
FrankenGraphics wrote:
Quote:
I don't know if any popular homebrew games use it (most people wouldn't be able to make use of it on a real NES, so relying on it would be a bit of a gamble), but it's very popular among Famitracker users.
You'd need your sound engine to support it though, and my suggestion would be, for your first NES project, either use someone else's sound engine, or refrain from having sound at all. Don't overstretch yourself!
Yeah, i know of no such homebrew game either. Another point is that the only currently available expansion synth is the one used with the Sunsoft 5b mapper, but they cost a premium price, so it's hard to break even if you were to use it in a game. Currently, only the "new" Famitracker beta supports it, i think? Maybe also FT-0CC. So that's a block in the road - being restricted to using Famitracker as your primary audio driver in a game means your game needs to be quite modest in what else it can do, because FT eats quite a bit of resources. Also, we don't really know exactly how the Sunsoft synth works, so emulation may be off. This is because no historical game really used all of its features. If you want to play it safe, you need to stay away from using the hardware envelope it has.
Abandoning expansion sound altogether, there is still a good option.
If you need to use more than 2 pulses, 1tri, 1 noise, your best bet is the DPCM channel as that is compatible with all NES units without modification.
Famitracker itself, FamiTone2 and GGsound are three good drivers you can use that support DPCM. Pently and Penguin are two other good drivers that don't, but have other merits. Each has its usecase, and it takes some time getting into. If you rule out using Famitracker in your game, writing songs for the other four is similar enough that you can make your songs more or less driver agnostic and as a last step add in the special features you like with each of them once you've learned more and decided what you really want.
Simple rules to keep a song agnostic - the most important ones first:
-stay away from the volume column, always.
-obviously stay away from expansion chips.
-in your tracks; always assign instruments to notes, always assign notes to instruments (at least FamiTone2 converter will ignore entries that doesn't come in note+instrument tuples).
-you may use the loop effect (Bxx), but avoid the other famitracker effects for now. only do backward references when using the loop effect. Once you've locked in a decision on a driver, some more effects may become available.
-don't use DPCM samples if you want to keep pently and penguin as options
-don't use the pitch envelopes if you want to keep pently as an option
-don't loop duty envelopes if you want to keep pently as an option
-don't use duty envelopes longer than 1 entry if you want to keep FamiTone2 as an option.
-don't accumulate pitch changes over envelope loops (at least not more than 63 units in either direction) if you want to keep FamiTone2 as an option.
-don't use hi-pitch envelopes if you want to keep GGsound as an option (also goes for Pently, see above).
Thanks for the lesson of the music? I don't know how to reply without sounding offensive on accident.
-------
pubby wrote:
Dude, let me tell you a story.
Back in 2006, I spent several weeks, if not months, banging my head into a wall trying to learn assembly language. No matter how much I tried, and no matter how I read, nothing made sense. I made zero progress.
It was demoralizing. I felt stupid and hopeless.
The solution I found was not to keep at it. Instead, I picked something easier to learn: GameMaker. And you know what? I was good at GameMaker! And after a year or two of that, I moved to C! And then to C++! I was climbing a set of stairs, rather than leaping over a building.
10 years later, in 2016, I finally returned to assembly. And you know what? Everything made sense! All the pieces fell into place and I was able to understand everything in just a few days. It was super easy. 6502 took a few hours to learn, and the hardware took about 3 days.
So here's my advice: find something easier. Come back to the NES when you're ready. No tutor or tutorial can make up for a lack of experience.
Here's the thing: I just did which is SmileBASIC, a game where you make games using BASIC Languages with tutors inside the manual. But irony is that I understand BASIC, C# increasingly, and Java, yet I still struggle with 6502. Which I had no choice but to try and ask for help here. I been here since over 5 years, but were shy to ask..
I hope I'm not missing out on any comments.
viewtopic.php?f=2&t=10028&hilit=caramelpuffpuff&start=45#p111943So I'm going to try and ask more. From this post I found from another who also struggles with NES about assembly, he mentions about the starting creation of NES blank template.
-What is CN/N/UNRoM? By name and whats the differences?
Upon reading the code:
-Why isn't there an iNES code in the beginning, just mirror and PRG count?
-Why is MyVariable coded out into comment? As further reading, its obvious a tip or hint, but I don't see any... "visual entertaining" to pay attention.
-So .db stand for "database"?
-NMI? IRQ? "Reset" in this format? What is it and what does it do?
-Reading the code, there's nothing inside either of reset or NMI or IRQ. The comments is often ignored, possibly chance of sucking the byte memory out of it?
-I feel .enum is directions toward address code $0000, the main place to store code.
DocWaluigean wrote:
????????????????????????????
Restated: What are the issues you're having with easy6502? I have asked this. I have stated the question is not rhetorical: That is, that I'd like an answer to it. We can discuss whether people's replies are offensive or not, but I don't believe it will be as helpful to your goal of learning to program as telling me/us what specific things you are having issues with programming-wise.
Which I guess the post I'm about to answer seems to be doing, so
let's go!Quote:
-What is CN/N/UNRoM? By name and whats the differences?
NES has a set of abilities.
Its graphics processor (commonly called the PPU) can "see" 256 background tiles and 256 sprite tiles at a time. (This totals 8KB.)
Its CPU can "see" 64KB of data at a time. By "default" 32KB of this is data from the cartridge.
Super Mario Bros. is 40KB. It has seemingly "maxed out" the NES abilities. But there are games larger than this. The answer to how is extra hardware in the cartridge. This extra hardware is commonly called a "mapper".
NROM is the Super Mario Bros. mapper. It's stock NES abilities.
CNROM allows one to access four times as much graphical memory as Super Mario Bros. could access. (32KB instead of 8KB.) The PPU can still only "see" 8KB at a time. But this mapper lets you swap out what the PPU is "looking at".
UNROM allows one to access four times as much non graphical memory as Super Mario Bros. could access. (128KB instead of 32KB). The CPU can still only "see" 32KB from the cartridge at a time. But this mapper lets you swap out what the CPU is "looking at".
UOROM is similar to UNROM except it allows access to 256KB of non graphical memory. There's an extension of this as well to access even more.
There are actually more than 100 unique mappers. You can only use one at a time. As a beginner, just worry about NROM.
Quote:
-Why isn't there an iNES code in the beginning, just mirror and PRG count?
Because this is for a different assembler. Only NESASM uses .ines stuff. Edit: Perhaps a better answer is there is iNES code. It starts under the iNES header comment. The code at the top just makes the parts of the iNES header the user is likely to change easier to access. PRG_COUNT = 1 tells the assembler "Whenever I use PRG_COUNT, use the value 1." If the user changed that to '1' to a '2', everywhere PRG_COUNT is used would now be like using 2. So under the iNES header comment, you'll see a .db PRG_COUNT. Changing the value at the top would also change the header because it would cause a different value to be inserted here.
Quote:
-Why is MyVariable coded out into comment? As further reading, its obvious a tip or hint, but I don't see any... "visual entertaining" to pay attention.
It is meant to show an example of how one is supposed to define RAM.
Quote:
-So .db stand for "database"?
Define Byte.
Quote:
-NMI? IRQ? "Reset" in this format? What is it and what does it do?
I covered that in this post:
viewtopic.php?p=223346#p223346 I say this not to be mean, but if there's something about the post that's not clear could you ask a more specific question about it?
Quote:
-Reading the code, there's nothing inside either of reset or NMI or IRQ. The comments is often ignored, possibly chance of sucking the byte memory out of it?
It's just a template, not a program that does anything. The user of the template is meant to add the code that goes under reset, NMI and IRQ.
Quote:
-I feel .enum is directions toward address code $0000, the main place to store code.
$0000-$07FF is RAM. Code needs to be stored at $8000-$FFFF. That .enum is meant to work with the .dsb statements (if one were to uncomment them, or add one's own) .enum sets a sort of "counter" to the value given. When (name) .dsb (number) is encountered, (name) is assigned the current value of the counter. (This results in the use of (name) basically being the same as using the value of whatever the counter was at the point in time the .dsb was parsed.) Then (number) is added to the counter. Let's look at how this looks if the example variables were uncommented.
Code:
.enum $0000;Sets the counter to $0000
;NOTE: declare variables using the DSB and DSW directives, like this:
MyVariable0 .dsb 1;The counter is $0000. So MyVariable0 is now equal to $0000. Typing lda MyVariable0 will now be the same as typing lda $0000 later in the code.
;The number provided is 1. $0000+1= $0001. So the counter is now $0001
MyVariable1 .dsb 3;The counter is $0001. So MyVariable1 is now equal to $0001. Typing lda MyVariable1 will now be the same as typing lda $0001 later in the code.
;The number provided is 3. $0001+3=$0004. So the counter is now $0004.
I see kasumi answered a lot more a lot quicker.
Namespace and nametable are two very different things.
-A namespace is a sort of container in your code. It is also called a scope or name scope. Names declared in that container are local to that container, ie. they can't be seen from the outside. You have probably used namespaces if you've used C#.
-A nametable is an actual physical RAM space specific to the NES/Famicom, which the PPU uses to know what tiles from the graphics bank to draw where.
Quote:
-What is CN/N/UNRoM? By name and whats the differences?
These are different so-called mappers. Well, CN/UNROM are. A mapper is a hardware feature on the game pak / cartridge which allows the console to access more ROM, RAM, and special hardware features than its 16 bit address range was designed for.
NROM is the most simple, basic type of game pak. It isn't even a mapper in the real sense - just some storage for program and graphics on the PCB. There is no mapping devices on that PCB type, and as such, programs can be no bigger than 32kB, and graphics (stored separately) can be no larger than 8kB. Very early NES games use this type, and it is also a recommended start for new NES programmers, because it is simple to interface with.
CNROM uses CHR-ROM for graphics just like the NROM boards, but can page between several banks of CHR-ROM, so you can have more graphics stored. PRG-ROM is still limited to 32kB.
UNROM uses CHR-RAM instead of CHR-ROM, and allows for very big PRG-ROM sizes, but has no special features beyond that. Graphics need to be loaded from PRG-ROM to CHR-RAM, so it is probably not the best type of cartridges to start out with. But the challenge will be easy to overcome once you've written a few programs for NROM.
Quote:
So .db stand for "database"?
it stands for "define byte". .dw stands for "define word", and so on.
I don't know if any assembler out of CA65 uses it, but I prefer to use .byte or .word myself. It pretty much states what you are doing.
In my opinion relying on abbreviations for everything in source code belongs in the 90s. If the three-letter opcodes weren't standard in every documentation everywhere I wouldn't be using them either.
By the way, my little observation:
when I dealt with banks, I saw a slight difference between nasasm3 and asm6:
nesasm3 - fills the unused space 0xFF (Undefined)
while asm6 - fills 0x00 (BRK)
It's conventional to fill with $FF because when programming UV EPROM, traditional EEPROM, or NOR flash, it's faster to program $FF than any other value.
In ASM6, try
fillvalue $FF(Source:
README.txt)
In ca65, set
fill=yes, fillval=$FF for each memory area in the linker script you pass to ld65.
(Source:
ld65 Users Guide: 5.5 Other MEMORY area attributes)
tepples wrote:
In ASM6, try fillvalue $FF
Ok, by default
PS "fillvalue" is useful, thanks
The use of $FF fill for EPROMs isn't really relevant for most people's workflow these days, though. I personally prefer filling with 0, because it creates a BRK opcode, which has more predictable behaviour in the accident that your program tries to execute an empty space.
$FF is some weird illegal opcode but it will keep executing, eventually try to execute the vector table, and then likely rolling over into ZP and start executing there where who knows what it's going to do.
BRK on the other hand goes straight to your interrupt handler.
You can even use the interrupt handler to
trap errors this way. For me this was a big help for catching stack misuse errors (e.g. unpaired PHA/PLA). If you're using your IRQ for something else already, this may not be viable (you
can detect the difference between a BRQ and a regular IRQ in the handler though), but even if you can't, I still think $00 fill is a vote for more predictable/detectable error conditions.
There's WAAAYYY too many comments and I got lost. But thanks for giving me chance to try and speak up.
I'm going to draw a sketch so I could see if it's possible to even make children find value and learn NES much higher friendly. It's possible a cartoon would be made in favor for this.
So sadly, I have to start over...again. But I'm going too high level on asking about it.
obviously I understand HEX, binary, and "decimals", or normal numbers anyone knows what it means in much simpler terms, so I can skip this Week one. [No offense. I'm tired of seeing things so simple goes too complicated.]
Ironically, I understand Week 2, but many times I keep forgetting what it means or what it does and I had to go here to figure out what they mean sometimes.
Week 2:
-Is there the ENTIRE map of CPU overview? Where each address specifies what it does, like $3F10 is used for palette assignment in those specific screen? I didn't see PPU overview until just now, so that's off the question, but what about the rest of them?
-$800 - $1FFF = nothing. Is it the NES system flaw or is it only usable for mapper? or that's actually Famicom before removed toward release in US?
Week 3 is my "Forever broken tire" style, so I'm going to write it as I read it.
DocWaluigean wrote:
-Is there the ENTIRE map of CPU overview? Where each address specifies what it does, like $3F10 is used for palette assignment in those specific screen? I didn't see PPU overview until just now, so that's off the question, but what about the rest of them?
You're asking for a combination of 1) CPU memory map, and 2) list of MMIO registers (some call them "ports", for reasons unknown to mankind). You can find both here (refer to relevant links within wiki itself):
https://wiki.nesdev.com/w/index.php/CPU_memory_mapDocWaluigean wrote:
-$800 - $1FFF = nothing. Is it the NES system flaw or is it only usable for mapper? or that's actually Famicom before removed toward release in US?
See above.
koitsu wrote:
DocWaluigean wrote:
-Is there the ENTIRE map of CPU overview? Where each address specifies what it does, like $3F10 is used for palette assignment in those specific screen? I didn't see PPU overview until just now, so that's off the question, but what about the rest of them?
You're asking for a combination of 1) CPU memory map, and 2) list of MMIO registers (some call them "ports", for reasons unknown to mankind). You can find both here (refer to relevant links within wiki itself):
https://wiki.nesdev.com/w/index.php/CPU_memory_mapDocWaluigean wrote:
-$800 - $1FFF = nothing. Is it the NES system flaw or is it only usable for mapper? or that's actually Famicom before removed toward release in US?
See above.
-
$0000-$07FF $0800 2KB internal RAM So are these temporary memory where you place code that's being active? [I.E., equipping level 4 sword, being on World 3-6, no save data until world 4]
I would question more, but I could feel stern against me like that early comment, so I won't bother you much with it. Sorry...
DocWaluigean wrote:
- $0000-$07FF $0800 2KB internal RAM
So are these temporary memory where you place code that's being active? [I.E., equipping level 4 sword, being on World 3-6, no save data until world 4]
It's exactly what it says it is: memory range $0000 to $07FF is RAM. You can use it for whatever purpose you want. Most people use it for exactly what you described. But if you want to put code there and run code out of RAM, you can do it (ex.
jmp $0400 will work exactly like you think, but it's up to to put the code into RAM first :-) ).
Keep in mind that:
* $0000 to $00FF is zero page (you should know about this already, it's a 65xx architecture thing),
* $0100 to $01FF is for the stack.
The contents of said RAM are lost on power cycle, but retained on a soft reset (pressing the reset button).
It's up to you to decide how you want to lay out your RAM usage.
Here's a model some people use, but you DO NOT have to follow it.
If you want persistent RAM (i.e. retained during power loss, like Zelda's save feature), then you want battery-backed RAM (sometimes called SRAM ("save RAM", not be confused with "static RAM")). That's different and unrelated to the RAM from $0000 to $07FF. Battery-backed RAM is on the cartridge, along with a battery (so it retains charge), and is mapped to $6000 to $7FFF (8KBytes) in CPU memory space. To use it in a ROM (.NES file), you need to set bit 1 of byte 6 of
the header to 1. Don't ask me why the docs call it "PRG RAM". (Edit: people replying to this paragraph to hem and haw over NES 2.0, >8KByte, etc. should go away -- the guy is trying to learn basics, don't confuse him)
Edit 2: fixing up stack area description, thanks rainwarrior.
rainwarrior wrote:
The use of $FF fill for EPROMs isn't really relevant for most people's workflow these days, though. I personally prefer filling with 0, because it creates a BRK opcode, which has more predictable behaviour in the accident that your program tries to execute an empty space.
$FF is some weird illegal opcode but it will keep executing, eventually try to execute the vector table, and then likely rolling over into ZP and start executing there where who knows what it's going to do.
BRK on the other hand goes straight to your interrupt handler.
You can even use the interrupt handler to
trap errors this way. For me this was a big help for catching stack misuse errors (e.g. unpaired PHA/PLA). If you're using your IRQ for something else already, this may not be viable (you
can detect the difference between a BRQ and a regular IRQ in the handler though), but even if you can't, I still think $00 fill is a vote for more predictable/detectable error conditions.
Here I agree more with
tepples wrote:
It's conventional to fill with $FF because when programming UV EPROM, traditional EEPROM, or NOR flash, it's faster to program $FF than any other value.
If you want to debug, do this on the emulator (for example, fceux), if you want to catch errors, use the emulator with a breakpoint on "break on bad operation" =)
After full debugging, you can flash the PPU / CPU.
PS The device does not execute this command, $ FF is a bad operation, it will be a software reset.
Don't get too complex for someone who is just starting out
$0000-$07FF is just RAM, it's where you store any number you want to be able to retrieve again. The position of your player. The state of its movement. The stage you are on. Etc.
You could store code there, but it would serve no purpose unless you have something really clever planned out. Which you won't in your first project.
$0800-$1FFF I guess is just a mirror because the NES only has 2KB RAM. It's easier for the hardware to mirror data than have an unusable address range.
Why is it unused? I'm sure someone here has a great, correct response, but one guess could be that Nintendo wanted the NES to potentially have (or be upgraded to have) 4KB RAM at some point during the design process.
kocmoc wrote:
Here I agree more with
tepples wrote:
It's conventional to fill with $FF because when programming UV EPROM, traditional EEPROM, or NOR flash, it's faster to program $FF than any other value.
If you want to debug, do this on the emulator (for example, fceux)
Provided the emulators for your platform even support debugging. Though Mesen and FCEUX do, I doubt that is true of most emulators built for, say, the ARM architecture seen on Pinebook, Raspberry Pi, and Android tablets. Even if your PC is x86-64, you might not want to spend a gigabyte of a small SSD on installing Wine and/or Mono, and you might not want to tolerate the mandatory telemetry and other annoyances of Windows 10. (
We've been through this before.)
kocmoc wrote:
PS The device does not execute this command, $ FF is a bad operation, it will be a software reset.
An authentic MOS 6502 will execute $FF as
ISC aaaa,X, which performs
INC aaaa,X then
SBC aaaa,X. For example, FF 46 02 is
ISC $0246,X, and FF FF FF is
ISC $FFFF,X. The second source 6502 in the NES executes
unofficial opcodes the same way as the original, given that it was cut from an identical mask with only the transistors enabling BCD addition and subtraction cut out. Or what external hardware did you have in mind for detecting that opcode and performing a soft reset?
It's my fault for not replying or read-and-think, and attempting to re-read it. But why is nearly every information has to be written so difficult? I obviously know off-topic and pretty ignorant to say, but Archimedes wouldn't make the coding very complex and this... "push-away" style. Like I said, the other countries like Japan has made coding really fun, and I feel we're really behind if lesser-grammar people can't understand the US style. [No offense. I really want to help make the guide and tutorial for 6502.]
What I'm getting on the past comment last time was the code I explained was exactly right, and then the another type is the stack, which I doubt it's a type of array. [Like list of fruits and what each gives points.] and $FF is the bad operation, which reset upon meeting to it's destination. And the advertising of Fecux or Mesen? I would go for Mesen if the Karilla wasn't complex...
So,
Week 3:-What are the entire beginner's code usages recommanded for the directives, if you were Bunnyboy? There's one for opcodes I'm guessing.
-So labels are like " Define CAKE" like this:
Code:
***pseudocode***
DEF CAKE:
Milk = 1
Flour = 2
Eggs = 3
Sugar = 4
END DEF
Is this correct? or what's missing pieces?
-Now
this one is really annoying. The opcodes.. ---------------------------------------------------------
dougeff wrote:
Quote:
JOE = 10
ROB = 5
JUMP = JOE + ROB
IF JOE == ROB
GOTO @NAME
In Assembly, JOE, ROB, and JUMP could be RAM address, and @NAME is a label that the assembler will give a value to at assembly time. (Omitting some assembly directives to make it easier)
LDA #10 ;load A with 10
STA JOE ;store it to JOE
LDA #5 ;load A with 5
STA ROB ;store it to ROB
LDA JOE ;load A with JOE
CLC ;clear the carry flag, for addition
ADC ROB ;add ROB to A
STA JUMP ;store the result to JUMP
LDA ROB ;load A with ROB
CMP JOE ;compare A with JOE
BEQ @NAME ;branch to the label @NAME if equal
-First, the @DEFAULT: is it a label where you jump or go to when certain requires meet? or labels is completely different between BASIC and 6502?
Now... this one will be strange or hilarious. Let say I change the words around, and change A into X or Y or other unmentioned register from BunnyBoy. From what I'm getting, this is a type of "individual cute calculators" where A is "Calculator A", X is "Calculator X", and Y is "Calculator Y", no? Each calculators is connected to the NES CPU blahs. And they only connected one way. And absolutely no way to connect the math "temporary holding" between X, Y, and A, right? The only way is through NES CPU blahs with the "SXY, SXA, SYA, SYX", correct?
And what if I change some of the letters around?Code:
[color=#00BF00]LDA #10[/color] ;load A with 10
[color=#00BF00]STA JOE[/color] ;store it to JOE
[color=#00BF00]LDX #5[/color] ;load A with 5
[color=#00BF00]STX ROB[/color] ;store it to ROB
[color=#00BF00]LDA JOE[/color] ;load A with JOE
[color=#00BF00]CLC[/color] ;clear the carry flag, for addition
[color=#00BF00]ADC ROB[/color] ;add ROB to A
[color=#00BF00]STY JUMP[/color] ;store the result to JUMP
[color=#00BF00]LDY ROB[/color] ;load A with ROB
[color=#00BF00]CMP JOE[/color] ;compare A with JOE
[color=#00BF00]BEQ @NAME[/color] ;branch to the label @NAME if equal
Is the one above correct or easily qualified into assembly? or each registers has their own limits? and another example, if I completely ignore the A X Y law, as I were to think it's the same..Code:
[color=#00BF00]LDA #10[/color] ;load A with 10
[color=#00BF00]STX JOE[/color] ;store it to JOE
[color=#00BF00]LDY #5[/color] ;load A with 5
[color=#00BF00]STA ROB[/color] ;store it to ROB
[color=#00BF00]LDY JOE[/color] ;load A with JOE
[color=#00BF00]CLC[/color] ;clear the carry flag, for addition
[color=#00BF00]XDC ROB[/color] ;add ROB to A
[color=#00BF00]STA JUMP[/color] ;store the result to JUMP
[color=#00BF00]LDY ROB[/color] ;load A with ROB
[color=#00BF00]CMP JOE[/color] ;compare A with JOE
[color=#00BF00]BEQ @NAME[/color] ;branch to the label @NAME if equal
obviously something is wrong, but why? and what result would it give if you go Leeroy Jenkins and keep the code in? Explain it in original way, and in Elementary School way please, so maybe I could write it down for user-friendly guides.-I know comments, but does it waste spaces? And by how much each character?
DocWaluigean wrote:
Is this correct? or what's missing pieces?
I have no idea what you're trying to do here.
Quote:
-First, the @DEFAULT: is it a label where you jump or go to when certain requires meet?
Yes, labels mark places in the code where you can jump to. A label is just a "nickname" for a memory location, so they're used for variables too, they're not just for jumping.
Quote:
Now... this one will be strange or hilarious. Let say I change the words around, and change A into X or Y or other unmentioned register from BunnyBoy.
You can change which registers are used for which task, but you have to be consistent (e.g. you can't use STX to write to memory a value that's in Y!) and you have to keep in mind that not all registers can do everything, all of them have different limitations.
Quote:
LDA #10 ;load A with 10
STA JOE ;store it to JOE
This is correct.
Quote:
LDX #5 ;load A with 5
STX ROB ;store it to ROB
This works fine too. If X isn't being used for anything else, you can use it as intermediate storage when writing a value to memory.
Quote:
LDA JOE ;load A with JOE
CLC ;clear the carry flag, for addition
ADC ROB ;add ROB to A
STY JUMP ;store the result to JUMP
Now this doesn't make sense, because Y doesn't contain the result of the addition, A does. The result is always in A, that's just how the ADC operation works:
A = A + MEMORY + C. That STY will just store whatever Y contains into the JUMP variable.
Quote:
LDY ROB ;load A with ROB
CMP JOE ;compare A with JOE
BEQ @NAME ;branch to the label @NAME if equal
This also won't work, because CMP compares the accumulator against another value. There's another compare instruction for the Y register, CPY. If you use that instead of CMP, it'll work.
Quote:
or each registers has their own limits?
Yes, they have limits. Math and bitwise operations can only be done with A. X and Y can only be incremented/decremented by 1, and are meant to be used as counters and indices (for accessing arrays and the like), with different addressing modes using them in different ways.
Quote:
LDA #10 ;load A with 10
STX JOE ;store it to JOE
The number 10 is NOT being stored in JOE.
Quote:
LDY #5 ;load A with 5
STA ROB ;store it to ROB
Number 5 is NOT being stored in ROB. ROB will actually be 10, which is what A contains at this point (remember the
LDA #10 from before? so yeah, a still contains 10).
Quote:
LDY JOE ;load A with JOE
CLC ;clear the carry flag, for addition
XDC ROB ;add ROB to A
STA JUMP ;store the result to JUMP
The "A" in ADC doesn't represent the accumulator. "ADC" is short for
ADd with
Carry. There's no instruction for adding X or Y to another value, only A can be added.
Quote:
LDY ROB ;load A with ROB
CMP JOE ;compare A with JOE
BEQ @NAME ;branch to the label @NAME if equal
Again, change that CMP to CPY and it'll work.
Quote:
obviously something is wrong, but why?
Because you're not routing the values to the places where you want them to go.
Quote:
and what result would it give if you go Leeroy Jenkins and keep the code in?
The wrong values will go to the wrong variables, decisions will be made based on the wrong conditions, causing the logic you tried to implement to fail.
Quote:
Explain it in original way, and in Elementary School way please, so maybe I could write it down for user-friendly guides.
You just have to understand what the CPU does, and think like the CPU. Here's
a page with all the instructions the CPU supports. Those are all the commands you have to implement the logic in your game. That's your tool box, and you'll have to make do with just that.
Say you want to do
VARIABLE = 30 like you do in basic. Tough luck, there's no instruction to save an arbitrary value to RAM. However, there are instructions to put values in CPU registers, and there are instructions to save the registers to RAM, so that's how you do it. Choose a register (A, X or Y) and put your value in it (using LDA, LDX or LDY). Then, save THAT SAME REGISTER to RAM using the respective store instruction (STA, STX or STY). You have to use the same register for loading and storing, otherwise you'll not put the value you want in the location you want, you'll just put something else there.
The same goes for CMP, CPX and CPY. If you put a number to compare in Y, and then do a CMP, that instruction will compare whatever was left in A from the code before, it will not use Y in any way. This means that the decision to jump or not to jump will be made based on the wrong result.
Stop trying to think like a human, and start thinking like the dumb CPU that the 6502 is. It only does stuff little by little, so complex operations will have to be broken down into several instructions. Whenever you need to do something, look at the instructions and see which ones can help you get the job done, and then use them in sequence until the task is done. In the beginning you'll be reading about the instructions a lot, but eventually you'll remember what they all do and you'll be able to write code faster.
Quote:
-I know comments, but does it waste spaces? And by how much each character?
Comments are ignored by the assembler and don't take any space in the assembled binary. They exist to make the source code easier to comprehend, they don't affect the final ROM in any way.
Quote:
Like I said, the other countries like Japan has made coding really fun, and I feel we're really behind if lesser-grammar people can't understand the US style.
I'm curious what makes you think this is true. If you know Japanese enough to understand they make coding fun, then you why not just follow the better, more fun ways to learn? If you don't know Japanese, how are you sure it's any different?
I realize I've mentioned it a dozen times already, but could you
please try
easy6502? It allows you to just try things and see what happens. Even if you don't even
read it, you can still use it to look at exactly what happens with each instruction.
The gif stops showing what happens with the mouse at stx $0704 because I didn't set up the memory viewer to go that far down. Still, it should demonstrate how one can run code instruction by instruction and follow along.
Edit: The reason I keep saying this is because rather than asking about abstract concepts, you can ask about exact behavior. The difference is between
"Does this do what I expect it to do?"
And,
"This doesn't do what I expected it to do, can you help me understand why?"
You're asking about the concepts which isn't exactly a problem, but tools exist to let you play directly with the CPU. Why aren't you trying them? I'm not asking to be snarky. Is there something about the tool you're having trouble with or don't understand?
DocWaluigean wrote:
It's my fault for not replying or read-and-think, and attempting to re-read it. But why is nearly every information has to be written so difficult?
That's one major difference between coding assembly, and coding high level languages.
The high level languages (especially super abstracted stuff like C# and Java) is designed by humans to be read by humans. They are better at making sense at a more straight forward level.
When you are writing machine code, you are talking the computer's language. And when stuff is designed for computers to do it most effectively, it might not always be the straightforward way humans expect. For example, this is why the A register can do a lot of stuff that the X and Y registers can.
Honestly, it's not really
that complex, you just need to get into it. Get some hands-on experience. Once you get used to the quirks and limitations, you'll be able to apply human logic to your project.
Do you understand variables, DocWaluigean?
Like in this C# code:
Code:
foo = 5;
bar = 7;
foo = bar;
qux = foo;
What would the values of foo, bar, and qux be after running this?
@Tokumaru:
on the pseudocode, I mean to "assign type of codes into one small word, like "CAKES". The "CAKES" has variables of 1, 2, 3, and 4 of those mentions, like INC CAKES or DEC CAKES. [INCrement / DECrement the number by one inside the CAKES, meaning 0, 1, 2, and 3 now with DEC.]
-
I'm more surprised I got the A X Y common questions right.
-
ooohh, A can increment by more than one, whether adding and multiplying, right? And X and Y only increment by only one, otherwise, same as A, right?
-
Quote:
The wrong values will go to the wrong variables, decisions will be made based on the wrong conditions, causing the logic you tried to implement to fail.
Indeed, but I mean what would the result show upon? A hilarious glitches, or the decisions would be ignored, or crashes?
-
Before other comments, I feel that's offensive with "think like dumb CPU"...
For the first time, I'm finally starting to understand A X and Y styles, but it's a
major progress compare with couple years. Seeing the Instructions references would mean I have a long way to make guides for all. It may take a lot of errors and progresses to finally make it suitable to learn.
I hope I don't miss out any replies. Again..
DocWaluigean wrote:
Indeed, but I mean what would the result show upon? A hilarious glitches, or the decisions would be ignored, or crashes?
The specific result will follow the logic of whatever you actually told it to do.
Kasumi wrote:
Quote:
Like I said, the other countries like Japan has made coding really fun, and I feel we're really behind if lesser-grammar people can't understand the US style.
I'm curious what makes you think this is true. If you know Japanese enough to understand they make coding fun, then you why not just follow the better, more fun ways to learn? If you don't know Japanese, how are you sure it's any different?
Because there is no sources for 6502 programming tutorials in my taste and acknowledge, and there's no love or fun ways to learn programming languages of 6502 Assembly in English without grammar screw-ups, or mis-translation. If you look about many sites in English (At least from my perspective), there isn't any feelings of effort of love. It's only business writing to make the employees understand how programming concepts work on things "far more better to do than to make inprofitable children's toys." in old days. If I tried to do the fun ways, I'd get the info much worse then I were years ago, and I'm sure as heck be criticized as bad as Joe Cracker for getting many information wrong in case I want to teach the newcomers.
In USA, it's really hard to find the fun styles of learning because of big culture differences.
I remember a stories in Japan in Car Industries, they explain even tiniest details of flaws if there's an error, and show and teaches the entire employees about what the tiniest problem is. It takes so much effort and time to even go down to tiniest examples, and they fix it. It's a massive effort of love I value. Imagine doing the same thing to teaching. In USA today[?], it's more struggling to find one person who has that kind of devotions to details and qualities and love, because they only think in themselves or other forms of things inside their mind. I want to help bring those love in and bring it back like Atari.
EDIT: not the infamous Video Game Crash stories. I mean the Golden Age of Video Games.Kasumi wrote:
I realize I've mentioned it a dozen times already, but could you
please try
easy6502? It allows you to just try things and see what happens. Even if you don't even
read it, you can still use it to look at exactly what happens with each instruction.
The gif stops showing what happens with the mouse at stx $0704 because I didn't set up the memory viewer to go that far down. Still, it should demonstrate how one can run code instruction by instruction and follow along.
Edit: The reason I keep saying this is because rather than asking about abstract concepts, you can ask about exact behavior. The difference is between
"Does this do what I expect it to do?"
And,
"This doesn't do what I expected it to do, can you help me understand why?"
You're asking about the concepts which isn't exactly a problem, but tools exist to let you play directly with the CPU. Why aren't you trying them? I'm not asking to be snarky. Is there something about the tool you're having trouble with or don't understand?
I'll try soon again. I had the Easy6502, and I disliked the informations they are speaking, and going wrong directions. And after the "Introduction" list, I gave up few days after when it shows no result. All I keep getting is "LDA and STA is a color palette code." years ago.
-----------
Sumez wrote:
DocWaluigean wrote:
It's my fault for not replying or read-and-think, and attempting to re-read it. But why is nearly every information has to be written so difficult?
That's one major difference between coding assembly, and coding high level languages.
The high level languages (especially super abstracted stuff like C# and Java) is designed by humans to be read by humans. They are better at making sense at a more straight forward level.
When you are writing machine code, you are talking the computer's language. And when stuff is designed for computers to do it most effectively, it might not always be the straightforward way humans expect. For example, this is why the A register can do a lot of stuff that the X and Y registers can.
Honestly, it's not really
that complex, you just need to get into it. Get some hands-on experience. Once you get used to the quirks and limitations, you'll be able to apply human logic to your project.
As mush as I would agree with you if I was on everyone's level, things get complex when I put A and 1 and # and other characters together like playing with 3D toys fitting in a hole. The thing is everyone has style of learning abilities that in some cases, it's always omitted during lectures, which result in F in school stuff.
Think about if I was a Math student, and my preferences learning style is Visual learning, like watching cartoons or seeing funny scenes on a book, yet the Math teacher focuses on Read/Write method, which I were to get D- at best for trying hard to learn. That's exactly how it goes or feels to me. [In case your wondering, it's called
The VARK Method. one of most important things need to understand before 100% learning levels for all like learning ABC and 123.]
I hope I'm not offending you in anyway. Sorry? If I did, sorry.
pubby wrote:
Do you understand variables, DocWaluigean?
Like in this C# code:
Code:
foo = 5;
bar = 7;
foo = bar;
qux = foo;
What would the values of foo, bar, and qux be after running this?
Somewhat consequentially.
The values of those depends. It goes two ways:
foo will be shown as 5. bar will be shown as 7. There's a complete differences between " = " and " == " Either way, it possibly be converted into Boolean Logic and result in false, because 5 does not equal to 7. qux has no value, so by system's potential default, it'll be assign as "0" because it has no value. I forgot in some code cases, it will be 1. So by that idea, it will also be result in false because 0 [1?] does not equal to 5. So its either this...
Code:
5
7
False.
False.
or it will go this...
Code:
5
7
False.
[color=#BF0000][[[Insert Error and Shut Down Comments Here.]]][/color]
----------
rainwarrior wrote:
DocWaluigean wrote:
Indeed, but I mean what would the result show upon? A hilarious glitches, or the decisions would be ignored, or crashes?
The specific result will follow the logic of whatever you actually told it to do.
I'll take it as hilarious glitches or crashes. Thanks!
Let's switch up the thinking. Easy6502/Nerdy Nights were written for beginners. Keeping that in mind, they already tried to cover things down to the teeniest tiniest examples. They're not trying to show off or lose you. They're trying to help you.
Now, if you don't understand them, it doesn't mean the tutorials are bad. Indeed, they may just not suit your learning style. But the thing I'm trying to figure out is what kind of lesson are you expecting? In my mind, easy6502 is what you're describing. So how specifically is it failing you? "I disliked the information." Why? "going wrong directions" How? "I gave up few days after when it shows no result." What did you try specifically that got no result?
All you have to do to progress is be specific about what you want, and be specific about what you don't understand. Programming is literally all about being as specific as possible. I can't help you if you don't tell me what the problem is. And I genuinely don't know what the problem is.
All I want is your questions. If I mention easy6502 (lots of times) and then you don't use it and also don't ask about your issues with it, what do you actually want? Some resource that's "better"? I'm not in the business of offering solutions that aren't the best that I know!
I truly believe easy6502 is the best resource for you right now. It's fine if you don't get it, I'm happy to answer questions about it. But if you don't read it, or don't ask questions about what I consider the best resource, what else can I do? If you were me in this situation, trying to help you, what would you do? What do you want?
Kasumi wrote:
Let's switch up the thinking. Easy6502/Nerdy Nights were written for beginners. Keeping that in mind, they already tried to cover things down to the teeniest tiniest examples. They're not trying to show off or lose you. They're trying to help you.
Now, if you don't understand them, it doesn't mean the tutorials are bad. Indeed, they may just not suit your learning style. But the thing I'm trying to figure out is what kind of lesson are you expecting? In my mind, easy6502 is what you're describing. So how specifically is it failing you? "I disliked the information." Why? "going wrong directions" How? "I gave up few days after when it shows no result." What did you try specifically that got no result?
All you have to do to progress is be specific about what you want, and be specific about what you don't understand. Programming is literally all about being as specific as possible. I can't help you if you don't tell me what the problem is. And I genuinely don't know what the problem is.
All I want is your questions. If I mention easy6502 (lots of times) and then you don't use it and also don't ask about your issues with it, what do you actually want? Some resource that's "better"? I'm not in the business of offering solutions that aren't the best that I know!
I truly believe easy6502 is the best resource for you right now. It's fine if you don't get it, I'm happy to answer questions about it. But if you don't read it, or don't ask questions about what I consider the best resource, what else can I do? If you were me in this situation, trying to help you, what would you do? What do you want?
THIS is going to take a while for me to think. It'll be edit...
EDIT: It's too much, so I made new one instead.
Kasumi wrote:
Let's switch up the thinking. Easy6502/Nerdy Nights were written for beginners. Keeping that in mind, they already tried to cover things down to the teeniest tiniest examples. They're not trying to show off or lose you. They're trying to help you.
Now, if you don't understand them, it doesn't mean the tutorials are bad. Indeed, they may just not suit your learning style. But the thing I'm trying to figure out is what kind of lesson are you expecting? In my mind, easy6502 is what you're describing. So how specifically is it failing you? "I disliked the information." Why? "going wrong directions" How? "I gave up few days after when it shows no result." What did you try specifically that got no result?
All you have to do to progress is be specific about what you want, and be specific about what you don't understand. Programming is literally all about being as specific as possible. I can't help you if you don't tell me what the problem is. And I genuinely don't know what the problem is.
All I want is your questions. If I mention easy6502 (lots of times) and then you don't use it and also don't ask about your issues with it, what do you actually want? Some resource that's "better"? I'm not in the business of offering solutions that aren't the best that I know!
I truly believe easy6502 is the best resource for you right now. It's fine if you don't get it, I'm happy to answer questions about it. But if you don't read it, or don't ask questions about what I consider the best resource, what else can I do? If you were me in this situation, trying to help you, what would you do? What do you want?
*** Response ***
I am absolutely unsure how to explain it, so I may skip something because I feel I know I might repeat myself on same topic if I don't skip, and gives out hints.
If I were you, I would try to find someone who I hope I can successfully convince, like Shiru, Dahrkdaiz, etc. to tutor me, while recording those entire lectures, I will give details on "What Binary means to this?" "What is the usefulness of it?" "Is there much more examples?" or anything to help keep interests in. I would mention memorable parts of how one code impacts so big, like giving good examples of one or more codes usages inside the Kirby's Adventure, while showing the dramatic cut-scenes between Kirby and Sphere-Nnightmare. ANYTHING to help give them ideas. Even draw pictures or draw sprites of examples, like picture of Mario jumping using "JMP", and "If JMP = 0" Mario would not jump anymore, and shows him crying he can't jump. "If JMP = 255 [tHE LIMIT]", Mario jumps way too far into the moon.
Sounds really fun, but the important thing is how details this kind of code explanation can help children, teens, autism, even me, learn much more efficient than BunnyBoy. Every examples, even comparing one code to another, will be taught, and hopefully be able to understand.
Think yourself in Kindergarten, but there's no toys, rabbits or rainbows, etc... And learning isn't fun. It's written on piece of paper, with no pictures, just word that mentally just said, "Write me the answer. If you don't know, you fail." No sing songs, no cartoons that learn ABCs, Histories, etc. Just pure serious as adult work inside a cubical office.
It's depressing for the soul in youth. That's how I kind of feel when trying to learn to code long time ago. I don't ever want any other people go into my shoes and struggle and "find it boring" and give up too easily.
My questions about Easy6502:
What else can you do? Tutor me? Because 99% in this community will say no. 1% is a glimmering hope that's too hard to get.
What do I want? To master 6502 atm so I can make cartoons / comic / better than Bunnyboy in making 6502 programming so understandable, I hoped it will be in NESDev News when they mention with proof that a 9 year old girl has made one of the most quality game on NES.
What would I do? I think I mention this above.
What kind of lesson?
Imagine everything of 6502 assembly being taught in Codecademy. Where they give you pointers on first thing of "Hello World!" of each by each code on what it does. here it gives MANY examples on how each by each opcodes work. What examples in lovable or popular games used while demonstrating code performances. Shiru's game is the only game I know that's open sourced, and potentially can be used, but it's out of topic.
-------
How specifically? I'm re-reading it right now:
-The first conversation in this is "Lol Buddy! Yeah, this is the stuff for awesomeness!" talk. It's fine if the tutorial is going to be fun with pictures or stuff, but I looked ahead and it's nothing but words that bore the heck out of me. obviously pure ignorant response, but this is the stuff many people would find learning 6502 boring, which in turn, find learning to code not worth it. It's one of reasons why NESMaker is made, and even that didn't satisfied me today. [Maybe future with updates.]
Even if I tried to bypass it, the speaking feels like either I'm wasting my time hearing his conversation about off-topic which might have important info, or it's trying to challenge me to pay attention and read immature responses. [Huuuge no offenses. No vendetta against it, but Easy6502 and Bunnyboy is the most popular responses for all beginners who have trouble thinking normal as all of you, it's starting to give certain people wrong impression that this is elitist.]
-I know that this Easy6502 is for universal uses like Macintosh and older Apple products and Atari, but like I said, it's one of very popular choice for beginners, so why isn't there an NES CPU addresses explanation over the Easy6502 in favor for NESDev communities?
-
SP is the stack pointer. I won’t get into the stack yet, but basically this register is decremented every time a byte is pushed onto the stack, and incremented when a byte is popped off the stack.Terribly poor choice of words for this. You can't put this info in the middle of beginning and just say you can't get into stack yet.
-
The last section shows the processor flags. Each flag is one bit, so all seven flags live in a single byte. The flags are set by the processor to give information about the previous instruction. More on that later. Read more about the registers and flags here.So what if I don't care about what you said after this, and I want to learn more about registers and flags
from you? If I read it from that link you provided me, it will take me to official 6502 guides, which is not what I want because they explained it more complex than how I can understand from you, the maker of EASY6502. I can't even use dictionary to help, because I will get fixated on words I know and words they said!
-Early times, at 2nd level, it shows nothing, and they said the problem about $FF. I re-read it before and it didn't tell me to put the code in. obviously it's on the below of it, but I am still fixated onto the 2nd 6502, and it feels wrong to go to the 3rd level because I didn't understood what it wants. Am I supposed to change the code to see the hidden picture? You can't arrange this. [This is obvious on very wrong post where I could be missing something...]
[This is the point I'm starting to get mad reading Easy6502 about the past. I can't continue more. I said earlier, I'm not like other people who can comprehend more clearer in this stuff.]
-------
Quote:
All you have to do to progress is be specific about what you want, and be specific about what you don't understand. Programming is literally all about being as specific as possible. I can't help you if you don't tell me what the problem is. And I genuinely don't know what the problem is.
Please, tell me if you understand what I mean with specific after saying what my mind wants.
DocWaluigean wrote:
A can increment by more than one, whether adding and multiplying, right?
There are a lot of things you can do only with A, such as add, subtract, shift/rotate... but multiplication is something the 6502 doesn't do out if the box at all. If you need multiplication, you'll need to implement a multiplication algorithm using shifting and addition.
Quote:
And X and Y only increment by only one, otherwise, same as A, right?
They're the same as A in the sense that they all hold 8-bit values and can be loaded and stored, but other than that they're meant for different purposes.
Quote:
Indeed, but I mean what would the result show upon? A hilarious glitches, or the decisions would be ignored, or crashes?
That's not easy to predict, it will depend on all the code that came before and all the code that'll come after. If you wanted to put 5 in a variable, but ended up putting 10, the consequence of that will depend on what this variable is used for at a later time. It may represent the speed of a character's jump, in which case the character will jump higher than he normally would, or it may be the index of an entry in a jump table, in which case the wrong destination would be jumped to and the program would crash. It's hard to predict all the ramifications of a bug.
Quote:
Before other comments, I feel that's offensive with "think like dumb CPU"...
Offensive to the CPU? Well, it is a dumb piece of hardware... It can only execute a few commands, and will blindly follow whatever orders you give it. If that's not the definition of dumb, I don't know what is!
The CPU doesn't work anything like a human, so you can't expect it to know what you want it to do based on context, you have to break down each task in tiny little bits that the CPU is capable of handling.
For example, as a grown-up, you can easily understand the command "make a ham sandwich", but a young kid may not know how to do that, so you'll have to break that task in smaller tasks that the kid does know how to do. You may have to go "take a slice of bread", "put it on the plate", "take a slice of ham", "put it on the bread", and so on, until the whole sandwich is done. Working with the 6502 is the same thing: it only "knows" how to do a handful of things, so whenever you need to do something more complicated than it can handle, you have to break it down into smaller tasks that it can do.
DocWaluigean wrote:
The values of those depends. It goes two ways:
foo will be shown as 5. bar will be shown as 7. There's a complete differences between " = " and " == " Either way, it possibly be converted into Boolean Logic and result in false, because 5 does not equal to 7. qux has no value, so by system's potential default, it'll be assign as "0" because it has no value. I forgot in some code cases, it will be 1. So by that idea, it will also be result in false because 0 [1?] does not equal to 5. So its either this...
Sorry dude but that's incorrect. All variables end up equal to 7.
I really think you should learn more programming before diving into the 6502. Get to the point where you can write actual programs that do useful things. The skills will transfer.
Right now, all of this is flying over your head because of fundamental misunderstandings. Registers, for example, are really similar to variables. If you don't understand variables, you're not going to understand registers. And it's easier to learn variables in an easy to use language, like C#.
Best of luck.
tokumaru wrote:
DocWaluigean wrote:
A can increment by more than one, whether adding and multiplying, right?
There are a lot of things you can do only with A, such as add, subtract, shift/rotate... but multiplication is something the 6502 doesn't do out if the box at all. If you need multiplication, you'll need to implement a multiplication algorithm using shifting and addition.
Quote:
And X and Y only increment by only one, otherwise, same as A, right?
They're the same as A in the sense that they all hold 8-bit values and can be loaded and stored, but other than that they're meant for different purposes.
Quote:
Indeed, but I mean what would the result show upon? A hilarious glitches, or the decisions would be ignored, or crashes?
That's not easy to predict, it will depend on all the code that came before and all the code that'll come after. If you wanted to put 5 in a variable, but ended up putting 10, the consequence of that will depend on what this variable is used for at a later time. It may represent the speed of a character's jump, in which case the character will jump higher than he normally would, or it may be the index of an entry in a jump table, in which case the wrong destination would be jumped to and the program would crash. It's hard to predict all the ramifications of a bug.
Quote:
Before other comments, I feel that's offensive with "think like dumb CPU"...
Offensive to the CPU? Well, it is a dumb piece of hardware... It can only execute a few commands, and will blindly follow whatever orders you give it. If that's not the definition of dumb, I don't know what is!
The CPU doesn't work anything like a human, so you can't expect it to know what you want it to do based on context, you have to break down each task in tiny little bits that the CPU is capable of handling.
For example, as a grown-up, you can easily understand the command "make a ham sandwich", but a young kid may not know how to do that, so you'll have to break that task in smaller tasks that the kid does know how to do. You may have to go "take a slice of bread", "put it on the plate", "take a slice of ham", "put it on the bread", and so on, until the whole sandwich is done. Working with the 6502 is the same thing: it only "knows" how to do a handful of things, so whenever you need to do something more complicated than it can handle, you have to break it down into smaller tasks that it can do.
oh, I think I understand what you mean.
---
pubby wrote:
DocWaluigean wrote:
The values of those depends. It goes two ways:
foo will be shown as 5. bar will be shown as 7. There's a complete differences between " = " and " == " Either way, it possibly be converted into Boolean Logic and result in false, because 5 does not equal to 7. qux has no value, so by system's potential default, it'll be assign as "0" because it has no value. I forgot in some code cases, it will be 1. So by that idea, it will also be result in false because 0 [1?] does not equal to 5. So its either this...
Sorry dude but that's incorrect. All variables end up equal to 7.
I really think you should learn more programming before diving into the 6502. Get to the point where you can write actual programs that do useful things. The skills will transfer.
Right now, all of this is flying over your head because of fundamental misunderstandings. Registers, for example, are really similar to variables. If you don't understand variables, you're not going to understand registers. And it's easier to learn variables in an easy to use language, like C#.
Best of luck.
?
This stuff I'm talking about is from BASIC programming languages.
DocWaluigean wrote:
This stuff I'm talking about is from BASIC programming languages.
The PL (programming language) was stated as C# in pubby's example. Let's circle back to the actual question:
viewtopic.php?p=223961#p223961Q:
Quote:
Code:
foo = 5;
bar = 7;
foo = bar;
qux = foo;
What would the values of foo, bar, and qux be after running this?
A:
Quote:
Somewhat consequentially.
The values of those depends. It goes two ways:
foo will be shown as 5. bar will be shown as 7. There's a complete differences between " = " and " == " Either way, it possibly be converted into Boolean Logic and result in false, because 5 does not equal to 7. qux has no value, so by system's potential default, it'll be assign as "0" because it has no value. I forgot in some code cases, it will be 1. So by that idea, it will also be result in false because 0 [1?] does not equal to 5. So its either this...
This is incorrect, as pubby stated. Regardless of the PL. Here's how it works, in linear order at runtime:
foo is assigned a value of 5.
bar is assigned a value of 7.
foo is assigned a value of what bar contains at that time, i.e. 7.
qux is assigned a value of what foo contains at that time, i.e. 7.
All the operators used are
=, i.e. assignment.
I understand what you're starting to get at, re: BASIC. You're talking about how in BASIC,
= is also a comparison operator. However, that's only true in situations where comparison statements are being used, i.e.
IF ... THEN. There are no conditionals in the above code. It's all 100% assignment. If you took his C# code and turned it into Applesoft BASIC (what I'm familiar with), it would be this:
Code:
FOO = 5
BAR = 7
FOO = BAR
QUX = FOO
For the code given, that's it. There is no "potential default", "assign to 0" or "no value", nor "some cases it will be 1". These are assignments, not comparisons. I think your brain might have been thinking this (in BASIC):
Code:
FOO = 5
BAR = 7
IF FOO = BAR THEN ...
IF QUX = FOO THEN ...
...which is not the case.
It's really pretty simple: you can think of 6502 registers as variables which can only hold values ranging from 0 to 255. The 6502 code that's equivalent to the above would be:
Code:
foo = $00 ; Memory location $00
bar = $01 ; Memory location $01
qux = $02 ; Memory location $02
lda #5
sta foo ; foo = 5
lda #7
sta bar ; bar = 7
lda bar
sta foo ; foo = bar
lda foo
sta qux ; qux = foo
Finally: Easy6502 is mentioned because it provides a really easy way, via a web page, for someone to write 6502 code and "understand" it, with a way of doing visuals to indicate results. Its debugger is a bit "meh, I agree, but that's where the "coloured dots on the screen" aspect comes in handy. For truth statements (ex. "is bar == 7?"), you can for example say "if false, draw a blue dot. if true, draw red dot". Then you know what's true/false. A good debugger can make this possible too, but Easy6502 doesn't have that.
P.S. -- And I meant this with utmost respect (I myself do English/Chinese/little Korean/little Swedish): I get the impression there's a language barrier here. Am I wrong? If English isn't your native tongue, then what is? We have TONS of multi-lingual folks here (examples: Portuguese, Spanish, French, German, Swedish, Danish, Finnish, Dutch, Japanese, Chinese, and some Russian) who can help.
koitsu wrote:
Finally: Easy6502 is mentioned because it provides a really easy way, via a web page, for someone to write 6502 code and "understand" it, with a way of doing visuals to indicate results. Its debugger is a bit "meh, I agree, but that's where the "coloured dots on the screen" aspect comes in handy. For truth statements (ex. "is bar == 7?"), you can for example say "if false, draw a blue dot. if true, draw red dot". Then you know what's true/false. A good debugger can make this possible too, but Easy6502 doesn't have that.
P.S. -- And I meant this with utmost respect (I myself do English/Chinese/little Korean/little Swedish): I get the impression there's a language barrier here. Am I wrong? If English isn't your native tongue, then what is? We have TONS of multi-lingual folks here (examples: Portuguese, Spanish, French, German, Swedish, Danish, Finnish, Dutch, Japanese, Chinese, and some Russian) who can help.
My native tongue [Language I was born with] is Mexican Spanish... but I speak primarily with English most of my life. Personal issue-wise, I'm not really good with English, same thing with Spanish. Able to speak fluent English doesn't mean I know English grammar completely well... My forms of communication is very complex. I could draw every picture, and it could make more sense than what I'm talking right now...
I want to reply on the Easy6502, but I am not sure what to explain... even the BASIC != C#...
Quote:
If I were you, I would try to find someone who I hope I can successfully convince, like Shiru, Dahrkdaiz, etc. to tutor me,
Why do you think this will go differently? What I mean by that is, if I were to tutor you, I would be telling you to do exactly what I'm telling you to do in this thread. You'd be putting things into easy6502's debugger. The only difference would be you could get answers to questions immediately.
But you've gotten answers to questions on this thread pretty immediately when you've asked them too.
I understand your complaints about easy6502's tutorial. (Which... I didn't write? I'm not sure if you think I wrote easy6502.)
But ignoring that. Honestly, here is my ideal situation: That you are able to run 6502 code, on your own, and see exactly what happens. Here are the steps to do that:
Go the website:
https://skilldrick.github.io/easy6502Ignore all the text on it. Find one of the debugger windows. Do the following:
Delete all existing text in it.
Type
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Check "Monitor"
Click "Assemble".
Check "Debugger"
Click Run.
Tell me what happens in the black box in the right.
Kasumi wrote:
Quote:
If I were you, I would try to find someone who I hope I can successfully convince, like Shiru, Dahrkdaiz, etc. to tutor me,
Why do you think this will go differently? What I mean by that is, if I were to tutor you, I would be telling you to do exactly what I'm telling you to do in this thread. You'd be putting things into easy6502's debugger. The only difference would be you could get answers to questions immediately.
But you've gotten answers to questions on this thread pretty immediately when you've asked them too.
I understand your complaints about easy6502's tutorial. (Which... I didn't write? I'm not sure if you think I wrote easy6502.)
But ignoring that. Honestly, here is my ideal situation: That you are able to run 6502 code, on your own, and see exactly what happens. Here are the steps to do that:
Go the website:
https://skilldrick.github.io/easy6502Ignore all the text on it. Find one of the debugger windows. Do the following:
Delete all existing text in it.
Type
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Check "Monitor"
Click "Assemble".
Check "Debugger"
Click Run.
Tell me what happens in the black box in the right.
There is a white dot all the way down and right.
Code:
0000: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d3
What exactly is your end goal here? Are you wishing for someone to make a funny cartoon that will somehow teach you 6502 code?
Sumez wrote:
What exactly is your end goal here? Are you wishing for someone to make a funny cartoon that will somehow teach you 6502 code?
My end goal atm is to master 6502, and make the learning so good, it would or will be impossible to not understand.
The "funny cartoon" is crucial to teach 6502 in young or teen mindset, as that is the most recognized things out there today.
Ever since the Mario Adventure made by DahrkDaiz got me into this homebrew things, I can't tell you how much potential I see in SNES and NES. And I want to make a type of revolution that not even NESMaker can accomplish.
How old are you, BTW? Just curious.
koitsu wrote:
How old are you, BTW? Just curious.
.............................
December 16, 1995..........
Quote:
I would try to find someone who I hope I can successfully convince, like Shiru, Dahrkdaiz, etc. to tutor me
Thought I would let you know...
You are currently talking to people who know as much about 6502 and NES programming as all those people you mentioned.
People like koitsu, memblers, chris covell, etc have been doing this since the 90s.
I don't think Shiru nor Darkdaiz visits any of the forums anymore.
dougeff wrote:
Quote:
I would try to find someone who I hope I can successfully convince, like Shiru, Dahrkdaiz, etc. to tutor me
Thought I would let you know...
You are currently talking to people who know as much about 6502 and NES programming as all those people you mentioned.
People like koitsu, memblers, chris covell, etc have been doing this since the 90s.
I don't think Shiru nor Darkdaiz visits any of the forums anymore.
Except the differences is I am absolutely terrible at grammars and specific type of readings. Because private tutors is 99% impossible, I got to explain as much as I can while giving proof that I'm listening and trying. Every tiny details I find, I have to dig it all down the rabbit hole and find ways to make 6502 Assembly teachings look like Kindergarten language programming instead of College programming. Also, I got to find ways and ways to finally get myself to explain correctly. I don't want to be, "Another typical guy who 'forgets' or never progress to help make new tutorials."
There's also a red dot in the top left. But seems like that worked.
Okay. That's what you have to do, to run code in this. You type some there. And click assemble. And click run. If you click Reset it will allow you to run the code again. You don't have to use the example code, or the code I just gave you. You can type your own code in there and see what happens. This will let you see how 6502 behaves. You type instructions in here, and run them. It's that simple.
Underneath the black box (where the white dot appeared) is a debugger. This shows the current "state" of the CPU. The CPU "state" is the current value of all values the CPU can hold. You'll see the familiar A, X, and Y. There's some other values there I won't cover yet. (I know you don't want things introduced before they can properly explained. Those other things are in that set of things.)
Now, I may start covering some things you already know. Please bear with me. The 6502 CPU will run "instructions", one at a time going down. (At least, that's the best way to explain it for now.) The "instruction set" for a CPU is simply all of the things that it can do. 6502 has 56 "instructions". This may seem like a lot, but most of them do something very simple and easy to see.
An instruction is made of a 3 letter code (called a "mnemonic") and sometimes a "something" that follows it. For now, that something will be a number.
Run the code I gave you again, and you'll see this: "A=$01" in the debugger box. Let's talk about why that is. Let's talk about the first "instruction."
LDA stands for LoaD Accumulator. LDA is that 3 letter code we just discussed. The mnemonic.
This will take the value following the instruction, and copy it into the "accumulator". The accumulator is part of the "state" of the CPU.
You can think of the accumulator like a very small box. It can hold exactly one value. To load a new value, the old one has to get removed. So, anytime the CPU gets to an LDA, it will take the old value out of the box, and put the new value specified into the box.
That's really all it does! Remember how "A=$01" in that box after you ran that code? Let's learn how to "step" through code. "Step" means run a single instruction. (Usually this means one line.)
So click "reset". Recheck debugger if you need to. You'll see A=$00. Ignore the rest. Click step once. You'll see "A=$01" in that box. This means it just ran the first line of code.
The first line of code was
Code:
lda #$01
And you'll see that after running that line of code, A did indeed get the value $01 put into its box.
Click step again. This will run sta $08. This is a new instruction. This STores the Accumulator to the place specified after the mnemonic. On the 6502 CPU, "Store" is more like a copy, though. The value in the accumulator remains in the accumulator. It's just ALSO copied into the location specified. In this case $08.
Below where the code is (below the monitor checkbox too) you'll see some RAM. RAM is "Random Access Memory". Each location in RAM has a number called its "address". It's not unlike a bunch of post office boxes:
Much like the accumulator (and unlike real post office boxes), each RAM "address" can only hold one value. To put something new in the box, the old thing gets removed.
So, look at location $08. If you start at the top left ($00), and count going right, you'll see that that address ($08) now has the value "$01" in it. It has this value, because that was the value in the accumulator when you told the CPU to store the value in the accumulator into that address.
Click step again. You've already seen one LDA in action. So it should not surprise you that in the CPU "state" the accumulator now has the value $02. But note that address $08 in RAM is still $01. The value is copied FROM the accumulator, but changes to the accumulator don't change that RAM after the copy (or store) has happened.
Click step again. This stores the value in the accumulator (currently 2) into $0200. And while you can't go that far down in the monitor by default, you'll notice the top left part of the black box on the right is now red. On easy6502, storing to addresses $0200 to $05ff will change the colors in that black box. (This is one thing that is ONLY on easy6502. Every thing that uses 6502 has different addresses that have different effects. On NES for instance, storing to $0200-$05FF would not do anything related to graphics.)
So, you see a dark red pixel. The reason that pixel becomes red is simply because $02 means red to it. There's no "why" behind this part. It's just what the designer of easy6502 chose.
Click step again. A now equals $01. Step again. STA $05FF. We've now copied the value in A (currently $01) into the address $05FF. And you recall, that's one of the addresses that changes the pixels in the black box. Remember how $02 meant red? Well, you can probably guess now that $01 means white.
This is how the white dot got there. And now, there's no instructions left. So the code is where it would have been if you had "run" it. (Run runs all the code at once.) So that's why after running, the state of the CPU showed "A=$01". It was the last value placed into A before the program ended.
Let's make two small changes so this is really understood. Remember how $02 is a red pixel and $01 is a white pixel? (In easy6502 only.)
Change
Code:
lda #$02
sta $0200
to
Code:
lda #$01
sta $0200
and change
Code:
lda #$01
sta $05FF
to
Code:
lda #$02
sta $05FF
What happens? Do you understand why what happens DOES happen?
There are a few things I'm glossing over in this post. But does this make sense? If anything and I mean
anything does not make sense in this post, ask and I will try to explain it differently. The most important thing is to understand how to run the code a line at a time and understand how to see how each line affects the "state" of the CPU.
DocWaluigean wrote:
December 16, 1995..........
Cool, 23. Just was curious. Sometimes it helps to know the age of someone wanting assistance; younger folks often require different media and depictions and warrant use of different words when describing something. The 6502 isn't too hard to understand, but some of the NES architecture (particularly PPU behaviour) most certainly is. And FWIW, I can't stand most college textbooks or teaching materials. But everyone learns differently.
Kasumi wrote:
There's also a red dot in the top left. But seems like that worked.
Okay. That's what you have to do, to run code in this. You type some there. And click assemble. And click run. If you click Reset it will allow you to run the code again. You don't have to use the example code, or the code I just gave you. You can type your own code in there and see what happens. This will let you see how 6502 behaves. You type instructions in here, and run them. It's that simple.
Underneath the black box (where the white dot appeared) is a debugger. This shows the current "state" of the CPU. The CPU "state" is the current value of all values the CPU can hold. You'll see the familiar A, X, and Y. There's some other values there I won't cover yet. (I know you don't want things introduced before they can properly explained. Those other things are in that set of things.)
Now, I may start covering some things you already know. Please bear with me. The 6502 CPU will run "instructions", one at a time going down. (At least, that's the best way to explain it for now.) The "instruction set" for a CPU is simply all of the things that it can do. 6502 has 56 "instructions". This may seem like a lot, but most of them do something very simple and easy to see.
An instruction is made of a 3 letter code (called a "mnemonic") and sometimes a "something" that follows it. For now, that something will be a number.
Run the code I gave you again, and you'll see this: "A=$01" in the debugger box. Let's talk about why that is. Let's talk about the first "instruction."
LDA stands for LoaD Accumulator. LDA is that 3 letter code we just discussed. The mnemonic.
This will take the value following the instruction, and copy it into the "accumulator". The accumulator is part of the "state" of the CPU.
You can think of the accumulator like a very small box. It can hold exactly one value. To load a new value, the old one has to get removed. So, anytime the CPU gets to an LDA, it will take the old value out of the box, and put the new value specified into the box.
That's really all it does! Remember how "A=$01" in that box after you ran that code? Let's learn how to "step" through code. "Step" means run a single instruction. (Usually this means one line.)
So click "reset". Recheck debugger if you need to. You'll see A=$00. Ignore the rest. Click step once. You'll see "A=$01" in that box. This means it just ran the first line of code.
The first line of code was
Code:
lda #$01
And you'll see that after running that line of code, A did indeed get the value $01 put into its box.
Click step again. This will run sta $08. This is a new instruction. This STores the Accumulator to the place specified after the mnemonic. On the 6502 CPU, "Store" is more like a copy, though. The value in the accumulator remains in the accumulator. It's just ALSO copied into the location specified. In this case $08.
Below where the code is (below the monitor checkbox too) you'll see some RAM. RAM is "Random Access Memory". Each location in RAM has a number called its "address". It's not unlike a bunch of post office boxes:
Much like the accumulator (and unlike real post office boxes), each RAM "address" can only hold one value. To put something new in the box, the old thing gets removed.
So, look at location $08. If you start at the top left ($00), and count going right, you'll see that that address ($08) now has the value "$01" in it. It has this value, because that was the value in the accumulator when you told the CPU to store the value in the accumulator into that address.
Click step again. You've already seen one LDA in action. So it should not surprise you that in the CPU "state" the accumulator now has the value $02. But note that address $08 in RAM is still $01. The value is copied FROM the accumulator, but changes to the accumulator don't change that RAM after the copy (or store) has happened.
Click step again. This stores the value in the accumulator (currently 2) into $0200. And while you can't go that far down in the monitor by default, you'll notice the top left part of the black box on the right is now red. On easy6502, storing to addresses $0200 to $05ff will change the colors in that black box. (This is one thing that is ONLY on easy6502. Every thing that uses 6502 has different addresses that have different effects. On NES for instance, storing to $0200-$05FF would not do anything related to graphics.)
So, you see a dark red pixel. The reason that pixel becomes red is simply because $02 means red to it. There's no "why" behind this part. It's just what the designer of easy6502 chose.
Click step again. A now equals $01. Step again. STA $05FF. We've now copied the value in A (currently $01) into the address $05FF. And you recall, that's one of the addresses that changes the pixels in the black box. Remember how $02 meant red? Well, you can probably guess now that $01 means white.
This is how the white dot got there. And now, there's no instructions left. So the code is where it would have been if you had "run" it. (Run runs all the code at once.) So that's why after running, the state of the CPU showed "A=$01". It was the last value placed into A before the program ended.
Let's make two small changes so this is really understood. Remember how $02 is a red pixel and $01 is a white pixel? (In easy6502 only.)
Change
Code:
lda #$02
sta $0200
to
Code:
lda #$01
sta $0200
and change
Code:
lda #$01
sta $05FF
to
Code:
lda #$02
sta $05FF
What happens? Do you understand why what happens DOES happen?
There are a few things I'm glossing over in this post. But does this make sense? If anything and I mean
anything does not make sense in this post, ask and I will try to explain it differently. The most important thing is to understand how to run the code a line at a time and understand how to see how each line affects the "state" of the CPU.
I'm sorry, but this is honestly hilarious, because I didn't expect this to be this simple explanation with deep examples.
I tried it again on first one, and I did see the red dot on other side of white dot.
I know that instructions is opcode ; operation code?
I also know what mnemonic means, but I can't provide descriptions on what it really means without dictionary.
Is "something" an address code? Real Number?
Alright, I got lost on the "So click "reset". Recheck debugger if you need to." because it feels like it's starting to lose certain information.
Quote:
And you'll see that after running that line of code, A did indeed get the value $01 put into its box.
Click step again. This will run sta $08. This is a new instruction. This STores the Accumulator to the place specified after the mnemonic. On the 6502 CPU, "Store" is more like a copy, though. The value in the accumulator remains in the accumulator. It's just ALSO copied into the location specified. In this case $08.
-"A did indeed get the value $01 put into it's box" ???
"A got the value / Address $01 into "the box that's written 'A'"?
-I thought you can't change the RAM styles? or was it that you can't save it?
I honestly really enjoy this effort though.
koitsu wrote:
DocWaluigean wrote:
December 16, 1995..........
Cool, 23. Just was curious. Sometimes it helps to know the age of someone wanting assistance; younger folks often require different media and depictions and warrant use of different words when describing something. The 6502 isn't too hard to understand, but some of the NES architecture (particularly PPU behaviour) most certainly is. And FWIW, I can't stand most college textbooks or teaching materials. But everyone learns differently.
It's not just college materials. It's that 90% of "teachers" just doesn't care about the "gift" side of every student like Elementary / Middle / High school teacher did. You have to pay approximately 300$ - 500$ just to take one class. It was real bad, one of the tutors for "Special Disability / Study Center" gave me a C / C++ book to keep and said that the materials is too hard, and I have to put so much effort. The only reason I pass as B is because I had to stay after school starting week 3. It's one of last Colleges before I lost respect for them.
As I agree on what you said that everyone learns differently, I feel as though showing an age of adult is sign of shame or dishonor..
Let's start with where you actually got stuck, since a few other answers you want might be a bit better understood after you get unstuck.
Quote:
Alright, I got lost on the "So click "reset". Recheck debugger if you need to." because it feels like it's starting to lose certain information.
"Reset" (next to "Run" and "Hexdump"), takes the CPU back to its initial "state". "Recheck debugger" means Check the checkbox next to the "Debugger" option. (Underneath the black box.) You have to check "Debugger" again after you click "Run". Which... is a bit annoying, but hey, it's still a good package.
So for that section starting from the total beginning (refresh the page), you want this code again (from the previous post, sorry, yes, that wasn't clear):
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Remove any code already in the box. Paste the code above into the box. Click Assemble, check "Debugger", and check "Monitor". And then continue reading the post.
Quote:
-"A did indeed get the value $01 put into it's box" ???
I described earlier in the post that A (the accumulator) was like a box that holds one value. So this put the value $01 into that box. (That is, that A now hold the value $01.) Does this make sense now?
I'll answer your questions in a different order than you asked, because they sort of flow into each other. And it's okay to not understand these things too! So long as you get to the end of that other post, I promise you're getting somewhere.
Quote:
Is "something" an address code? Real Number?
This one's tough... I want to say maybe wait for the answer, but I'll try to get the basics.
The "something" is the "addressing mode". (Edit: Kasumi learned something new today! I guess it's really called the "operand", but addressing modes are still pretty important to learn so let's go!) And it's
often an address or a real number. Most instructions have several "addressing modes". And usually the addressing mode affects which value is used, but not... the "goal" of the instruction? (Goal here is not a technical term.) For example, LDA always copies some value into the accumulator. That's its goal. The addressing mode affects how the value that gets copied is fetched.
For example #$XX (where XX is any one hexadecimal value between $00 and $FF) is called "immediate" addressing. (You don't really need to remember the names of the addressing modes.) A number symbol '#' before a value means immediate addressing. Immediate addressing means use that value given as it is. If you leave out the number symbol, it's a different addressing mode. (And you will definitely mess them up accidentally at least once in your code! It's a rite of passage.
)
lda #$00 means A (the accumulator) will get the value $00.
lda #$FF means A will get the value $FF.
Immediate is the easiest addressing mode.
Two other addressing modes are used in the post.
$XX (where XX is any value between $00 and $FF) is "zero page" addressing. $0000-$00FF in RAM are called the zero page because their leftmost digits are, well, zero. Rather than use the value of "XX" directly, it uses the value stored in RAM at $00XX.
lda $00 means A will get the value stored at $0000.
lda $08 means A will get the value stored at $0008.
$XXXX is "absolute" addressing.
lda $0200 means A will get the value stored at $0200. It's worth noting there's no guarantee an "absolute" address is RAM. What's RAM and what influences hardware is one of the things that can change between things that use 6502.
If you don't understand addressing modes, please, please don't get hung up on it. They're... eventually necessarily knowledge, but they become easier to understand once you start coding a bit.
Quote:
I know that instructions is opcode ; operation code?
Opcode is operation code, yes. Each mnemonic can have several "opcodes". And the reason for this is because of the addressing modes. LDA #$00 has a different "opcode" than LDA $00. (The different opcode is how the CPU fetches the right value to put in the accumulator.)
Shorter, the opcode is the byte that tells the CPU exactly what to do.
What the CPU does, is read a byte (the opcode), do the action associated with that byte (run the instruction, which may involve reading a few more bytes). When that instruction is done, it will read another byte, and do the action associated with that byte. Basically forever.
Again, if that doesn't make much sense, don't worry too much. You can actually get away with
never learning much about opcodes.
Quote:
-I thought you can't change the RAM styles? or was it that you can't save it?
I don't understand what you mean by RAM styles. Can you rephrase the question?
Kasumi wrote:
Let's start with where you actually got stuck, since a few other answers you want might be a bit better understood after you get unstuck.
Quote:
Alright, I got lost on the "So click "reset". Recheck debugger if you need to." because it feels like it's starting to lose certain information.
"Reset" (next to "Run" and "Hexdump"), takes the CPU back to its initial "state". "Recheck debugger" means Check the checkbox next to the "Debugger" option. (Underneath the black box.) You have to check "Debugger" again after you click "Run". Which... is a bit annoying, but hey, it's still a good package.
So for that section starting from the total beginning (refresh the page), you want this code again (from the previous post, sorry, yes, that wasn't clear):
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Remove any code already in the box. Paste the code above into the box. Click Assemble, check "Debugger", and check "Monitor". And then continue reading the post.
Quote:
-"A did indeed get the value $01 put into it's box" ???
I described earlier in the post that A (the accumulator) was like a box that holds one value. So this put the value $01 into that box. (That is, that A now hold the value $01.) Does this make sense now?
I'll answer your questions in a different order than you asked, because they sort of flow into each other. And it's okay to not understand these things too! So long as you get to the end of that other post, I promise you're getting somewhere.
Quote:
Is "something" an address code? Real Number?
This one's tough... I want to say maybe wait for the answer, but I'll try to get the basics.
The "something" is the "addressing mode". (Edit: Kasumi learned something new today! I guess it's really called the "operand", but addressing modes are still pretty important to learn so let's go!) And it's
often an address or a real number. Most instructions have several "addressing modes". And usually the addressing mode affects which value is used, but not... the "goal" of the instruction? (Goal here is not a technical term.) For example, LDA always copies some value into the accumulator. That's its goal. The addressing mode affects how the value that gets copied is fetched.
For example #$XX (where XX is any one hexadecimal value between $00 and $FF) is called "immediate" addressing. (You don't really need to remember the names of the addressing modes.) A number symbol '#' before a value means immediate addressing. Immediate addressing means use that value given as it is. If you leave out the number symbol, it's a different addressing mode. (And you will definitely mess them up accidentally at least once in your code! It's a rite of passage.
)
lda #$00 means A (the accumulator) will get the value $00.
lda #$FF means A will get the value $FF.
Immediate is the easiest addressing mode.
Two other addressing modes are used in the post.
$XX (where XX is any value between $00 and $FF) is "zero page" addressing. $0000-$00FF in RAM are called the zero page because their leftmost digits are, well, zero. Rather than use the value of "XX" directly, it uses the value stored in RAM at $00XX.
lda $00 means A will get the value stored at $0000.
lda $08 means A will get the value stored at $0008.
$XXXX is "absolute" addressing.
lda $0200 means A will get the value stored at $0200. It's worth noting there's no guarantee an "absolute" address is RAM. What's RAM and what influences hardware is one of the things that can change between things that use 6502.
If you don't understand addressing modes, please, please don't get hung up on it. They're... eventually necessarily knowledge, but they become easier to understand once you start coding a bit.
Quote:
I know that instructions is opcode ; operation code?
Opcode is operation code, yes. Each mnemonic can have several "opcodes". And the reason for this is because of the addressing modes. LDA #$00 has a different "opcode" than LDA $00. (The different opcode is how the CPU fetches the right value to put in the accumulator.)
Shorter, the opcode is the byte that tells the CPU exactly what to do.
What the CPU does, is read a byte (the opcode), do the action associated with that byte (run the instruction, which may involve reading a few more bytes). When that instruction is done, it will read another byte, and do the action associated with that byte. Basically forever.
Again, if that doesn't make much sense, don't worry too much. You can actually get away with
never learning much about opcodes.
Quote:
-I thought you can't change the RAM styles? or was it that you can't save it?
I don't understand what you mean by RAM styles. Can you rephrase the question?
So the Debugger and Monitor ALWAYS need to be turn on?
I'm guessing A ~=~ $01. The pseudocode, " ~=~ " is "is now carrying..."
[It's getting late and need to sleep. I REALLY hope I learn something as I wake up. You can make edits or replies if you want!]
Quote:
So the Debugger and Monitor ALWAYS need to be turn on?
You probably always want them on while learning, yes. The debugger is what you lets run a single instruction, which is helpful for seeing the exact result of that instruction.
The monitor lets you view RAM, but it's much more willing to stay "on" than the debugger.
Code:
I'm guessing A ~=~ $01. The pseudocode, " ~=~ " is "is now carrying..."
Correct. A "is now carrying" or A "is
currently equal to".
Sorry I've not really been tracking this topic..
How to learn programming with funny comics, and easy to read follow along. This does exist, just it was all done before your time...
https://usborne.com/browse-books/featur ... ing-books/ scroll past the modern crap python stuff and you will get down to the free pfds. SO Programming Tricks and Skills, Machine Code programming for beginners, Basic for beginners, Computer battlegames etc Are great for learning. I read them when I was 6 and first got my Commodore 64. They have diagrams with robot and make puns etc.
From there
http://www.bombjack.org/commodore/books.htm Machine Language
on the Commodore 64, 128 and other Commodore Computers Revised and Expanded Edition by Jim Butterfield is
the book to learn from, Jim was a celebrity back in the late 70s and was "the expert" on 6502 and Commodore computers. The Compute's guide too books are also very nice introductions.
The Abacus books are a bit higher level, more of a professional of the era teaching guide.
Commodore 64 Assembly Language by Bruce Smith is in the middle. But if you have a book and the style or language doesn't work for you, just pick another one.
Or hit up Archive.org and read the old Compute magazines, or Your Commodore etc from back when the Commodore, Atari and Apple computers where the hottest thing on the market.
DocWaluigean, I know that
this post of mine didn't make much sense to you when you read it; but, I want you to know that rereading lots of my thread was extremely helpful to me and most of the posts that I didn't fully understand made tons more sense to me after I got more comfortable with 6502.
My post I linked describes, to the best of my ability, the most crucial assembly information I learned in college; I hope you'll revisit it after you get more comfortable with 6502.
Knowing that has made me more comfortable with 6502 because I know what's really happening at the 6502 "foundation".
p.s. Here is
booker's excellent post office RAM/ROM explanation to me. Kasumi's post office picture reminded me of booker's post.
edit: fixed spelling of "extreemly" and added an "s" to the http in my second link. Sorry.
DocWaluigean wrote:
Kasumi wrote:
Let's start with where you actually got stuck, since a few other answers you want might be a bit better understood after you get unstuck.
Quote:
Alright, I got lost on the "So click "reset". Recheck debugger if you need to." because it feels like it's starting to lose certain information.
"Reset" (next to "Run" and "Hexdump"), takes the CPU back to its initial "state". "Recheck debugger" means Check the checkbox next to the "Debugger" option. (Underneath the black box.) You have to check "Debugger" again after you click "Run". Which... is a bit annoying, but hey, it's still a good package.
So for that section starting from the total beginning (refresh the page), you want this code again (from the previous post, sorry, yes, that wasn't clear):
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Remove any code already in the box. Paste the code above into the box. Click Assemble, check "Debugger", and check "Monitor". And then continue reading the post.
Quote:
-"A did indeed get the value $01 put into it's box" ???
I described earlier in the post that A (the accumulator) was like a box that holds one value. So this put the value $01 into that box. (That is, that A now hold the value $01.) Does this make sense now?
I'll answer your questions in a different order than you asked, because they sort of flow into each other. And it's okay to not understand these things too! So long as you get to the end of that other post, I promise you're getting somewhere.
Quote:
Is "something" an address code? Real Number?
This one's tough... I want to say maybe wait for the answer, but I'll try to get the basics.
The "something" is the "addressing mode". (Edit: Kasumi learned something new today! I guess it's really called the "operand", but addressing modes are still pretty important to learn so let's go!) And it's
often an address or a real number. Most instructions have several "addressing modes". And usually the addressing mode affects which value is used, but not... the "goal" of the instruction? (Goal here is not a technical term.) For example, LDA always copies some value into the accumulator. That's its goal. The addressing mode affects how the value that gets copied is fetched.
For example #$XX (where XX is any one hexadecimal value between $00 and $FF) is called "immediate" addressing. (You don't really need to remember the names of the addressing modes.) A number symbol '#' before a value means immediate addressing. Immediate addressing means use that value given as it is. If you leave out the number symbol, it's a different addressing mode. (And you will definitely mess them up accidentally at least once in your code! It's a rite of passage.
)
lda #$00 means A (the accumulator) will get the value $00.
lda #$FF means A will get the value $FF.
Immediate is the easiest addressing mode.
Two other addressing modes are used in the post.
$XX (where XX is any value between $00 and $FF) is "zero page" addressing. $0000-$00FF in RAM are called the zero page because their leftmost digits are, well, zero. Rather than use the value of "XX" directly, it uses the value stored in RAM at $00XX.
lda $00 means A will get the value stored at $0000.
lda $08 means A will get the value stored at $0008.
$XXXX is "absolute" addressing.
lda $0200 means A will get the value stored at $0200. It's worth noting there's no guarantee an "absolute" address is RAM. What's RAM and what influences hardware is one of the things that can change between things that use 6502.
If you don't understand addressing modes, please, please don't get hung up on it. They're... eventually necessarily knowledge, but they become easier to understand once you start coding a bit.
Quote:
I know that instructions is opcode ; operation code?
Opcode is operation code, yes. Each mnemonic can have several "opcodes". And the reason for this is because of the addressing modes. LDA #$00 has a different "opcode" than LDA $00. (The different opcode is how the CPU fetches the right value to put in the accumulator.)
Shorter, the opcode is the byte that tells the CPU exactly what to do.
What the CPU does, is read a byte (the opcode), do the action associated with that byte (run the instruction, which may involve reading a few more bytes). When that instruction is done, it will read another byte, and do the action associated with that byte. Basically forever.
Again, if that doesn't make much sense, don't worry too much. You can actually get away with
never learning much about opcodes.
Quote:
-I thought you can't change the RAM styles? or was it that you can't save it?
I don't understand what you mean by RAM styles. Can you rephrase the question?
2nd
----------------------
For example #$XX (where XX is any one hexadecimal value between $00 and $FF) is called "immediate" addressing. (You don't really need to remember the names of the addressing modes.) A number symbol '#' before a value means immediate addressing. Immediate addressing means use that value given as it is. If you leave out the number symbol, it's a different addressing mode. (And you will definitely mess them up accidentally at least once in your code! It's a rite of passage. )So $XX[XX] means "While your at the Address XXXX.."
And #$XX[XX] means "Use the code found at Address XXXX..." ?
I nearly forgot what # does, but I feel it's "...Number..." But what's its used for?
Again, if that doesn't make much sense, don't worry too much. You can actually get away with never learning much about opcodes. It's kind of hard to agree with, because when I tried Debugger on Mesen on NES rom games made by Shiru, I feel much demotivated because all I see is mathematical performances on few used $0000 something. Like how am I going to make programming incredibly fun to learn?
I don't understand what you mean by RAM styles. Can you rephrase the question?There as a question by one of teachers[?] here who said you can never change the code inside the NES, but only change the code in Assembly?
unregistered wrote:
DocWaluigean, I know that
this post of mine didn't make much sense to you when you read it; but, I want you to know that rereading lots of my thread was extremely helpful to me and most of the posts that I didn't fully understand made tons more sense to me after I got more comfortable with 6502.
My post I linked describes, to the best of my ability, the most crucial assembly information I learned in college; I hope you'll revisit it after you get more comfortable with 6502.
Knowing that has made me more comfortable with 6502 because I know what's really happening at the 6502 "foundation".
p.s. Here is
booker's excellent post office RAM/ROM explanation to me. Kasumi's post office picture reminded me of booker's post.
edit: fixed spelling of "extreemly" and added an "s" to the http in my second link. Sorry.
Thanks? (I want to say it's a compliment. ^^; But I don't know if I did anything helpful..)
And thanks for the link about it.
Oziphantom wrote:
Sorry I've not really been tracking this topic..
How to learn programming with funny comics, and easy to read follow along. This does exist, just it was all done before your time...
https://usborne.com/browse-books/featur ... ing-books/ scroll past the modern crap python stuff and you will get down to the free pfds. SO Programming Tricks and Skills, Machine Code programming for beginners, Basic for beginners, Computer battlegames etc Are great for learning. I read them when I was 6 and first got my Commodore 64. They have diagrams with robot and make puns etc.
From there
http://www.bombjack.org/commodore/books.htm Machine Language
on the Commodore 64, 128 and other Commodore Computers Revised and Expanded Edition by Jim Butterfield is
the book to learn from, Jim was a celebrity back in the late 70s and was "the expert" on 6502 and Commodore computers. The Compute's guide too books are also very nice introductions.
The Abacus books are a bit higher level, more of a professional of the era teaching guide.
Commodore 64 Assembly Language by Bruce Smith is in the middle. But if you have a book and the style or language doesn't work for you, just pick another one.
Or hit up Archive.org and read the old Compute magazines, or Your Commodore etc from back when the Commodore, Atari and Apple computers where the hottest thing on the market.
THAT'S EXACTLY what I'm talking about, and what I want to accomplished on making 6502 that focuses primary on NES! Thank you so much for the link!Btw, it doesn't mean I'm leaving like that. It's stupid; there's about infinite things to learn. I'd never wanna leave th0ugh.
But however, there isn't a type of enjoyments for 6502 NES styles the way that can make us in competition between Japanese programmers and future other programmers. [So sorry if it sounds racist. I'm just jealous or appreciative how good they code with Famicom homebrews, yet I can't find the NESDev equivalent of Japan.]
Quote:
So $XX[XX] means "While your at the Address XXXX.."
$0000 through $FFFF means address. Not while you're at an address. Just an address.
$00 through $FF also means address. $00 means $0000. $FF means $00FF. $56 means $0056.
All of this specifically applies to code you plan to assemble. In the easy6502 debugger (and most debuggers), it says A=$00. But $00 in that context is not an address, it's just a value. Perhaps that's confusing, but it is how it is.
Quote:
And #$XX[XX] means "Use the code found at Address XXXX..." ?
No, this
usually denotes a number. You can also only use two (hexadecimal) digits. #$00 through #$FF are valid. #$0100 through #$FFFF are not.
Quote:
It's kind of hard to agree with, because when I tried Debugger on Mesen on NES rom games made by Shiru,
Running a debugger on a game someone else made is different than running the debugger on a game you made. Either way, you don't really need to know about opcodes because the debugger also displays the instructions as they'd appear in source code. It helps to know which names you've given to things correspond to which address (and some debuggers can import source code so you don't even need to know this), but that's not really opcodes. Knowing opcodes is way more helpful for game
hacking, which you can also get away with never learning much about.
The thing about making a 6502 guide that's focused on NES is that 6502 is easy and NES is hard. Teaching both together is like trying to teach you to juggle and solve a rubik's cube at the same time. I'd rather just help you through the rubik's cube for now. We can get to juggling later. I'm even working on what I guess will be considered an NES focused guide, but NES won't be talked about until the user is already running 6502 code.
Keep working through that post:
viewtopic.php?p=224023#p224023Edit: Missed one:
Quote:
There as a question by one of teachers[?] here who said you can never change the code inside the NES, but only change the code in Assembly?
You can't change ROM. "Read Only Memory" because it's read-only. Writes aren't allowed. That's the only rule. Which addresses are RAM (can be changed) and which are ROM also vary between things that use the CPU. $00 through $FF are a pretty safe bet to be RAM across the board, though. (NES included.)
DocWaluigean wrote:
Oziphantom wrote:
Sorry I've not really been tracking this topic..
How to learn programming with funny comics, and easy to read follow along. This does exist, just it was all done before your time...
https://usborne.com/browse-books/featur ... ing-books/ scroll past the modern crap python stuff and you will get down to the free pfds. SO Programming Tricks and Skills, Machine Code programming for beginners, Basic for beginners, Computer battlegames etc Are great for learning. I read them when I was 6 and first got my Commodore 64. They have diagrams with robot and make puns etc.
From there
http://www.bombjack.org/commodore/books.htm Machine Language
on the Commodore 64, 128 and other Commodore Computers Revised and Expanded Edition by Jim Butterfield is
the book to learn from, Jim was a celebrity back in the late 70s and was "the expert" on 6502 and Commodore computers. The Compute's guide too books are also very nice introductions.
The Abacus books are a bit higher level, more of a professional of the era teaching guide.
Commodore 64 Assembly Language by Bruce Smith is in the middle. But if you have a book and the style or language doesn't work for you, just pick another one.
Or hit up Archive.org and read the old Compute magazines, or Your Commodore etc from back when the Commodore, Atari and Apple computers where the hottest thing on the market.
THAT'S EXACTLY what I'm talking about, and what I want to accomplished on making 6502 that focuses primary on NES! Thank you so much for the link!Btw, it doesn't mean I'm leaving like that. It's stupid; there's about infinite things to learn. I'd never wanna leave th0ugh.
But however, there isn't a type of enjoyments for 6502 NES styles the way that can make us in competition between Japanese programmers and future other programmers. [So sorry if it sounds racist. I'm just jealous or appreciative how good they code with Famicom homebrews, yet I can't find the NESDev equivalent of Japan.]
Well 6502 is 6502 and the 6502 books are mostly generic. However the NES is a hard lump of metal, with zero help and it takes a lot to get anything going. You would be MUCH better off coming over to lemon64.com and doing some C64 stuff. As the C64 has a keyboard, and BASIC and disk drives, a character set, KERNAL and tonnes and tonnes of resources, editors, code snippets, book galore, the Programmers Reference Guide, and other very indepth docs.
Once you know how chars and sprites work, you can come back to the NES and learn how to do it without all the nice stuff, and without all the fancy features and well put up with the NES being a bit lame
When you learn to ski you don't start on the hard course
The NES and C64 are very similar in the methods you use to do things. Tiles, Sprites, Joysticks etc But at first you want to work on doing 5 + 7 and getting the result, to which being able to poke a memory location and then peek it in basic to get the actual number printed for you makes life a lot easier. Also we have better debugging tools
Or basically get it 'doing the thing' in the C64 emulator, then take what you have learnt and get it working in the NES emulator
What Homebrews are Japanese?
Oziphantom wrote:
DocWaluigean wrote:
Oziphantom wrote:
Sorry I've not really been tracking this topic..
How to learn programming with funny comics, and easy to read follow along. This does exist, just it was all done before your time...
https://usborne.com/browse-books/featur ... ing-books/ scroll past the modern crap python stuff and you will get down to the free pfds. SO Programming Tricks and Skills, Machine Code programming for beginners, Basic for beginners, Computer battlegames etc Are great for learning. I read them when I was 6 and first got my Commodore 64. They have diagrams with robot and make puns etc.
From there
http://www.bombjack.org/commodore/books.htm Machine Language
on the Commodore 64, 128 and other Commodore Computers Revised and Expanded Edition by Jim Butterfield is
the book to learn from, Jim was a celebrity back in the late 70s and was "the expert" on 6502 and Commodore computers. The Compute's guide too books are also very nice introductions.
The Abacus books are a bit higher level, more of a professional of the era teaching guide.
Commodore 64 Assembly Language by Bruce Smith is in the middle. But if you have a book and the style or language doesn't work for you, just pick another one.
Or hit up Archive.org and read the old Compute magazines, or Your Commodore etc from back when the Commodore, Atari and Apple computers where the hottest thing on the market.
THAT'S EXACTLY what I'm talking about, and what I want to accomplished on making 6502 that focuses primary on NES! Thank you so much for the link!Btw, it doesn't mean I'm leaving like that. It's stupid; there's about infinite things to learn. I'd never wanna leave th0ugh.
But however, there isn't a type of enjoyments for 6502 NES styles the way that can make us in competition between Japanese programmers and future other programmers. [So sorry if it sounds racist. I'm just jealous or appreciative how good they code with Famicom homebrews, yet I can't find the NESDev equivalent of Japan.]
Well 6502 is 6502 and the 6502 books are mostly generic. However the NES is a hard lump of metal, with zero help and it takes a lot to get anything going. You would be MUCH better off coming over to lemon64.com and doing some C64 stuff. As the C64 has a keyboard, and BASIC and disk drives, a character set, KERNAL and tonnes and tonnes of resources, editors, code snippets, book galore, the Programmers Reference Guide, and other very indepth docs.
Once you know how chars and sprites work, you can come back to the NES and learn how to do it without all the nice stuff, and without all the fancy features and well put up with the NES being a bit lame
When you learn to ski you don't start on the hard course
The NES and C64 are very similar in the methods you use to do things. Tiles, Sprites, Joysticks etc But at first you want to work on doing 5 + 7 and getting the result, to which being able to poke a memory location and then peek it in basic to get the actual number printed for you makes life a lot easier. Also we have better debugging tools
Or basically get it 'doing the thing' in the C64 emulator, then take what you have learnt and get it working in the NES emulator
What Homebrews are Japanese?
Hard lump of metal? I might going to need Mercury for it!...and helps...
I never played C64 sadly. But the NES has a type of love that's not even scratched the surface yet. There isn't a game that fully fully use the NES color palettes like the palette demo showing all colors at once yet, or at least one step progresses for it, and I have yet to see home-brew games that utilize Namco106 yet!
The term NES being lame just made me more determined to make learning NES codings fun.
Sounds amazing, but I'm sadly not interested yet.. I wonder if there's NESDev C64.
https://www.youtube.com/watch?v=xMB5FK2YMVA https://www.youtube.com/watch?v=hi4MM1E5f7Ehttps://youtu.be/FuQc1xpx78cthe top are self made, the bottom two are examples of extreme code edit.
Don't go chasing demos, what a machine can do when you throw the whole CPU at making it do neat stuff with special case tricks and what you can do generically in a game are two
very different things.
Demos can look like this
https://www.youtube.com/watch?v=DzQVECn3tY8But games can only look like this
https://youtu.be/ldo2ewLBt3Y?t=512My point is not to love the C64, but to take you baby steps on it, then tackle the steep climb of the NES, but if you prefer the sharpen you beak on a mountain of diamond, what ever works for you
By NesDev C64 you mean a place where C64 devs hang out and discuss programing and development?
http://www.lemon64.comhttp://www.forum64.dehttps://csdb.dk/http://www.melon64.comhttp://www.com64.net/foorumi/http://www.c64persian.tk/Also FB groups and IRC groups, I think there is even a Discord..
Also the Japanese NesDEV is here
viewforum.php?f=11
Kasumi wrote:
Quote:
So $XX[XX] means "While your at the Address XXXX.."
$0000 through $FFFF means address. Not while you're at an address. Just an address.
$00 through $FF also means address. $00 means $0000. $FF means $00FF. $56 means $0056.
All of this specifically applies to code you plan to assemble. In the easy6502 debugger (and most debuggers), it says A=$00. But $00 in that context is not an address, it's just a value. Perhaps that's confusing, but it is how it is.
Quote:
And #$XX[XX] means "Use the code found at Address XXXX..." ?
No, this
usually denotes a number. You can also only use two (hexadecimal) digits. #$00 through #$FF are valid. #$0100 through #$FFFF are not.
Quote:
It's kind of hard to agree with, because when I tried Debugger on Mesen on NES rom games made by Shiru,
Running a debugger on a game someone else made is different than running the debugger on a game you made. Either way, you don't really need to know about opcodes because the debugger also displays the instructions as they'd appear in source code. It helps to know which names you've given to things correspond to which address (and some debuggers can import source code so you don't even need to know this), but that's not really opcodes. Knowing opcodes is way more helpful for game
hacking, which you can also get away with never learning much about.
The thing about making a 6502 guide that's focused on NES is that 6502 is easy and NES is hard. Teaching both together is like trying to teach you to juggle and solve a rubik's cube at the same time. I'd rather just help you through the rubik's cube for now. We can get to juggling later. I'm even working on what I guess will be considered an NES focused guide, but NES won't be talked about until the user is already running 6502 code.
Keep working through that post:
https://forums.nesdev.com/viewtopic.php ... 23#p224023Edit: Missed one:
Quote:
There as a question by one of teachers[?] here who said you can never change the code inside the NES, but only change the code in Assembly?
You can't change ROM. "Read Only Memory" because it's read-only. Writes aren't allowed. That's the only rule. Which addresses are RAM (can be changed) and which are ROM also vary between things that use the CPU. $00 through $FF are a pretty safe bet to be RAM across the board, though. (NES included.)
I see.. Going to start over just so we can get progressions not just for me, not just for you, but for everyone.
Did the first part with red and white dots.
Now new:---
The A=$01 turns into A=$02 before revert to $01.
STA as in put new numbers / variables into the A register. It will hold on forever unless told to place it somewhere or get replaced with LDA, new number of STA, or the system turns off.
So what's the meaning with LDA/LDX/LDY when its between, "Load this data with new number, like 'Load it in with new numbers of your choice!'" and "Load the date FR0M $#????" ?
After last steps, theres 2 white pixels, and doing another step, the colors switched around!
I understands the fact that in THIS CPU of Easy6502, there's a made-up Address information where #$00XX is the Address code where it's "show one pixel with any color depending on your code choosing."
But what about if I only put "$XXXX" or "#XXXX" or "#$XXXX" ??? What's major differences and examples of using it? [I almost didn't want to ask because I want to progress..]
Oziphantom wrote:
Don't go chasing demos, what a machine can do when you throw the whole CPU at making it do neat stuff with special case tricks and what you can do generically in a game are two
very different things.
Demos can look like this
https://www.youtube.com/watch?v=DzQVECn3tY8But games can only look like this
https://youtu.be/ldo2ewLBt3Y?t=512My point is not to love the C64, but to take you baby steps on it, then tackle the steep climb of the NES, but if you prefer the sharpen you beak on a mountain of diamond, what ever works for you
By NesDev C64 you mean a place where C64 devs hang out and discuss programing and development?
http://www.lemon64.comhttp://www.forum64.dehttps://csdb.dk/http://www.melon64.comhttp://www.com64.net/foorumi/http://www.c64persian.tk/Also FB groups and IRC groups, I think there is even a Discord..
Also the Japanese NesDEV is here
http://forums.nesdev.com/viewforum.php?f=11 That's sadly true. BUUUT there is hope to make the demo with insane abilities to be able to turn into a full game if knowledge of 6502 is so great! Apple Macintosh is made with 6502, so with effort of love into programming in NES that Nintendo never thought, things can get beautiful!
It's possible to break mountains of diamonds. You just need to be smart and understand the geometries and inside Diamond's anatomy of weakness.
And alright, I'll check it out thanks!
But I am not sure if it really is the only NES/FC-focused places that makes homebrews for FC/NES [Mostly FC. I'm fine the fact I could use classic edition haha!]
The Lisa and original Macintosh used a Motorola 68000 CPU, as did the Macintosh 512K, Macintosh Plus, Macintosh SE, Macintosh Portable, Macintosh Classic, and Macintosh PowerBook 100. The closest things to a 6502 in a Mac were the 65816 as the main CPU of the Apple IIGS and the 65C02 on the Apple IIe card for Macintosh LC.
tepples wrote:
The Lisa and original Macintosh used a Motorola 68000 CPU, as did the Macintosh 512K, Macintosh Plus, Macintosh SE, Macintosh Portable, Macintosh Classic, and Macintosh PowerBook 100. The closest things to a 6502 in a Mac were the 65816 as the main CPU of the Apple IIGS and the 65C02 on the Apple IIe card for Macintosh LC.
oooooooh. VVhat does SNES CPU use? 65402? or 65302?
The Super NES's 5A22 CPU contains a 65816 core licensed from WDC and a custom memory controller.
The Sega Genesis, Neo Geo, and Capcom CPS have a 68000, like the Macintosh. CD-i has a "68070", which is a 68000 core licensed from Motorola with a less efficient address generator plus a custom memory controller. The Atari Jaguar uses a 68000 as an I/O processor alongside two glitchy 32-bit RISC CPUs.
tepples wrote:
The Super NES's 5A22 CPU contains a 65816 core licensed from WDC and a custom memory controller.
The Sega Genesis, Neo Geo, and Capcom CPS have a 68000, like the Macintosh. CD-i has a "68070", which is a 68000 core licensed from Motorola with a less efficient address generator plus a custom memory controller. The Atari Jaguar uses a 68000 as an I/O processor alongside two glitchy 32-bit RISC CPUs.
So that means 6502 code languages that I'm learning right now doesn't apply to 65816?....
@Kazumi
I'm finish with the Easy6502 test now from above the comments. Ready when you are. ^^;
DocWaluigean wrote:
But what about if I only put "$XXXX" or "#XXXX" or "#$XXXX" ??? What's major differences and examples of using it? [I almost didn't want to ask because I want to progress..]
lda $XXXX <- a now has what is stored in the memory location at XXXX
lda #XXXX <- this is not possible, its an 8bit machine
lda #$XXXX <- also not possible
LDA #XXX <- this loads the A with XXX where XXX is decimal (0-255)
LDA #$XX <- this load The A with XX where XX is in hexadecimal (0-FF)
DocWaluigean wrote:
That's sadly true. BUUUT there is hope to make the demo with insane abilities to be able to turn into a full game if knowledge of 6502 is so great! Apple Macintosh is made with 6502, so with effort of love into programming in NES that Nintendo never thought, things can get beautiful
Ok lets imagine for a second this is true (its not, but lets just imagine it is ). The Mac is butt ugly, slow and incompetent in the highest order. I mean there are machines that have a slower CPU, that cost less that can emulate it faster than it can run it self. Its monochrome, slow, has a 1bit speaker and looks ugly. What magic of a 6502 on the Mac would you be referring to?
DocWaluigean wrote:
tepples wrote:
The Super NES's 5A22 CPU contains a 65816 core licensed from WDC and a custom memory controller.
The Sega Genesis, Neo Geo, and Capcom CPS have a 68000, like the Macintosh. CD-i has a "68070", which is a 68000 core licensed from Motorola with a less efficient address generator plus a custom memory controller. The Atari Jaguar uses a 68000 as an I/O processor alongside two glitchy 32-bit RISC CPUs.
So that means 6502 code languages that I'm learning right now doesn't apply to 65816?....
65816 is a super set of 6502, it also has a pure 6502 emulation mode. So everything you learn in 6502 applies to the 65816. The 65816 is a 6502 with all the trimmings and the nice things. However this makes it easier to use, much harder to master. On the 6502 there is usually 1 way and its fairly straight forward, or when there are multiple ways they each have a clear cut advantage in one regard, less bytes or less clocks. On the 65816 there are multiple different ways to change and do things and which one is "best" really depends on everything else around it. It has some really complex concepts you need to master before you can begin to understand how to use it properly. For now stick to the 6502
DocWaluigean wrote:
So that means 6502 code languages that I'm learning right now doesn't apply to 65816?....
About 99 percent of what you learn of the 6502 will apply to the 65816. Maybe half will carry over to the 68000.
DocWaluigean wrote:
I'm finish with the Easy6502 test now from above the comments. Ready when you are. ^^;
I haven't forgotten you! I'm currently visiting a friend, so it's a bit harder to find time to respond at the moment. It seems like Oziphantom got it, but here are some things anyway.
Quote:
STA as in put new numbers / variables into the A register. It will hold on forever unless told to place it somewhere or get replaced with LDA, new number of STA, or the system turns off.
No, STA does not change the A register at all. It writes what is in the A register to an address.
Quote:
So what's the meaning with LDA/LDX/LDY when its between, "Load this data with new number, like 'Load it in with new numbers of your choice!'" and "Load the date FR0M $#????" ?
LDA always means
Loa
D the
Accumulator with a value. What follows after the LDA simply specifies how to get the value to load.You can load a value directly (LDA #$00) or load a value from an address (LDA $00).
LDX always means Load X with a value.
LDY always means Load Y with a value.
There's no such thing as #$????. The largest value can only be a maximum of two hexadecimal digits. It's also #$, not $#. This order is important.
Quote:
What's major differences and examples of using it?
edit:
It's hard to come up with examples that won't seem abstract if you don't yet understand sta. The code that draws the pixels shows LDA #$??.
As far as LDA $?? Try this following code. It is the first version of the example code (before the pixels were swapped) with two extra lines on the end that use LDA $?? and LDA $????. Step through it.
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
lda $0200;First marked line
lda $08;Second marked line
What value gets into A on the first marked line? What value gets loaded into A on the second marked line? The answer for both is the last value stored to the address that follows their LDA instruction. The addresses in both marked lines refer to a single byte of RAM. All they do is get the very last value stored into those addresses.
Change the code in the line lda #$02 to lda #$0E. Step through the code again. What value is in A after the first marked line? Can you explain specifically why that value gets loaded?
Quote:
I'm finish with the Easy6502 test now from above the comments. Ready when you are. ^^;
What is your answer to the final questions? (which weren't quite specific enough, so I'll reword them)
After changing the two numbers after LDA, how does this affect what gets displayed? (You did answer this one.)
Can you explain why that change happens specifically? "Because the numbers were changed," it not an answer. Why does changing the numbers cause that change in the display?
Kasumi wrote:
DocWaluigean wrote:
I'm finish with the Easy6502 test now from above the comments. Ready when you are. ^^;
I haven't forgotten you! I'm currently visiting a friend, so it's a bit harder to find time to respond at the moment. It seems like Oziphantom got it, but here are some things anyway.
Quote:
STA as in put new numbers / variables into the A register. It will hold on forever unless told to place it somewhere or get replaced with LDA, new number of STA, or the system turns off.
No, STA does not change the A register at all. It writes what is in the A register to an address.
Quote:
So what's the meaning with LDA/LDX/LDY when its between, "Load this data with new number, like 'Load it in with new numbers of your choice!'" and "Load the date FR0M $#????" ?
LDA always means
Loa
D the
Accumulator with a value. What follows after the LDA simply specifies how to get the value to load.You can load a value directly (LDA #$00) or load a value from an address (LDA $00).
LDX always means Load X with a value.
LDY always means Load Y with a value.
There's no such thing as #$????. The largest value can only be a maximum of two hexadecimal digits. It's also #$, not $#. This order is important.
Quote:
What's major differences and examples of using it?
edit:
It's hard to come up with examples that won't seem abstract if you don't yet understand sta. The code that draws the pixels shows LDA #$??.
As far as LDA $?? Try this following code. It is the first version of the example code (before the pixels were swapped) with two extra lines on the end that use LDA $?? and LDA $????. Step through it.
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
lda $0200;First marked line
lda $08;Second marked line
What value gets into A on the first marked line? What value gets loaded into A on the second marked line? The answer for both is the last value stored to the address that follows their LDA instruction. The addresses in both marked lines refer to a single byte of RAM. All they do is get the very last value stored into those addresses.
Change the code in the line lda #$02 to lda #$0E. Step through the code again. What value is in A after the first marked line? Can you explain specifically why that value gets loaded?
Quote:
I'm finish with the Easy6502 test now from above the comments. Ready when you are. ^^;
What is your answer to the final questions? (which weren't quite specific enough, so I'll reword them)
After changing the two numbers after LDA, how does this affect what gets displayed? (You did answer this one.)
Can you explain why that change happens specifically? "Because the numbers were changed," it not an answer. Why does changing the numbers cause that change in the display?
I'm going to say this once in this thread. I have a form of mental condition that made me really stressed out today, in form of insanity or other things. So whenever I get forms of doubts, or forms of issues, it's not my fault.
...
Because the numbers that is changing has a form of address code in it.
On this CPU of Easy6502, in #$01, or Address code 0001, 1 through F is the Address Home-code for color palettes. The one with STA ( $200 - $2FF ) is an Address Home-Code for location of a pixellated dot.
Hmm... there seems to be confusion on addresses and values.
The Accumulator (or A) contains a single 8 bit value. The accumulator is WHERE the value is stored. The value is WHAT is stored in the accumulator.
RAM is a series of 8 bit values. Each "address" of RAM refers to a specific container of an 8 bit value. Each container can "hold" one 8 bit value, not unlike how the accumulator can hold one 8 bit value.
Say we have $56 stored in RAM at location $07FF. $07FF is WHERE the value is stored. $56 is WHAT is stored there.
An address is a "where." (A, X and Y are "wheres" too, but they're not "addresses" in the same sense. It's a bit like how all squares are rectangles, but not all rectangles are squares.)
A value is a "what."
In the above example, $56 is the value stored in (or "held by") the "address" $07FF.
When you do
Code:
lda #$56
The accumulator will
always get the value $56. That is to say, after lda #$56, The accumulator will now "hold" $56.
After
Code:
lda $56
The accumulator gets the value that address $56 holds. Address $56 can hold any 8bit value. So it's possible for the accumulator to hold any 8 bit value after lda $56. But which 8 bit value the accumulator ends up holding is not "random". It's always the last thing that was written to address $56.
Code:
lda #$00;A now holds the value $00
sta $56;The RAM at address $56 now holds the value from A. The value in A is $00. So address $56 now holds the value $00.
lda $56;A now holds the value held by the RAM at address $56. The value held by address $56 is $00. So A now holds the value $00
lda #$8F;A now holds the value $8F
lda $56;A now holds the value held by the RAM at address $56. The value held by address $56 is $00. So A now holds the value $00
lda #$8F;A now holds the value $8F
sta $56;;The RAM at address $56 now holds the value from A. The value in A is $8F. So address $56 now holds the value $8F.
lda #$56;A now holds the value $56
lda $56;A now holds the value held by the RAM at address $56. The value held by address $56 is $8F. So A now holds the value $8F
Step through this code in the debugger. The thing to notice is that lda $56 is used multiple times, but A will hold either $00 or $8F afterwards. This is because when lda $56 is done it's loading what is stored there. sta $56 changes what is stored there.
If 6502, a ; starts a "comment". text after that ; is ignored by the assembler until a new line. The text following the ; doesn't get run or affect the final program at all.
Homework assignment (I guess?). Comment this example code like I have done above. It may start to make more sense:
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Then do the same for this code:
Code:
lda #$01
sta $08
lda #$01
sta $0200
lda #$02
sta $05FF
And the reason for the display difference between them should be more clear.
Kasumi wrote:
Hmm... there seems to be confusion on addresses and values.
...
I have been reading this forum for a while and I really think you should copy some of your responses to the Wiki. Sections like
http://wiki.nesdev.com/w/index.php/Programming_Basics are still half empty, and your explanations are lengthy but always good quality.
Kasumi wrote:
Hmm... there seems to be confusion on addresses and values.
The Accumulator (or A) contains a single 8 bit value. The accumulator is WHERE the value is stored. The value is WHAT is stored in the accumulator.
RAM is a series of 8 bit values. Each "address" of RAM refers to a specific container of an 8 bit value. Each container can "hold" one 8 bit value, not unlike how the accumulator can hold one 8 bit value.
Say we have $56 stored in RAM at location $07FF. $07FF is WHERE the value is stored. $56 is WHAT is stored there.
An address is a "where." (A, X and Y are "wheres" too, but they're not "addresses" in the same sense. It's a bit like how all squares are rectangles, but not all rectangles are squares.)
A value is a "what."
In the above example, $56 is the value stored in (or "held by") the "address" $07FF.
When you do
Code:
lda #$56
The accumulator will
always get the value $56. That is to say, after lda #$56, The accumulator will now "hold" $56.
After
Code:
lda $56
The accumulator gets the value that address $56 holds. Address $56 can hold any 8bit value. So it's possible for the accumulator to hold any 8 bit value after lda $56. But which 8 bit value the accumulator ends up holding is not "random". It's always the last thing that was written to address $56.
Code:
lda #$00;A now holds the value $00
sta $56;The RAM at address $56 now holds the value from A. The value in A is $00. So address $56 now holds the value $00.
lda $56;A now holds the value held by the RAM at address $56. The value held by address $56 is $00. So A now holds the value $00
lda #$8F;A now holds the value $8F
lda $56;A now holds the value held by the RAM at address $56. The value held by address $56 is $00. So A now holds the value $00
lda #$8F;A now holds the value $8F
sta $56;;The RAM at address $56 now holds the value from A. The value in A is $8F. So address $56 now holds the value $8F.
lda #$56;A now holds the value $56
lda $56;A now holds the value held by the RAM at address $56. The value held by address $56 is $8F. So A now holds the value $8F
Step through this code in the debugger. The thing to notice is that lda $56 is used multiple times, but A will hold either $00 or $8F afterwards. This is because when lda $56 is done it's loading what is stored there. sta $56 changes what is stored there.
If 6502, a ; starts a "comment". text after that ; is ignored by the assembler until a new line. The text following the ; doesn't get run or affect the final program at all.
Homework assignment (I guess?). Comment this example code like I have done above. It may start to make more sense:
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Then do the same for this code:
Code:
lda #$01
sta $08
lda #$01
sta $0200
lda #$02
sta $05FF
And the reason for the display difference between them should be more clear.
You mean the register [X, Y, A, P...] is WHERE the value is stored? Like, "Where is $20 / #$1000 / $3F stored in so it can be used later? Maybe A as in Accumulator!"
I'm guessing accumulator has absolutely nothing to do with how fast it goes, like a race cars or Sonic The Hedgehog, right?
I'm sorry, but your making it a little difficult.
The accumulator is WHERE the value is stored. The value is WHAT is stored in the accumulator.Ok, Accumulator is like a box with numbers and actions ready to be used. The Value is the object, numbers, and actions INSIDE of selected destinations like Accumulator or something like, "JOE = 23" stuff.
...
But why WHAT? What kind you mean? "What is stored in the A, Accumulator? Maybe it's 3. Maybe it could be a code to make Mario jump! Maybe it could be the recipe on making swords! Maybe it's number and Address code for pause AND exiting!"
............
I should've read first before reply...
An address is a "where." (A, X and Y are "wheres" too, but they're not "addresses" in the same sense. It's a bit like how all squares are rectangles, but not all rectangles are squares.)
A value is a "what."Obvious on how Address is where. Because they are not the same as, "Location of your friends house" or "the name of the website link or
www.com stuff."
But I don't know the entire CPU lists of simplified on what each they do.
https://wiki.nesdev.com/w/index.php/CPU_memory_map The CPU Memory Map Tokumaru showed me isn't sufficient enough because massive lack of information on what each does and what do they do, and more importantly, what's inside each by each CPU for NES. Sample RAM Map isn't sufficient enough for beginners...
[I'm sorry, am I being rude?]
Also, when doing LDA / LDX / LDY / LD? / etc. do they ALWAYS replace the number inside the A/X/Y/P/C/etc. if there's already a number-stored / variables in it?
...
I don't know why I can't read well in some situations. If I read first before write, The questions I may ask will no longer appear, and the next time I come back to this, I will be more confusing as to why I thought of that and why it's the answer or not.
---
Ok, so the limit is
Accumulator = It ALWAYS store variables / number or Math's "correct answer" into Accumulator AS "$"
X = ??? \
] - Can only do numbers. Cannot add, multiply, subtract, divide. Capable on ONLY INCrement or DECrement by 1.
Y = ??? /
---
I'm going to comment it later or soon. Because I may WAAAAYYY explain so much words..
yaros wrote:
Kasumi wrote:
Hmm... there seems to be confusion on addresses and values.
...
I have been reading this forum for a while and I really think you should copy some of your responses to the Wiki. Sections like
http://wiki.nesdev.com/w/index.php/Programming_Basics are still half empty, and your explanations are lengthy but always good quality.
Extreme irony is that my way of explaining how it works for help may also make Wiki 100% successfully functional, which is what I wanted not with Wiki, but with cartoons or similar.
Quote:
You mean the register [X, Y, A, P...] is WHERE the value is stored? Like, "Where is $20 / #$1000 / $3F stored in so it can be used later? Maybe A as in Accumulator!"
The register is WHERE
a value is stored. Each byte of RAM is WHERE
a value is stored. They all have their own value, though. So I'm not sure what you mean by
the value.
A, X, Y, $00, $07FF, $0200 whatever can all hold a single 8bit value. There's nothing more to it.
Edit: The only thing that holds two bytes is the Program Counter, which we're somewhat far from covering.
$00 is an address. $07FF is an address. $0200 is an address. If you want to get value stored there, you use that address. If you want to change the value stored there, you use that address.
Quote:
Ok, Accumulator is like a box with numbers and actions ready to be used. The Value is the object, numbers, and actions INSIDE of selected destinations like Accumulator or something like, "JOE = 23" stuff.
No, it's like a box with a SINGLE 8bit number. Just like X. Just Y. Just like $00. Just like $07FF. It cannot hold an object. It cannot hold actions. It cannot hold destinations.
Quote:
But why WHAT? What kind you mean? "What is stored in the A, Accumulator? Maybe it's 3. Maybe it could be a code to make Mario jump! Maybe it could be the recipe on making swords! Maybe it's number and Address code for pause AND exiting!"
"What is stored in the accumulator?" A single 8 bit value! So if that value is 3
"What is stored in the accumulator?" 3!
Nothing more, nothing less.
It can't be code to make Mario jump. It can't be a recipe on making swords. It will always be an 8 bit value.
Quote:
Because they are not the same as, "Location of your friends house" or "the name of the website link or
http://www.com stuff."
Why is it different than either? If you give me your friend's address, I can go there and see what's inside. If you give me a website link, I can click it and view what's there. If you give the CPU a RAM address, it can get the value there.
Edit3:
Where does your friend live? 1234 fake street.
Where is my mom's quilting page? somewebsiteiammakingup.com (not a real site)
Where do we store how many lives Mario has? $075A
If I wanted to see your friend's house, I'd go to 1234 fake street.
If I wanted to see my mom's quilting page, I'd go to somewebsiteiammakingup.com
If I wanted to see how many lives Mario has, I'd look in $075A
Quote:
But I don't know the entire CPU lists of simplified on what each they do.
Why do you need to? Nothing I've stated relies on any of that knowledge, or else I'd have taught that knowledge. Ignore anything NES related you've read or learned already.
Quote:
Sample RAM Map isn't sufficient enough for beginners...
Ignore anything NES related you've read or learned already. It will only confuse you further.
Quote:
Also, when doing LDA / LDX / LDY / LD? / etc. do they ALWAYS replace the number inside the A/X/Y/P/C/etc. if there's already a number-stored / variables in it?
Only LDX, LDA, and LDY exist. There are not others to fill LD?. Yes, they always replace the number inside. I said this in an earlier post.
Edit4: They also can't even really hold a "variable". If you load a variable (LDA $0000), you will get that value that $0000 was holding was when it was loaded. But they are separate. Changing the value of the variable doesn't change the value in the accumulator. Changing the accumulator doesn't change the value in the variable ($0000 in this example).
Edit5:
Quote:
Accumulator = It ALWAYS store variables / number or Math's "correct answer" into Accumulator AS "$"
X = ??? \
] - Can only do numbers. Cannot add, multiply, subtract, divide. Capable on ONLY INCrement or DECrement by 1.
Y = ??? /
Let's focus on that they all store a single 8 bit value for now. Gaining more knowledge on what each can do won't help with what you're stuck on now. LDA will change the 8 bit value the accumulator is holding. In the case of #$??, it will change it to $??. In the case of $????, it will change it to the value stored at address $????.
STA will change the 8 bit value at the address specified to the 8 bit value in the accumulator. Let's get these two nailed and we'll get to other stuff, I promise.
Edit2:
yaros wrote:
I have been reading this forum for a while and I really think you should copy some of your responses to the Wiki. Sections like
http://wiki.nesdev.com/w/index.php/Programming_Basics are still half empty, and your explanations are lengthy but always good quality.
I'm glad you're finding my explanations helpful. I'm not sure about the wiki, yet. I started writing some tutorials due to this thread, this is helping me see which things cause confusion while I do so.
DocWaluigean wrote:
Ok, Accumulator is like a box with numbers and actions ready to be used. The Value is the object, numbers, and actions INSIDE of selected destinations like Accumulator or something like, "JOE = 23" stuff.
...
But why WHAT? What kind you mean? "What is stored in the A, Accumulator? Maybe it's 3. Maybe it could be a code to make Mario jump! Maybe it could be the recipe on making swords! Maybe it's number and Address code for pause AND exiting!"
............
WHAT because really, the only thing that CPU can store anywhere is a number. Really, the only thing you do while programming for any CPU is you read number from one place, change it if needed, and store it in another place. What that number represents always depends on the context. But in the essence, it is just a number.
DocWaluigean wrote:
An address is a "where." (A, X and Y are "wheres" too, but they're not "addresses" in the same sense. It's a bit like how all squares are rectangles, but not all rectangles are squares.)
A value is a "what."Obvious on how Address is where. Because they are not the same as, "Location of your friends house" or "the name of the website link or
http://www.com stuff."
But I don't know the entire CPU lists of simplified on what each they do.
https://wiki.nesdev.com/w/index.php/CPU_memory_map The CPU Memory Map Tokumaru showed me isn't sufficient enough because massive lack of information on what each does and what do they do, and more importantly, what's inside each by each CPU for NES. Sample RAM Map isn't sufficient enough for beginners...
[I'm sorry, am I being rude?]
So there is a difference between registers of CPU and other memory. Registers are like pockets, they are always with you and always on the same place. You can not have more, you can not have less.
Memory addresses are different. And they are kind of like "Address of your friends house" except you have a very weird postman.
CPU has 65535 possible addresses. Physically they are just 16 wires connected to different systems.
Some addresses destinations are fixed for NES, others depends on the cartridge mapper.
So between $0000 and $07FF - it is always RAM, memory you can read and write. Because your postman is weird, next addresses are mirrored.
$0800-$0FFF - is the same as $0000-$07FF. So if you store a value (send the letter) to $0000 it will be the same if you send it to $0800 ($0001 and $0801).
DocWaluigean wrote:
Also, when doing LDA / LDX / LDY / LD? / etc. do they ALWAYS replace the number inside the A/X/Y/P/C/etc. if there's already a number-stored / variables in it?
Yes, imagine registers and memory being like pocket where you can only put one thing. If you there is already something, it will have to be thrown out.
DocWaluigean wrote:
Ok, so the limit is
Accumulator = It ALWAYS store variables / number or Math's "correct answer" into Accumulator AS "$"
X = ??? \
] - Can only do numbers. Cannot add, multiply, subtract, divide. Capable on ONLY INCrement or DECrement by 1.
Y = ??? /
Yes. Accumulator is the pocket where you get used to store your money and change. You don't usually put the wallet into the wrong pocket. It is like that. Some registers can be used with one operations, but not the others.
Kasumi wrote:
I'm glad you're finding my explanations helpful. I'm not sure about the wiki, yet. I started writing some tutorials due to this thread, this is helping me see which things cause confusion while I do so.
At least this thread questions are more or less fine for me. I am web developer who also used to program in assembler for AVR microcontrollers and had my own struggles in the beginning, so I can relate.
Kasumi wrote:
Quote:
But why WHAT? What kind you mean? "What is stored in the A, Accumulator? Maybe it's 3. Maybe it could be a code to make Mario jump! Maybe it could be the recipe on making swords! Maybe it's number and Address code for pause AND exiting!"
"What is stored in the accumulator?" A single 8 bit value! So if that value is 3
"What is stored in the accumulator?" 3!
Nothing more, nothing less.
It can't be code to make Mario jump. ... It will always be an 8 bit value.
However, if a "code" to make Mario jump
is an 8 bit value, then yes, the accumulator can hold "a code" to make Mario jump. (In my sister's game: an #$01 makes our lady character jump... and to use that value we could load it into the accumulator. After loading the #$01 into the accumulator a
jsr use_bufferInputsiii causes the Program Counter to reach the actual code that may store the #$01 into a small buffer. Then later on a routine might run; it could read that #$01 from the buffer and our lady character will jump after branching appropriately.
) DocWaluigean said "a code" and I don't want him to think this isn't possible.
I'm trying to simplify, but even in a case like you mentioned I'd argue it's the branch, and the code run after that branch (or after not branching) that actually makes the jump. The code is not the 1 held by A, but (part of) the code is the instruction that puts the 1 into A. At least, that's how I consider it.
I guess there is a way that I'd consider specifically the value in A to be (part of) code, but it's freaky expert stuff. Even then, it could only be one byte of the code that makes the jump, never all of it.
Kasumi wrote:
Homework assignment (I guess?). Comment this example code like I have done above. It may start to make more sense:
Code:
lda #$01
sta $08
lda #$02
sta $0200
lda #$01
sta $05FF
Then do the same for this code:
Code:
lda #$01
sta $08
lda #$01
sta $0200
lda #$02
sta $05FF
And the reason for the display difference between them should be more clear.
Code:
lda #$01 ; The A, Accumulator, is now holding number 1.
sta $08 ; The A's content, number 1, is being stored inside Address 08 / $0008.
lda #$02 ; The A, Accululator, is now replacing previous Register A, from number 1 into number 2.
sta $0200 ; The A's content, number 2, is now being stored into Address 01 / $0001.
lda #$01 ; The A, Accumulator, is now replacing previous used Register A, from number 2 to number 1...Again.
sta $05FF ; The A's content, number 1, is now being stored into Address $05FF, NOT Address $FF, because it would mean $00FF.
I honestly can't find unintelligent comment for this atm.
Code:
lda #$01 ; The Register A, Accumulator, is now holding number/value 1.
sta $08 ; The Register A's content, number 1, is being stored into Address $08 / $0008.
lda #$01 ; The Register A, Accumulator does nothing, as it is already carrying number/value 1. However, it will be "copy" from the previous LDA #$01 into this one. The $08 will NOT be interfering.
; Simply put, 'The Register A, Accumulator, is now holding number/value 1.' It's just explaining it again. I'm telling this so no one get's confused about differences between first and second LDA.
sta $0200 ; Store 1 into Address 0200
lda #$02 ; Replace 1 with 2 into Register A.
sta $05FF ; Store 1 into Address 05FF
Looks good/correct except for one line:
Quote:
Code:
sta $0200 ; The A's content, number 2, is now being stored into Address 01 / $0001.
Everything else you said is right. *thumbs up*
Opening Note: It may seem like I'm being picky on language, but I'm just really trying to make sure everything is understood. Please bear with me.
Quote:
lda #$02 ; The A, Accululator, is now replacing previous Register A, from number 1 into number 2.
It may be better to think of it as the number inside the accumulator being replaced by another number rather than the register itself being replaced.
Quote:
lda #$01 ; The Register A, Accumulator does nothing, as it is already carrying number/value 1. However, it will be "copy" from the previous LDA #$01 into this one.
The CPU is simply copying the value that follows "LDA" into the accumulator. It's not from earlier or anything. Any instruction has no idea what instruction was run immediately before it. As well, even if A ends up with the same number it had in it before it's important to understand that the instruction still did the copy (in LDA's case.) The instruction is ALWAYS done, even if the result would not be different.
Edit: Come to think of it, you may have explained that you did understand that in the next comment.
Sorry!
A is just storage at the end of the day. It doesn't do the actions. The instruction tells the CPU what to do, and the action may use the contents of A.
koitsu caught what I thought was the only error, but I checked again! So edit:
Code:
lda #$02 ; Replace 1 with 2 into Register A.
sta $05FF ; Store 1 into Address 05FF
Explain the mistakes in this comment in this code and the comment in the code koitsu quoted. If you can, you're ready to move on! If you can't, don't attempt the happy face assignment (below) yet.
It does seem like you've got it! So your next assignment is to make a happy face.
As we've talked about, each address that is RAM holds a single 8 bit variable. And as we've talked about the values held by $200 to $5ff in easy6502 control its little display box.
Here are the values for valid colors.
Code:
$0: Black
$1: White
$2: Red
$3: Cyan
$4: Purple
$5: Green
$6: Blue
$7: Yellow
$8: Orange
$9: Brown
$a: Light red
$b: Dark grey
$c: Grey
$d: Light green
$e: Light blue
$f: Light grey
So if I do
Code:
lda #$03
sta $0200
I will get a cyan pixel in the top left corner of the screen.
$0200 is the top left.
$05FF is the bottom right.
The screen is 32 pixels wide.This means an address that is 32 ($20) bytes after another address is the pixel below.
Code:
lda #$03
sta $0200
lda #$02
sta $0220
The address immediately after another pixel's address will be the pixel to the right. (If the pixel is already the rightmost pixel of its row, the next address is the leftmost pixel in the next row.)
Code:
lda #$0F
sta $0200
lda #$0D
sta $0201
lda #$08
sta $021F
sta $0220
Looking at the addresses in the two pieces of code above may make it clear why adding one to the rightmost pixel of a row gets the leftmost pixel of the next row. Assemble, then run these two pieces of code in easy6502 to see the results.
Now, I want you to write a program in easy6502 that makes this face:
This specific face in this specific location.
Don't try to write the entire thing before checking how it's going. Frequently check if what you're adding to the code is getting closer by clicking assemble, then run.
Don't guess which addresses belong to which pixels. Use what I outlined further above to figure out the address for pixels adjacent to the correct ones you have already drawn. Good luck! Post the program that does it.
koitsu wrote:
Looks good/correct except for one line:
Quote:
Code:
sta $0200 ; The A's content, number 2, is now being stored into Address 01 / $0001.
Everything else you said is right. *thumbs up*
OOoooh, typo. My bad.
It's Number 2 being stored into Address $0200 / $200.
There is ABSOLUTELY NO forms of advanced technique about 2 into Address 01 with $0200. The only advance technique would be $00 instead of $0000.
Kasumi wrote:
Opening Note: It may seem like I'm being picky on language, but I'm just really trying to make sure everything is understood. Please bear with me.
Quote:
lda #$02 ; The A, Accululator, is now replacing previous Register A, from number 1 into number 2.
It may be better to think of it as the number inside the accumulator being replaced by another number rather than the register itself being replaced.
Quote:
lda #$01 ; The Register A, Accumulator does nothing, as it is already carrying number/value 1. However, it will be "copy" from the previous LDA #$01 into this one.
The CPU is simply copying the value that follows "LDA" into the accumulator. It's not from earlier or anything. Any instruction has no idea what instruction was run immediately before it. As well, even if A ends up with the same number it had in it before it's important to understand that the instruction still did the copy (in LDA's case.) The instruction is ALWAYS done, even if the result would not be different.
Edit: Come to think of it, you may have explained that you did understand that in the next comment.
Sorry!
A is just storage at the end of the day. It doesn't do the actions. The instruction tells the CPU what to do, and the action may use the contents of A.
koitsu caught what I thought was the only error, but I checked again! So edit:
Code:
lda #$02 ; Replace 1 with 2 into Register A.
sta $05FF ; Store 1 into Address 05FF
Explain the mistakes in this comment in this code and the comment in the code koitsu quoted. If you can, you're ready to move on! If you can't, don't attempt the happy face assignment (below) yet.
It does seem like you've got it! So your next assignment is to make a happy face.
As we've talked about, each address that is RAM holds a single 8 bit variable. And as we've talked about the values held by $200 to $5ff in easy6502 control its little display box.
Here are the values for valid colors.
Code:
$0: Black
$1: White
$2: Red
$3: Cyan
$4: Purple
$5: Green
$6: Blue
$7: Yellow
$8: Orange
$9: Brown
$a: Light red
$b: Dark grey
$c: Grey
$d: Light green
$e: Light blue
$f: Light grey
So if I do
Code:
lda #$03
sta $0200
I will get a cyan pixel in the top left corner of the screen.
$0200 is the top left.
$05FF is the bottom right.
The screen is 32 pixels wide.This means an address that is 32 ($20) bytes after another address is the pixel below.
Code:
lda #$03
sta $0200
lda #$02
sta $0220
The address immediately after another pixel's address will be the pixel to the right. (If the pixel is already the rightmost pixel of its row, the next address is the leftmost pixel in the next row.)
Code:
lda #$0F
sta $0200
lda #$0D
sta $0201
lda #$08
sta $021F
sta $0220
Looking at the addresses in the two pieces of code above may make it clear why adding one to the rightmost pixel of a row gets the leftmost pixel of the next row. Assemble, then run these two pieces of code in easy6502 to see the results.
Now, I want you to write a program in easy6502 that makes this face:
This specific face in this specific location.
Don't try to write the entire thing before checking how it's going. Frequently check if what you're adding to the code is getting closer by clicking assemble, then run.
Don't guess which addresses belong to which pixels. Use what I outlined further above to figure out the address for pixels adjacent to the correct ones you have already drawn. Good luck! Post the program that does it.
koitsu caught what I thought was the only error, but I checked again! So edit:
Code:
lda #$02 ; Replace 1 with 2 into Register A.
sta $05FF ; Store 1 into Address 05FF
Explain the mistakes in this comment in this code and the comment in the code koitsu quoted. If you can, you're ready to move on! If you can't, don't attempt the happy face assignment (below) yet.I typo with 1 and 2. I was fixated on that single number. TwT
The REAL one would be:
Code:
lda #$02 ; Replace 1 with TWO into Register A.
sta $05FF ; Store [b]TWO[/b] into Address 05FF
---
Here's the irony part:
Then do the same for this code:
Code:
lda #$01
sta $08
lda #$01
sta $0200
lda #$02
sta $05FF
And the reason for the display difference between them should be more clear.I tried the other method like:
Code:
LDA #$01
STA $08
STA $09
and it still shows the same thing. So I am wondering why waste a code like that? Especially if the NES is a really POOR kb storages without Mapper? Obviously is to organize things like that, but whatever happened to the " ;------- " this and " ; *** CHARACTER MOVEMENT ENGINE *** " ??? I seen a lot of this stuff in SmileBASIC, and they don't care of wasting codes! They had fun drawing on the codes!
I wish every homebrew games, even mine, have a source code shown out, but that's just me.
Yeeeeesh...
Code:
lda #$04
sta $0200
sta $0201
sta $0202
sta $0203
sta $0204
sta $0205
sta $0206
sta $0207
sta $0208
sta $0209
sta $020A
sta $020B
sta $020C
sta $020D
sta $020E
sta $020F
sta $0210
sta $0211
sta $0212
sta $0213
sta $0214
sta $0215
sta $0216
sta $0217
sta $0218
sta $0219
sta $021A
sta $021B
sta $021C
sta $021D
sta $021E
sta $021F
;-------
sta $0220
sta $023F
sta $0240
sta $025F
sta $0260
sta $027F
sta $0280
sta $029F
sta $02A0
sta $02BF
sta $02C0
sta $02DF
sta $02E0
sta $02FF
sta $0300
sta $031F
sta $0320
sta $033F
sta $0340
sta $035F
sta $0360
sta $037F
sta $0380
sta $039F
;-----
sta $03A0
sta $03A1
sta $03A2
sta $03A3
sta $03A4
sta $03A5
sta $03A6
sta $03BF
sta $03BE
sta $03BD
sta $03BC
sta $03BB
sta $03BA
sta $03B9
;*
sta $0398
sta $0397
sta $0396
sta $0395
sta $0394
sta $0387
sta $0388
sta $0389
sta $038A
sta $038B
;*
sta $0370
sta $0371
sta $0372
sta $0373
sta $036F
sta $036E
sta $036D
sta $036C
;*******************
;---
lda #$01
sta $038C
sta $03AC
sta $03CC
sta $03EC
sta $0393
sta $03B3
sta $03D3
sta $03F3
;---
sta $04AA
sta $04CB
sta $04CC
sta $04CD
sta $04CE
sta $04CF
sta $04D0
sta $04D1
sta $04D2
sta $04D3
sta $04D4
sta $04B5
;---
lda #$08
sta $03C0
sta $03DF
sta $03E0
sta $03FF
sta $0400
sta $041F
sta $0420
sta $043F
sta $0440
sta $045F
sta $0460
sta $047F
sta $0480
sta $049F
sta $04A0
sta $04BF
sta $04C0
sta $04DF
sta $04E0
sta $04FF
sta $0500
sta $051F
sta $0520
sta $053F
sta $0540
sta $055F
sta $0560
sta $057F
sta $0580
sta $059F
sta $05A0
sta $05BF
sta $05C0
sta $05DF
sta $05FF
sta $05E0
sta $05E1
sta $05E2
sta $05E3
sta $05E4
sta $05E5
sta $05E6
sta $05E7
sta $05E8
sta $05E9
sta $05EA
sta $05EB
sta $05EC
sta $05ED
sta $05EE
sta $05EF
sta $05F0
sta $05F1
sta $05F2
sta $05F3
sta $05F4
sta $05F5
sta $05F6
sta $05F7
sta $05F8
sta $05F9
sta $05FA
sta $05FB
sta $05FC
sta $05FD
sta $05FE
Edit: Oh. It didn't show me you made a post before I made this one. >_>
You did make a face! A different shape and position, but I'm cool with that, actually. And the face you made we'll actually get back to later. Because there's a way to do it in way fewer instructions which may fix some of the "Yeeeeesh..." factor, but there's a bit more to learn before it will make sense.
Quote:
and it still shows the same thing. So I am wondering why waste a code like that?
This would be your first "optimization". You are correct that that second LDA with the same number does not change the result and is not needed there! Seeing this means you are definitely getting it. Give that face a shot!
Just to explain, I did it that way to each instruction could be compared 1 to 1.
One of the largest NES homebrew games (that's actually assembly language) is open source:
https://github.com/NovaSquirrel/NovaThe ... src/main.sThere are also quite a few open source ones written in C. After the face exercise, I'll hit cover like 8 more instructions (they're all super easy if you can make the face). After that a bit more about addressing modes (covered earlier). And then we'll hit two very important things that make up how 6502 programs "make decisions" rather than do the same thing every time.
Here are a few "new" instructions. "Try 'em, they're easy!" I always say most of the things one can do in 6502 have a small, and simple result. (I really mean actually try them! Use the debugger, step through, and see how the "state" of the CPU changes. They are simple, but still look at them.)
We've covered LDA! Now meet its siblings, LDX and LDY. They do the same task, except they place a number in X or Y instead of A.
Code:
lda #$07;A now holds the number 7
ldx #$09;X now hold the number 9
ldy #$FF;Y now holds the number 255 ($FF)
Really! The primary difference is that they make X or Y hold a different number rather than A.
(There are other differences we'll cover later. LDA has more "addressing modes" which were mentioned in an earlier post. LD? #$?? is one addressing mode and all three LD? instructions can do that. LD? $?? is another and all three LD? instructions can do that. LD? $???? is the last one we've gone over, and again, all three LD? instructions can do that. But there are additional modes all three don't have.)
And two more! We've covered STA! Now meets its siblings STX and STY. And if you guessed they do the same thing as STA except they place the number in X or Y into the address instead of the number in A, by golly, you're right!
Code:
ldx #$07;X now hold the number 7
stx $05FF;$05FF now holds the number 7
ldy #$FF;Y now holds the number 255 ($FF)
sty $0200;$0200 now holds the number 255
And you may wonder, "Why have all three of A, X and Y when LDX/STX and LDY/STY pairs can basically be used interchangeably with LDA/STA pairs?" And it's a two part answer. The first part is, "There are instructions that can ONLY use the contents of A where there are not 'sibling' instructions for X and Y. Similarly, there are instructions that can ONLY use the contents of X or Y where there is not a 'sibling' instruction for A."
And the second part are the different "addressing modes" allowed. I promise when we get there it will make sense why X/Y don't have access to the same addressing modes as A.
The important thing to understand for these is that A, X and Y are all independent. Remember the comment you made "$08 will not be interfering"? It's a bit like that. Changing A won't change X or Y. Storing X won't affect A, or Y.
Just so you know, the next TEN instructions we'll learn will as simple as the ones above. (Some will actually be even simpler!)
I still want to give a quick assignment, but since these instructions are so similar I will be pickier about the result.
I want you to change your face code you have so that:
1. The eye on the left of the display is drawn using values from X rather than A.
2. The eye on the right of the display is drawn using values from Y rather than A.
3. The eye on the left of the display must be light green.
4. The eye on the right of the display must be light blue.
Edit: I made it more specific about left/right since I forgot that can be ambiguous.
You can post only the code that draws the eyes rather than all of it since I realize it's a lot of code right now.
Kasumi wrote:
Here are a few "new" instructions. "Try 'em, they're easy!" I always say most of the things one can do in 6502 have a small, and simple result. (I really mean actually try them! Use the debugger, step through, and see how the "state" of the CPU changes. They are simple, but still look at them.)
We've covered LDA! Now meet its siblings, LDX and LDY. They do the same task, except they place a number in X or Y instead of A.
Code:
lda #$07;A now holds the number 7
ldx #$09;X now hold the number 9
ldy #$FF;Y now holds the number 255 ($FF)
Really! The primary difference is that they make X or Y hold a different number rather than A.
(There are other differences we'll cover later. LDA has more "addressing modes" which were mentioned in an earlier post. LD? #$?? is one addressing mode and all three LD? instructions can do that. LD? $?? is another and all three LD? instructions can do that. LD? $???? is the last one we've gone over, and again, all three LD? instructions can do that. But there are additional modes all three don't have.)
And two more! We've covered STA! Now meets its siblings STX and STY. And if you guessed they do the same thing as STA except they place the number in X or Y into the address instead of the number in A, by golly, you're right!
Code:
ldx #$07;X now hold the number 7
stx $05FF;$05FF now holds the number 7
ldy #$FF;Y now holds the number 255 ($FF)
sty $0200;$0200 now holds the number 255
And you may wonder, "Why have all three of A, X and Y when LDX/STX and LDY/STY pairs can basically be used interchangeably with LDA/STA pairs?" And it's a two part answer. The first part is, "There are instructions that can ONLY use the contents of A where there are not 'sibling' instructions for X and Y. Similarly, there are instructions that can ONLY use the contents of X or Y where there is not a 'sibling' instruction for A."
And the second part are the different "addressing modes" allowed. I promise when we get there it will make sense why X/Y don't have access to the same addressing modes as A.
The important thing to understand for these is that A, X and Y are all independent. Remember the comment you made "$08 will not be interfering"? It's a bit like that. Changing A won't change X or Y. Storing X won't affect A, or Y.
Just so you know, the next TEN instructions we'll learn will as simple as the ones above. (Some will actually be even simpler!)
I still want to give a quick assignment, but since these instructions are so similar I will be pickier about the result.
I want you to change your face code you have so that:
1. The eye on the left of the display is drawn using values from X rather than A.
2. The eye on the right of the display is drawn using values from Y rather than A.
3. The eye on the left of the display must be light green.
4. The eye on the right of the display must be light blue.
Edit: I made it more specific about left/right since I forgot that can be ambiguous.
You can post only the code that draws the eyes rather than all of it since I realize it's a lot of code right now.
Like this?
Code:
lda #$04 ; Hat Horizonally [Left/Right]
sta $0200
sta $0201
sta $0202
sta $0203
sta $0204
sta $0205
sta $0206
sta $0207
sta $0208
sta $0209
sta $020A
sta $020B
sta $020C
sta $020D
sta $020E
sta $020F
sta $0210
sta $0211
sta $0212
sta $0213
sta $0214
sta $0215
sta $0216
sta $0217
sta $0218
sta $0219
sta $021A
sta $021B
sta $021C
sta $021D
sta $021E
sta $021F
;-------
sta $0220 ; Hat Vertically [Up/Down]
sta $023F
sta $0240
sta $025F
sta $0260
sta $027F
sta $0280
sta $029F
sta $02A0
sta $02BF
sta $02C0
sta $02DF
sta $02E0
sta $02FF
sta $0300
sta $031F
sta $0320
sta $033F
sta $0340
sta $035F
sta $0360
sta $037F
sta $0380
sta $039F
;----- Hat Curved [HARD PART]
sta $03A0
sta $03A1
sta $03A2
sta $03A3
sta $03A4
sta $03A5
sta $03A6
sta $03BF
sta $03BE
sta $03BD
sta $03BC
sta $03BB
sta $03BA
sta $03B9
;*
sta $0398
sta $0397
sta $0396
sta $0395
sta $0394
sta $0387
sta $0388
sta $0389
sta $038A
sta $038B
;*
sta $0370
sta $0371
sta $0372
sta $0373
sta $036F
sta $036E
sta $036D
sta $036C
;******************* VVV NEW VVV
;---
ldx #$0D ; Eye Color Light Green Left
stx $038C
stx $03AC
stx $03CC
stx $03EC
ldy #$0E ; Eye Color Light Blue Right
sty $0393
sty $03B3
sty $03D3
sty $03F3
;---
;******************** ^^^ NEW ^^^
lda #$01 ; Lip color White
sta $04AA
sta $04CB
sta $04CC
sta $04CD
sta $04CE
sta $04CF
sta $04D0
sta $04D1
sta $04D2
sta $04D3
sta $04D4
sta $04B5
;---
lda #$08
sta $03C0
sta $03DF
sta $03E0
sta $03FF
sta $0400
sta $041F
sta $0420
sta $043F
sta $0440
sta $045F
sta $0460
sta $047F
sta $0480
sta $049F
sta $04A0
sta $04BF
sta $04C0
sta $04DF
sta $04E0
sta $04FF
sta $0500
sta $051F
sta $0520
sta $053F
sta $0540
sta $055F
sta $0560
sta $057F
sta $0580
sta $059F
sta $05A0
sta $05BF
sta $05C0
sta $05DF
sta $05FF
sta $05E0
sta $05E1
sta $05E2
sta $05E3
sta $05E4
sta $05E5
sta $05E6
sta $05E7
sta $05E8
sta $05E9
sta $05EA
sta $05EB
sta $05EC
sta $05ED
sta $05EE
sta $05EF
sta $05F0
sta $05F1
sta $05F2
sta $05F3
sta $05F4
sta $05F5
sta $05F6
sta $05F7
sta $05F8
sta $05F9
sta $05FA
sta $05FB
sta $05FC
sta $05FD
sta $05FE
Yep, that's what I wanted.
Now let's get most of the remaining easy instructions out of the way. But realize things will get a bit harder after this since we'll introduce new concepts.
First, the "transfer" family. They're somewhat similar to the "LD?" family of instructions. They copy a new value into A, or X or Y.
There are four of these. TXA, TYA, TAX and TAY.
TXA is Transfer X to the Accumulator.
Code:
ldx #$02;X now holds the value $02
txa;A now holds the value $02
TXA is basically what LDA X would be. It retrieves the value from X, and copies it to the accumulator.
TYA is Transfer Y to the Accumulator.
Code:
ldy #$FF;Y now holds the value $FF
tya;A now holds the value $FF
TYA is basically what LDA Y would be. It retrieves the value from Y, and copies it to the accumulator.
And I bet you can already guess what TAX and TAY do.
TAX is Transfer the Accumulator to X.
Code:
lda #$80;A now holds the value $80
tax;X now holds the value $80
TAX is basically would LDX A would be. It retrieves the value from the accumulator, and copies it to X.
TAY is Transfer the Accumulator to Y.
Code:
lda #$7F;A now holds the value $7F
tay;Y now holds the value $7F
TAY is basically what LDY A would be. It retrieves the value from the accumulator, and copies it to Y.
Transfer source register to destination register. But the name is sort of misleading. It is a copy. When you transfer X to A, the value in X does not change.
What about TXY and TYX? The CPU only does a few things, and those just happen to not be in the set of things it can do. If you want to transfer X to Y, you can do this:
Code:
ldx #$80;X now holds the value $80
txa;A now holds the value $80
tay; Y now holds the value $80
That gets rid of the value in A, though.
Supposing you don't want to change A in the process...
Code:
ldx #$80;
stx $00;Store the value $80 from X into RAM
ldy $00;Load the value $80 from RAM.
Programming is using what the CPU
can do to accomplish what you want done. If there's not an instruction for the task, you use multiple instructions to get what you want.
The next family for this post is also simple. The increment and decrement family. Increments add one to things. Decrements subtract one from things. The instructions in this family are INX, INY, INC, DEX, DEY, DEC.
INX is INcrement X. It adds one to X. Nothing more, nothing less.
Code:
LDX #$00;X now holds the value $00
INX;X now holds the value $01
INX;X now holds the value $02
LDX #$FF;X now holds the value $FF
INX;X now holds the value $00
Notice it is subject to wraparound. If you add one to 255 ($FF), you will get zero because X can't hold a larger number. It's only an 8 bit value. This is true for the entire increment family.
INY is INcrement Y. It adds one to Y. Nothing more, nothing less.
Code:
LDY #$49;X now holds the value $49
INY;Y now holds the value $4A
INC is INCrement memory. It adds one to the value stored in the address given to it. Nothing more, nothing less.
Code:
lda #$26;A now holds the value $26
sta $00;$00 now holds the value $26
inc $00;$00 now holds the value $27
ldx #$40;X now holds the value $40
stx $0200;$0200 now holds the value $40
inc $0200;$0200 now holds the value $41
Much like sta, inc can act on the $?? and $???? addressing modes.
And now the decrement family, which is no more complicated than the increment family.
DEY is DEcrement Y. It subtracts one from Y. Nothing more, nothing less.
Code:
ldy #$00;Y now holds the value $00
dey;Y now holds the value $FF
dey;Y now holds the value $FE
Much like how 255 ($FF) is the highest number, 0 is the lowest number. Subtracting 1 from 0 will get $FF because it's only an 8 bit value. This is true for the entire decrement family.
DEX is DEcrement X. It subtract one from X. Nothing more, nothing less.
Code:
ldx #$54;X now holds the value $54
dex;X now holds the value $53
DEC is DECrement memory. It subtracts one from the value stored in the address given to it. Nothing more, nothing less.
Code:
ldy #$A0;Y now holds the value $A0
sty $FF;$FF now holds the value $A0
dec $FF;$FF now holds the value $9F
lda #$EB;A now holds the value $EB
sta $0234;$0234 now holds the value $EB
dec $0234;$0234 now holds the value $EA
What about INA and DEA? They don't exist! Like I said in an earlier post, there are some instructions without equivalent siblings for all registers. So your assignment this time is: You have a value in A. Find a way to get one less than that value in A (regardless of what that value in A was) using what the CPU
can do.
The four transfers and the six increment/decrement instructions make the ten simple instructions I mentioned in my last post. If you have questions, about any of these two instruction families, let me know. Otherwise, write code that "decrements A" and we'll start to get to how "decision making" in 6502 works.
Edit: And as before. These seem simple (and the concepts of them are), but still check the examples just to get used to typing them. And maybe I made a mistake in an example! (I didn't purposefully leave one to find, but I had a little less time to check the examples than I usually do.)
Kasumi wrote:
Yep, that's what I wanted.
Now let's get most of the remaining easy instructions out of the way. But realize things will get a bit harder after this since we'll introduce new concepts.
First, the "transfer" family. They're somewhat similar to the "LD?" family of instructions. They copy a new value into A, or X or Y.
There are four of these. TXA, TYA, TAX and TAY.
TXA is Transfer X to the Accumulator.
Code:
ldx #$02;X now holds the value $02
txa;A now holds the value $02
TXA is basically what LDA X would be. It retrieves the value from X, and copies it to the accumulator.
TYA is Transfer Y to the Accumulator.
Code:
ldy #$FF;Y now holds the value $FF
tya;A now holds the value $FF
TYA is basically what LDA Y would be. It retrieves the value from Y, and copies it to the accumulator.
And I bet you can already guess what TAX and TAY do.
TAX is Transfer the Accumulator to X.
Code:
lda #$80;A now holds the value $80
tax;X now holds the value $80
TAX is basically would LDX A would be. It retrieves the value from the accumulator, and copies it to X.
TAY is Transfer the Accumulator to Y.
Code:
lda #$7F;A now holds the value $7F
tay;Y now holds the value $7F
TAY is basically what LDY A would be. It retrieves the value from the accumulator, and copies it to Y.
Transfer source register to destination register. But the name is sort of misleading. It is a copy. When you transfer X to A, the value in X does not change.
What about TXY and TYX? The CPU only does a few things, and those just happen to not be in the set of things it can do. If you want to transfer X to Y, you can do this:
Code:
ldx #$80;X now holds the value $80
txa;A now holds the value $80
tay; Y now holds the value $80
That gets rid of the value in A, though.
Supposing you don't want to change A in the process...
Code:
ldx #$80;
stx $00;Store the value $80 from X into RAM
ldy $00;Load the value $80 from RAM.
Programming is using what the CPU
can do to accomplish what you want done. If there's not an instruction for the task, you use multiple instructions to get what you want.
The next family for this post is also simple. The increment and decrement family. Increments add one to things. Decrements subtract one from things. The instructions in this family are INX, INY, INC, DEX, DEY, DEC.
INX is INcrement X. It adds one to X. Nothing more, nothing less.
Code:
LDX #$00;X now holds the value $00
INX;X now holds the value $01
INX;X now holds the value $02
LDX #$FF;X now holds the value $FF
INX;X now holds the value $00
Notice it is subject to wraparound. If you add one to 255 ($FF), you will get zero because X can't hold a larger number. It's only an 8 bit value. This is true for the entire increment family.
INY is INcrement Y. It adds one to Y. Nothing more, nothing less.
Code:
LDY #$49;X now holds the value $49
INY;Y now holds the value $4A
INC is INCrement memory. It adds one to the value stored in the address given to it. Nothing more, nothing less.
Code:
lda #$26;A now holds the value $26
sta $00;$00 now holds the value $26
inc $00;$00 now holds the value $27
ldx #$40;X now holds the value $40
stx $0200;$0200 now holds the value $40
inc $0200;$0200 now holds the value $41
Much like sta, inc can act on the $?? and $???? addressing modes.
And now the decrement family, which is no more complicated than the increment family.
DEY is DEcrement Y. It subtracts one from Y. Nothing more, nothing less.
Code:
ldy #$00;Y now holds the value $00
dey;Y now holds the value $FF
dey;Y now holds the value $FE
Much like how 255 ($FF) is the highest number, 0 is the lowest number. Subtracting 1 from 0 will get $FF because it's only an 8 bit value. This is true for the entire decrement family.
DEX is DEcrement X. It subtract one from X. Nothing more, nothing less.
Code:
ldx #$54;X now holds the value $54
dex;X now holds the value $53
DEC is DECrement memory. It subtracts one from the value stored in the address given to it. Nothing more, nothing less.
Code:
ldy #$A0;Y now holds the value $A0
sty $FF;$FF now holds the value $A0
dec $FF;$FF now holds the value $9F
lda #$EB;A now holds the value $EB
sta $0234;$0234 now holds the value $EB
dec $0234;$0234 now holds the value $EA
What about INA and DEA? They don't exist! Like I said in an earlier post, there are some instructions without equivalent siblings for all registers. So your assignment this time is: You have a value in A. Find a way to get one less than that value in A (regardless of what that value in A was) using what the CPU
can do.
The four transfers and the six increment/decrement instructions make the ten simple instructions I mentioned in my last post. If you have questions, about any of these two instruction families, let me know. Otherwise, write code that "decrements A" and we'll start to get to how "decision making" in 6502 works.
Edit: And as before. These seem simple (and the concepts of them are), but still check the examples just to get used to typing them. And maybe I made a mistake in an example! (I didn't purposefully leave one to find, but I had a little less time to check the examples than I usually do.)
Waaaaay too much info, and looking through it, I feel it's repeating. O-o
Going to try to read it.
---
Stuff like transfer feels REALLY worthless. Is there a good example of using TXY and TXA stuff BESIDE "10000 score = one life" ?
So apparently the numerical system in this 6502 8-bit "integer" [numbers from 0 to 255.] is a WHEEL, instead of a road, where if you reach 255 and go one more, it will revert back to 0. [Maaaybe revert into -255??? I doubt it.]
Code:
LDA #$01 ; "Load it up!" number 1 into Register A.
STA $0205 ; Store number 1 from Register A into Address $0205.
INC $0205 ; Increment, or add one number, into Address $0205, making it number 2 now.
LDX #$02 ; "Load it up!" or put number 2 into Register X.
STX $0203 ; Store Register X [Number 2] into Address $0203.
INC $0203 ; INCrement one number into $0203, making it number 3 now.
LDY #$03 ; "Load number three into Register Y." or put number 3 into Register Y.
STY $0201 ; Store number 3 into Address $0201.
INC $0201 ; INCrement, or fancy word of adding 1 [and nothing else.] into Address $0201, which now has number 2 instead of number 1.
STA $0200 ; Use the recently used Register A, which contains 1, and put it into Address $0200.
;------
DEC $0204 ; Decrement, or subtract by one only, Address $0204. While the number contained inside is nothing, also as ZERO, it's goes backwards into the maximum number of what Address $0204 can hold. Obviously the maximum for each addresses is $FF, but in this case of 6502 engine for Easy6502, the maximum number would be $0F, resulting in light gray.
DEC $0204 ; DECrement, or subtract by one, already subtracted Address $0204. It's now $0E, which is light blue.
koitsu wrote:
It's really pretty simple: you can think of 6502 registers as variables which can only hold values ranging from 0 to 255. The 6502 code that's equivalent to the above would be:
Code:
foo = $00 ; Memory location $00
bar = $01 ; Memory location $01
qux = $02 ; Memory location $02
lda #5
sta foo ; foo = 5
lda #7
sta bar ; bar = 7
lda bar
sta foo ; foo = bar
lda foo
sta qux ; qux = foo
Judging by what I know now atm [I'm so sorry?] :
-Why lowercase for all opcodes? I'm more fixated on capital one.
- Shouldn't it be,
foo:
$00
bar:
$01
qux:
$02
???
-And what do you mean about "$00 = memory location $00?" Is it the Address code, or a type of number? And I think #N doesn't work, but #$N works.
DocWaluigean wrote:
Stuff like transfer feels REALLY worthless. Is there a good example of using TXY and TXA stuff BESIDE "10000 score = one life" ?
There are many cases where transferring one register to another can be useful. Like you already know, some operations can be done on some registers but not others, so you may need to load a value in one register, do something that can only be done with that register, then transfer it to another register and do something that can only be done in that register.
Another use is when you need 2 registers to have the same value. You can do it like this:
Code:
lda #$00
ldx #$00
But this uses less ROM:
Code:
lda #$00
tax
BTW, "10000 score = one life" is not something you'd use the transfer operations for... Normally you'd detect when a specific score digit changes every time the score increases, and then increase the number of lives as well. You'll see how this works when you get to the conditional instructions.
DocWaluigean wrote:
-And what do you mean about "$00 = memory location $00?" Is it the Address code, or a type of number?
When you're doing small test programs, it's fine to type memory addresses manually, but as programs get larger, it becomes really hard to remember what each address is used for. A game can easily have hundreds of variables, and unless you're Rain Man or something, you won't be able to remember where each of those variables is. So, in order to make our lives easier, we give nicknames to the various addresses we need to use, so we can look at these names and instantly know what the variables are for.
Instead of remembering that the number of lives is stored in address $037B, you just do
Lives = $037B at the beginning of the program and use the word "Lives" whenever we want to access that address.
Quote:
And I think #N doesn't work, but #$N works.
#N works, it means "immediate decimal", while #$N means "immediate hexadecimal".
tokumaru wrote:
There are many cases where transferring one register to another can be useful. Like you already know, some operations can be done on some registers but not others, so you may need to load a value in one register, do something that can only be done with that register, then transfer it to another register and do something that can only be done in that register.
Another use is when you need 2 registers to have the same value. You can do it like this:
Code:
lda #$00
ldx #$00
But this uses less ROM:
Code:
lda #$00
tax
So your saying Transfer Opcodes is like "Copy and Paste from one code to another?"
And what about directly move A / X / Y from one to X / Y / A, with the A / X / Y left as blank or zero?
Code:
--Pseudocode--
LDA #$10 ; Put number 10 into Register A.
MAX ; Move the number 10 from Register A into Register X, making Register A empty zero.
STX $1000 ; Store number 10 from Register X into Address $1000.
tokumaru wrote:
BTW, "10000 score = one life" is not something you'd use the transfer operations for... Normally you'd detect when a specific score digit changes every time the score increases, and then increase the number of lives as well. You'll see how this works when you get to the conditional instructions.
When you're doing small test programs, it's fine to type memory addresses manually, but as programs get larger, it becomes really hard to remember what each address is used for. A game can easily have hundreds of variables, and unless you're Rain Man or something, you won't be able to remember where each of those variables is. So, in order to make our lives easier, we give nicknames to the various addresses we need to use, so we can look at these names and instantly know what the variables are for.
Instead of remembering that the number of lives is stored in address $037B, you just do Lives = $037B at the beginning of the program and use the word "Lives" whenever we want to access that address.
So basically=== In this 6502 senses ===
The "=" sign is to give value to any names like the example, "JOE = 3"?
The ":" sign with enter-space is to carry many codes and numbers and operations to be used many times or used later?
Quote:
#N works, it means "immediate decimal", while #$N means "immediate hexadecimal".
Ah, so...
Code:
LDA #$10 ; Number 16 in HEX
is basically the exact same as...
Code:
LDA #16 ; Number 16 in regular number / decimal style. Nothing special, just regular numbers, no binary, no HEX effect, just regular number. Negative Integers doesn't count? Or decimal like 1.5 included in immediate decimal?
???
ldx #$20 and
ldx #32 both put the number 32 in register X.
lda #$45 and
lda #69 both put the number 69 in register A. So does
lda #'E', as the ASCII code for capital E is 69 (or $45). When we eventually get to writing text to the screen, you'll start dealing with
ASCII codes.
If you want to
move the value in A to X, you need to clear A afterward:
Code:
lda #24 ; A contains 24
tax ; A contains 24, X contains 24
lda #0 ; A contains 0, X contains 24
tepples wrote:
ldx #$20 and
ldx #32 both put the number 32 in register X.
lda #$45 and
lda #69 both put the number 69 in register A. So does
lda #'E', as the ASCII code for capital E is 69 (or $45). When we eventually get to writing text to the screen, you'll start dealing with
ASCII codes.
If you want to
move the value in A to X, you need to clear A afterward:
Code:
lda #24 ; A contains 24
tax ; A contains 24, X contains 24
lda #0 ; A contains 0, X contains 24
Ah, so "#" and "#$" can be used. Is the binary [WAY advanced] also used like "B$"? [No way I'm doing any type of troll. Trust me, it happens with any programming irony.]
And on the move the value, MOVE move, not copy move, would that be a type of issues in memory waste? I been thinking of every single words of opcodes, numbers, would waste one space, and less words, numbers, and opcodes means saving more memories.
Why isn't ASCII code mentioned in the Bunnyboys...? Obviously difficult, but still... e-e;;;
This is going to be a loooong time for me to finally master 6502 and draw animations of edutainment for it.
DocWaluigean wrote:
Ah, so "#" and "#$" can be used. Is the binary [WAY advanced] also used like "B$"?
Binary depends on what assembler you're using. I don't think Easy 6502's assembler supports binary, but ca65 uses
% for binary
Code:
lda #$45
lda #%01000101
Negative numbers on 6502 are represented using
two's complement, which exploits the fact that addition wraps at 256. For example, -3 is represented as 256 - 3, or $FD.
Code:
lda #253
lda #$FD
lda #-3
lda #<-3 ; Some assemblers require < before all negative numbers because
; they check that all values are in 0-255 range
Add 253 to 6 and you get 259, which wraps to 3.
Decimals are a bit more complicated; you'll learn
fixed-point arithmetic sometime after you learn how to add numbers bigger than 256.
Yes, it was a lot of info, and yes a lot of it was similar (hence feeling repeated), but that's also why I did so much.
IN? adds one.
DE? subtracts one.
T12 copies the value from register 1 to register 2.
You can't INA, you can't DEA, you can't TXY and you can't TYX.
That's all 10 instructions. That's the short version of my last post.
Quote:
So apparently the numerical system in this 6502 8-bit "integer" [numbers from 0 to 255.] is a WHEEL, instead of a road, where if you reach 255 and go one more, it will revert back to 0. [Maaaybe revert into -255??? I doubt it.
Like I said in an earlier post, it's "always an 8 bit value." Thinking of it like a wheel is fine.
Quote:
DEC $0204 ; Decrement, or subtract by one only, Address $0204. While the number contained inside is nothing, also as ZERO, it's goes backwards into the maximum number of what Address $0204 can hold. Obviously the maximum for each addresses is $FF, but in this case of 6502 engine for Easy6502, the maximum number would be $0F, resulting in light gray.
Although it's true that in easy6502 the "default" value for RAM is 0, this is NOT a guarantee. One should not assume RAM to start with a given value.
On NES, the starting value of RAM is "random". So if you did dec $0204 at the start expecting the result to be $FF, your program would likely break later when you tried to use that value.
Quote:
Stuff like transfer feels REALLY worthless. Is there a good example of using TXY and TXA stuff BESIDE "10000 score = one life" ?
Say you want to subtract 1 from the accumulator, like the assignment.
Code:
tax
dex
txa
There's a way to subtract 1 from the accumulator too (we'll get there later), but it uses more bytes. (Same number of instructions, though.) But using more byte might be better if you don't want to avoid changing the value in X. Programming is thinking about trade-offs like that.
Tokumaru covered another example that ended up using fewer bytes.
Quote:
-Why lowercase for all opcodes? I'm more fixated on capital one.
It doesn't make a difference in a lot of assemblers these days. Lowercase means you don't have to hold shift or switch capslock on and off, so I prefer it.
It's also very good that you're rereading earlier posts. There's a lot of good info in them.
Quote:
And what about directly move A / X / Y from one to X / Y / A, with the A / X / Y left as blank or zero?
I said in the last post that sometimes, the CPU can't do things in one instruction. That's how programming works. If the thing you want to do doesn't exist, you use the things that do exist to make what you want to happen actually happen. Like the example you quoted.
As far as wasting space... if you don't need the accumulator to be zero after transferring the value to X, then just don't do the load after. If you need to use more instructions to do the job, it's not wasting anything, it's just doing the job.
Code:
LDX #$02 ; "Load it up!" or put number 2 into Register X.
STX $0203 ; Store Register X [Number 2] into Address $0203.
INC $0203 ; INCrement one number into $0203, making it number 3 now.
LDY #$03 ; "Load number three into Register Y." or put number 3 into Register Y.
STY $0201 ; Store number 3 into Address $0201.
INC $0201 ; INCrement, or fancy word of adding 1 [and nothing else.] into Address $0201, which now has number 2 instead of number 1.
Don't forget INX and INY, DEX, and DEY exist.
Code:
LDX #$02
INX
STX $0203
LDY #$03
INY
STY $0201
There are a lot of things I'm trying to avoid covering until later. Speed of individual instructions is one of them. INX/INY/DEX/DEY are way faster than INC/DEC, though.
Quote:
Why isn't ASCII code mentioned in the Bunnyboys...? Obviously difficult, but still... e-e;;;
NES programs would not necessarily lay out their text in ASCII order is one reason why. Another reason is that it's not necessarily guaranteed to be a function of the assembler. You can't do it in easy6502, for example.
I'm just going to start a new post for the next lesson.
tepples wrote:
DocWaluigean wrote:
Ah, so "#" and "#$" can be used. Is the binary [WAY advanced] also used like "B$"?
Binary depends on what assembler you're using. I don't think Easy 6502's assembler supports binary, but ca65 uses
% for binary
Code:
lda #$45
lda #%01000101
Negative numbers on 6502 are represented using
two's complement, which exploits the fact that addition wraps at 256. For example, -3 is represented as 256 - 3, or $FD.
Code:
lda #253
lda #$FD
lda #-3
lda #<-3 ; Some assemblers require < before all negative numbers because
; they check that all values are in 0-255 range
Add 253 to 6 and you get 259, which wraps to 3.
Decimals are a bit more complicated; you'll learn
fixed-point arithmetic sometime after you learn how to add numbers bigger than 256.
Binary as in the one for the NES.
I see about the other ones though.
Kasumi wrote:
Yes, it was a lot of info, and yes a lot of it was similar (hence feeling repeated), but that's also why I did so much.
IN? adds one.
DE? subtracts one.
T12 copies the value from register 1 to register 2.
You can't INA, you can't DEA, you can't TXY and you can't TYX.
That's all 10 instructions. That's the short version of my last post.
Quote:
So apparently the numerical system in this 6502 8-bit "integer" [numbers from 0 to 255.] is a WHEEL, instead of a road, where if you reach 255 and go one more, it will revert back to 0. [Maaaybe revert into -255??? I doubt it.
Like I said in an earlier post, it's "always an 8 bit value." Thinking of it like a wheel is fine.
Quote:
DEC $0204 ; Decrement, or subtract by one only, Address $0204. While the number contained inside is nothing, also as ZERO, it's goes backwards into the maximum number of what Address $0204 can hold. Obviously the maximum for each addresses is $FF, but in this case of 6502 engine for Easy6502, the maximum number would be $0F, resulting in light gray.
Although it's true that in easy6502 the "default" value for RAM is 0, this is NOT a guarantee. One should not assume RAM to start with a given value.
On NES, the starting value of RAM is "random". So if you did dec $0204 at the start expecting the result to be $FF, your program would likely break later when you tried to use that value.
Quote:
Stuff like transfer feels REALLY worthless. Is there a good example of using TXY and TXA stuff BESIDE "10000 score = one life" ?
Say you want to subtract 1 from the accumulator, like the assignment.
Code:
tax
dex
txa
There's a way to subtract 1 from the accumulator too (we'll get there later), but it uses more bytes. (Same number of instructions, though.) But using more byte might be better if you don't want to avoid changing the value in X. Programming is thinking about trade-offs like that.
Tokumaru covered another example that ended up using fewer bytes.
Quote:
-Why lowercase for all opcodes? I'm more fixated on capital one.
It doesn't make a difference in a lot of assemblers these days. Lowercase means you don't have to hold shift or switch capslock on and off, so I prefer it.
It's also very good that you're rereading earlier posts. There's a lot of good info in them.
Quote:
And what about directly move A / X / Y from one to X / Y / A, with the A / X / Y left as blank or zero?
I said in the last post that sometimes, the CPU can't do things in one instruction. That's how programming works. If the thing you want to do doesn't exist, you use the things that do exist to make what you want to happen actually happen. Like the example you quoted.
As far as wasting space... if you don't need the accumulator to be zero after transferring the value to X, then just don't do the load after. If you need to use more instructions to do the job, it's not wasting anything, it's just doing the job.
Code:
LDX #$02 ; "Load it up!" or put number 2 into Register X.
STX $0203 ; Store Register X [Number 2] into Address $0203.
INC $0203 ; INCrement one number into $0203, making it number 3 now.
LDY #$03 ; "Load number three into Register Y." or put number 3 into Register Y.
STY $0201 ; Store number 3 into Address $0201.
INC $0201 ; INCrement, or fancy word of adding 1 [and nothing else.] into Address $0201, which now has number 2 instead of number 1.
Don't forget INX and INY, DEX, and DEY exist.
Code:
LDX #$02
INX
STX $0203
LDY #$03
INY
STY $0201
There are a lot of things I'm trying to avoid covering until later. Speed of individual instructions is one of them. INX/INY/DEX/DEY are way faster than INC/DEC, though.
Quote:
Why isn't ASCII code mentioned in the Bunnyboys...? Obviously difficult, but still... e-e;;;
NES programs would not necessarily lay out their text in ASCII order is one reason why. Another reason is that it's not necessarily guaranteed to be a function of the assembler. You can't do it in easy6502, for example.
I'm just going to start a new post for the next lesson.
I see.. but I don't really feel too comfortable making new post; bad experiences from past with making too many threads by accidents. Unless you mean HERE for new post, then alright. I got all the time.
So it's the polar opposite of what A X and Y do...
A = Can't INC nor DEC directly. Only through Address Code.
X]
Y] = Can INC and DEC. Directly and substancely. Including INX and INY.
So disadvantages of A, X, and Y Register:
A = Cannot use INCrement nor DECrements DIRECTLY. INC and DEC only works onto Address Code.
X and Y = Cannot Transfer/"Copy-And-Paste" each other directly. ONLY through Register A.
Quote:
So disadvantages of A, X, and Y Register:
A = Cannot use INCrement nor DECrements DIRECTLY. It only works onto Address Code.
X and Y = Cannot Transfer/"Copy-And-Paste" each other directly. ONLY through Register A.
I think its better to say, "There's not an instruction to increment or decrement A". There are more ways to get the same result than just the address thing, and there's even a way to add 1 to A in a single instruction we'll learn later. (well
sometimes it's two instructions >_>, and that weirdness is precisely why I'm waiting to teach it.) Anyway, that thing is just not specifically an "increment."
And again, I realize it may seem like I'm picky on language, but the devil is truly in the details in these things.
That was a good overview of the disadvantages for now. There are more differences between the registers that will become clear some posts from now.
Quote:
I see.. but I don't really feel too comfortable making new post; bad experiences from past with making too many threads by accidents. Unless you mean HERE for new post, then alright. I got all the time.
Yes, I meant a new post in this topic. I just wanted to make it easier for you to find the new information. (So you didn't have to scroll too far down in the middle of a post for it.)
LESSON TIMEWe have talked about the "state" of the CPU before. We know that A, X and Y are part of the state. We're going to learn one more part of the CPU state now. The "Processor Status Flags".
On easy6502, they are here:
The Processor Status Register is one byte. Each "flag" is one bit. In easy6502, there is a character above each bit that corresponds to its name.
When talking about flags:
A bit that has the value 1 is usually referred to as "set".
A bit that has the value 0 is usually referred to as "clear".
So in the above image:
N is clear.
V is clear.
- is set.
B is set.
D is clear.
I is clear.
Z is clear.
C is clear.
After MOST instructions, these flags are set or cleared depending on the result of the instruction. Not all instructions affect all flags. And some of them (the ST? family in particular of the ones you've learned) don't affect any of the flags.
The easiest one to explain is 'Z'. It's the "Zero Flag". It is set when the result of the last instruction was zero. It is clear when the result of the last instruction was
anything except zero. And that's a little weird! It's 1 when the result was 0! But that's just how it is.
Step through the following code in easy6502 and watch the number below "Z" in the little box that holds the CPU state. I suppose your assigment this time is to comment what the Z flag was, after running each line.
Code:
lda #$FF
lda #$00
lda #$01
lda #$4D
lda #$00
ldx #$AB
tax
inx
dex
ldy #$FF
iny
That one should probably make perfect sense, but still, comment it with what the zero flag ends up being after each line.
And here's one that might make a little less sense, but comment it as well:
Code:
lda #$00
ldx #$FF
stx $00
sta $00
Way earlier in the topic you had mentioned you didn't like how easy6502 linked to the instruction reference so early. I'm going to link to it again now, and a lot of it will probably make more sense:
http://www.obelisk.me.uk/6502/reference.htmlNow, I want you to click LDA (an instruction you know) at the top. It explains what it does, and directly under that it explains how the processor status flags will be changed after the instruction was run. (You can ignore the stuff further down for now.)
You'll see that for the zero flag, it will be set if A is equal to zero. (So basically, if the result of the operation was equal to zero.) And indeed, that's what happens for the zero flag most of the time. (It also explains that it changes the negative flag, but it's cool if you don't understand that. We'll get to it later.)
It doesn't say that it clears the zero flag when A was not zero, but it also does this. And again, this is true for most things that affect the zero flag. They'll set it on zero, clear it on non zero.
But now scroll back up and click STA (another instruction you know). It explains that it doesn't affect the zero flag. Knowing this should help the last example make sense.
I'm showing you this for two reasons:
1. To show why people link to the documentation sometimes. It's hard to cover all the exceptions in a verbose manner.
2. To begin to teach you how to approach reading documentation, because you will eventually need to. (Especially for NES.)
I want to empower you to be able to verify if the things I'm teaching you are actually true. This is also why I wanted to get you started running 6502 code somehow. So you could see the concepts in action yourself. (In case I made a mistake or something else!)
To close this post, I will say why the flags exist. The CPU has run all the code we have written so far in order, one instruction at a time, going down. There is a family of instructions that allows you to send the CPU someplace other than one instruction down based on the "state" of one of the flags. For example if the zero flag is set, skip the next three instructions.
We'll cover some of this family of instructions next. If you have questions about how the Zero flag works, now's the time! It's the easiest one. Two of the others get more dastardly and non obvious, so fully understanding how Z gets set and cleared is an important first step before those.
Quote:
lda #<-3 ; Some assemblers require < before all negative numbers
thanks. I didn't know this. that will come in handy.
dougeff wrote:
Quote:
lda #<-3 ; Some assemblers require < before all negative numbers
thanks. I didn't know this. that will come in handy.
That was added in a later version of ca65, and I while I think the range checks are really useful in some cases, taking away the ability to represent signed data is bad collateral damage.
You can disable it with:
Code:
.feature force_range
I with this could be turned on and off, though, to allow range checking elsewhere in the file. I try to only turn it on when needed. (More ideal would be some sort of "signed" version of .byte / .word / # but this is an even more cumbersome proposal.) In some cases I'll live with the <.
Kasumi wrote:
The easiest one to explain is 'Z'. It's the "Zero Flag". It is set when the result of the last instruction was zero. It is clear when the result of the last instruction was anything except zero. And that's a little weird! It's 1 when the result was 0! But that's just how it is.
It really helps me to think of each of the processor status flags as being either TRUE or FALSE.
- TRUE is 1 (or set).
- FALSE is 0 (or clear).
That way when the Zero Flag is TRUE that means the result of the previous instruction was zero. That way is very clear, to me at least. Hope this helps you too DocWaluigean.
I generally prefer thinking about the flags as TRUE/FALSE too, except for the carry flag, which works well if interpreted as a numeric value.
unregistered wrote:
Kasumi wrote:
The easiest one to explain is 'Z'. It's the "Zero Flag". It is set when the result of the last instruction was zero. It is clear when the result of the last instruction was anything except zero. And that's a little weird! It's 1 when the result was 0! But that's just how it is.
It really helps me to think of each of the processor status flags as being either TRUE or FALSE.
- TRUE is 1 (or set).
- FALSE is 0 (or clear).
That way when the Zero Flag is TRUE that means the result of the previous instruction was zero. That way is very clear, to me at least. Hope this helps you too DocWaluigean.
Thanks for encourage! ^^
Isn't that Boolean Method?
Kasumi wrote:
Quote:
So disadvantages of A, X, and Y Register:
A = Cannot use INCrement nor DECrements DIRECTLY. It only works onto Address Code.
X and Y = Cannot Transfer/"Copy-And-Paste" each other directly. ONLY through Register A.
I think its better to say, "There's not an instruction to increment or decrement A". There are more ways to get the same result than just the address thing, and there's even a way to add 1 to A in a single instruction we'll learn later. (well
sometimes it's two instructions >_>, and that weirdness is precisely why I'm waiting to teach it.) Anyway, that thing is just not specifically an "increment."
And again, I realize it may seem like I'm picky on language, but the devil is truly in the details in these things.
That was a good overview of the disadvantages for now. There are more differences between the registers that will become clear some posts from now.
Quote:
I see.. but I don't really feel too comfortable making new post; bad experiences from past with making too many threads by accidents. Unless you mean HERE for new post, then alright. I got all the time.
Yes, I meant a new post in this topic. I just wanted to make it easier for you to find the new information. (So you didn't have to scroll too far down in the middle of a post for it.)
LESSON TIMEWe have talked about the "state" of the CPU before. We know that A, X and Y are part of the state. We're going to learn one more part of the CPU state now. The "Processor Status Flags".
On easy6502, they are here:
The Processor Status Register is one byte. Each "flag" is one bit. In easy6502, there is a character above each bit that corresponds to its name.
When talking about flags:
A bit that has the value 1 is usually referred to as "set".
A bit that has the value 0 is usually referred to as "clear".
So in the above image:
N is clear.
V is clear.
- is set.
B is set.
D is clear.
I is clear.
Z is clear.
C is clear.
After MOST instructions, these flags are set or cleared depending on the result of the instruction. Not all instructions affect all flags. And some of them (the ST? family in particular of the ones you've learned) don't affect any of the flags.
The easiest one to explain is 'Z'. It's the "Zero Flag". It is set when the result of the last instruction was zero. It is clear when the result of the last instruction was
anything except zero. And that's a little weird! It's 1 when the result was 0! But that's just how it is.
Step through the following code in easy6502 and watch the number below "Z" in the little box that holds the CPU state. I suppose your assigment this time is to comment what the Z flag was, after running each line.
Code:
lda #$FF
lda #$00
lda #$01
lda #$4D
lda #$00
ldx #$AB
tax
inx
dex
ldy #$FF
iny
That one should probably make perfect sense, but still, comment it with what the zero flag ends up being after each line.
And here's one that might make a little less sense, but comment it as well:
Code:
lda #$00
ldx #$FF
stx $00
sta $00
Way earlier in the topic you had mentioned you didn't like how easy6502 linked to the instruction reference so early. I'm going to link to it again now, and a lot of it will probably make more sense:
http://www.obelisk.me.uk/6502/reference.htmlNow, I want you to click LDA (an instruction you know) at the top. It explains what it does, and directly under that it explains how the processor status flags will be changed after the instruction was run. (You can ignore the stuff further down for now.)
You'll see that for the zero flag, it will be set if A is equal to zero. (So basically, if the result of the operation was equal to zero.) And indeed, that's what happens for the zero flag most of the time. (It also explains that it changes the negative flag, but it's cool if you don't understand that. We'll get to it later.)
It doesn't say that it clears the zero flag when A was not zero, but it also does this. And again, this is true for most things that affect the zero flag. They'll set it on zero, clear it on non zero.
But now scroll back up and click STA (another instruction you know). It explains that it doesn't affect the zero flag. Knowing this should help the last example make sense.
I'm showing you this for two reasons:
1. To show why people link to the documentation sometimes. It's hard to cover all the exceptions in a verbose manner.
2. To begin to teach you how to approach reading documentation, because you will eventually need to. (Especially for NES.)
I want to empower you to be able to verify if the things I'm teaching you are actually true. This is also why I wanted to get you started running 6502 code somehow. So you could see the concepts in action yourself. (In case I made a mistake or something else!)
To close this post, I will say why the flags exist. The CPU has run all the code we have written so far in order, one instruction at a time, going down. There is a family of instructions that allows you to send the CPU someplace other than one instruction down based on the "state" of one of the flags. For example if the zero flag is set, skip the next three instructions.
We'll cover some of this family of instructions next. If you have questions about how the Zero flag works, now's the time! It's the easiest one. Two of the others get more dastardly and non obvious, so fully understanding how Z gets set and cleared is an important first step before those.
Code:
lda #$FF ; Number 255 is stored into Register A.
;;; XXXX ;;;;
;The PSFlag of N [Number containment] is turned on. Meaning, "Excluding zero, you are storing number there, so the flag's turned on."
;;;XXXXXXX ;;;;;
;The PSFlag of N means, "You are carrying a number higher than 15 right now."
;;; ?????????????? ;;;;;
;The PSFlag of N means, "It is about to be used for further codings judging by how it looks right now, so the flag is turned on."
;---
lda #$00 ; Number 0 replaced Register A's number 255. Now number 0 is stored into Register A.
;;; The PSFlag of Z [Zero] is turned on. Meaning, "You are storing number zero in there, so the flag's turned on."
lda #$01 ; Register A is carrying number 1.
lda #$4D ; Register A is carrying HEX-number 4D.
lda #$00 ; Flag of Zero is turned on, because only zero is placed into the number.
ldx #$AB
tax ; copy and paste number 0 into Register A, replacing HEX-Number AB into number zero.
inx ; Add one into Register X.
dex ; Subtract one from Register X.
ldy #$FF ; The N Flag represent "It's about to be used in further programming."
iny ; Increase Register Y, 255, by one. As it's the limit of the number, it "rotates" back to zero.
; Register A, X, and Y: by carrying number, it means like "A = 123" "X = 123" and "Y = 123" for usages in further programmings.
; -----????????????-----
;The N flag represents the A, X, and/or Y Register's number that's about to be used in the further programming.
;The Z flag represents, "If A, X, and/or Y Register is purposefully storing number ZERO in the coding, the ZERO flag is turned on, because you are carrying number 0 in the Register A, X, and/or Y.
;------------------------------------------------
This is somewhat annoying or exhausting. TwT
Code:
lda #$00 ; LOAD, or put, number 0 into Register A.
;* The Z Flag, or ZERO Flag, is turned on because you are purposefully carrying number 0 into Register A.
ldx #$FF ; LOAD, or put, number 255, into Register X.
;* The N Flag is turned on because you are about to use the number 255 from Register X into $00.
stx $00 ; Store number 255 into Address Code $0000.
sta $00 ; Store number zero into Address Code $0000. As the Address Code $0000 contains number 255, the Register A's number 0 replaces the value inside the Address Code $0000.
; Now the Address Code $0000 is holding number 0 instead of 255.
I won't question about it if you understand COMPLETELY where I am coming from.
Are you... guessing the meaning of the N flag? "N" doesn't stand for "number containment"... after all, all values are numbers, even 0. Also, any value you load is probably going to be used for "further codings", otherwise why would you be loading them? So the CPU doesn't have any expectations regarding what you'll be doing with values in the future and doesn't have any flags for that.
"N" stands for "negative". It indicates when an operation resulted in a negative result. The 6502 uses the 2's complement notation to represent negative numbers, and in that notation, negative numbers always have the highest bit set. This means that the N flag is basically a copy of the 8th bit (bit 7) of an operstion's result.
Creating theories is part of the process of learning, but then you have to check the documentation and/or do some tests to see whether your theories make any sense. No document ever said that "N" means "number containment", so why would you go ahead with that assumption?
tokumaru wrote:
Are you... guessing the meaning of the N flag? "N" doesn't stand for "number containment"... after all, all values are numbers, even 0. Also, any value you load is probably going to be used for "further codings", otherwise why would you be loading them? So the CPU doesn't have any expectations regarding what you'll be doing with values in the future and doesn't have any flags for that.
"N" stands for "negative". It indicates when an operation resulted in a negative result. The 6502 uses the 2's complement notation to represent negative numbers, and in that notation, negative numbers always have the highest bit set. This means that the N flag is basically a copy of the 8th bit (bit 7) of an operstion's result.
Creating theories is part of the process of learning, but then you have to check the documentation and/or do some tests to see whether your theories make any sense. No document ever said that "N" means "number containment", so why would you go ahead with that assumption?
So it will be easier for me to give questions for Kasumi or anyone regarding if it's false or not, hence commenting almost every details I see.
I'm still not understanding about negative, because I haven't seen any coding regarding "LDA -#$0F" or something.
Yeah, don't worry about anything but the zero flag, that's all I covered.
This is what I'm looking for:
Code:
lda #$FF;The zero flag is clear because #$FF is not equal to zero
lda #$00;The zero flag is set because #$00 is equal to zero.
lda #$01;The zero flag is clear because #$01 is not equal to zero.
lda #$4D;etc
lda #$00
ldx #$AB
tax
inx
dex
ldy #$FF
iny
For both pieces of code. You commented when it gets set (turned on), but not when it's clear (turned off). Understanding this also happens is very important.
It's a simpler assignment, it's just trying to solidify exactly one of the processor status flags in your mind. I'm doing zero rather than the others first because they work similarly but are slightly less simple.
Kasumi wrote:
Yeah, don't worry about anything but the zero flag, that's all I covered.
This is what I'm looking for:
Code:
lda #$FF;The zero flag is clear because #$FF is not equal to zero
lda #$00;The zero flag is set because #$00 is equal to zero.
lda #$01;The zero flag is clear because #$01 is not equal to zero.
lda #$4D;etc
lda #$00
ldx #$AB
tax
inx
dex
ldy #$FF
iny
For both pieces of code. You commented when it gets set (turned on), but not when it's clear (turned off). Understanding this also happens is very important.
It's a simpler assignment, it's just trying to solidify exactly one of the processor status flags in your mind. I'm doing zero rather than the others first because they work similarly but are slightly less simple.
I understand.
[I can't say, "Is there another lesson?" because it's sounds rude.]
Could you fill out Z flag state for the rest, from "etc." down?
Hah, you can say that, I don't mind. And the answer is "Of course there's another lesson, after I see the zero flag is understood." I've started off the comments on one of the two code segments I left. I'd like to see the other lines commented in a similar way, as well as the trickier second piece of code commented in a similar way.
Everything that comes next requires true understanding of the zero flag, because what's next is seting up code that makes decisions and counts things based on its state. Even if it seems really simple, show what you've learned!
tepples wrote:
Could you fill out Z flag state for the rest, from "etc." down?
Kasumi wrote:
Hah, you can say that, I don't mind. And the answer is "Of course there's another lesson, after I see the zero flag is understood." I've started off the comments on one of the two code segments I left. I'd like to see the other lines commented in a similar way, as well as the trickier second piece of code commented in a similar way.
Everything that comes next requires true understanding of the zero flag, because what's next is seting up code that makes decisions and counts things based on its state. Even if it seems really simple, show what you've learned!
Ohhhh.. I didn't understood when you told me to do the same to what you wrote about that too until now. I thought you were giving "Overview".
Code:
da #$FF;The zero flag is clear because #$FF is not equal to zero
lda #$00;The zero flag is set because #$00 is equal to zero.
lda #$01;The zero flag is clear because #$01 is not equal to zero.
lda #$4D;etc
;----------
lda #$00 ; A == 0. The Zero Flag is "set", or on.
ldx #$AB ; A == HEX-AB. The Zero Flag is "clear", or off now.
tax; Copy and paste from Register A to X.
; X == 0
; The Zero Flag is turned on, or the Zero flag is now set. Again.
inx ; INCrement number inside X Register by 1.
; X == 1
; The Zero Flag is turned off. Or the Zero Flag is now clear...Again...
dex
;; The Zero Flag is turned on, or the Zero Flag is now set. Again!
ldy #$FF ; Y == 255 or Y == HEX-FF
iny ; Increment, or add by only one, to Register Y.
; Due to wheel-styles on numerical engine on 6502, it will always revert back to 0 on forward after 255, OR it will always revert back to 255 on backward before 0.
; Y == 0
; The Zero Flag is turned on, or the Zero Flag is now set. AGAIN!!!
Part one looks good, but part two existed for a reason.
Quote:
And here's one that might make a little less sense, but comment it as well:
Code:
lda #$00
ldx #$FF
stx $00
sta $00
Kasumi wrote:
Part one looks good, but part two existed for a reason.
Quote:
And here's one that might make a little less sense, but comment it as well:
Code:
lda #$00
ldx #$FF
stx $00
sta $00
Code:
Code:
lda #$00 ; A = 0. The Zero Flag is Set/Turned On.
ldx #$FF ; X = 255. The Zero Flag is Clear/Turned Off.
stx $00 ; Number 255 from Register X is stored into Address $0000. The Zero Flag is still Clear/Turned Off.
sta $00 ; Number 0 from Register A replaced Number 255 from Address X, and stored into Address $0000.
; For odd reason on last code, the Zero Flag isn't turn on.
DocWaluigean wrote:
; Due to wheel-styles on numerical engine on 6502, it will always revert back to 0 on forward after 255, OR it will always revert back to 255 on backward before 0.
Since there are also "wheel-styles" in our base 10 number system... what you talk about in this quote from your code section makes using numbers greater than #255 on the 6502 really easy to learn about.
Have you noticed the "wheel-style" when you are counting? Adding 1 to 09 gives you 10. The ones digit just reverted back to 0 on forward after 9. Also, "the carry" was set and so it added 1 to the tens place.
This same logic works the same way with numbers-within-bytes on the 6502. I'm sure Kasumi will expand on these ideas. Just think about this now; it will get easier with time.
Loads and transfers to A, X, or Y change the Z flag. This includes LDA, LDY, TAX, and others.
Arithmetic and logic operations (ALU ops) also change the Z flag. This includes INY, ADC, and others.
Stores do not affect the Z flag. This includes STA, STX, and STY.
unregistered wrote:
DocWaluigean wrote:
; Due to wheel-styles on numerical engine on 6502, it will always revert back to 0 on forward after 255, OR it will always revert back to 255 on backward before 0.
Since there are also "wheel-styles" in our base 10 number system... what you talk about in this quote from your code section makes using numbers greater than #255 on the 6502 really easy to learn about.
Have you noticed the "wheel-style" when you are counting? Adding 1 to 09 gives you 10. The ones digit just reverted back to 0 on forward after 9. Also, "the carry" was set and so it added 1 to the tens place.
This same logic works the same way with numbers-within-bytes on the 6502. I'm sure Kasumi will expand on these ideas. Just think about this now; it will get easier with time.
Yeah, I didn't know about that when I'm counting. XD
tepples wrote:
Loads and transfers to A, X, or Y change the Z flag. This includes LDA, LDY, TAX, and others.
Arithmetic and logic operations (ALU ops) also change the Z flag. This includes INY, ADC, and others.
Stores do not affect the Z flag. This includes STA, STX, and STY.
Oooh. So storage doesn't count.
If you're curious about which flags get flipped, see "Processor Status after use" in any
6502 reference.
Quote:
I'm sure Kasumi will expand on these ideas. Just think about this now; it will get easier with time.
Oh, man, you have no idea. I wrote a 700 word tutorial on that sort of thing to teach numbering systems, but I'll probably only keep reworking it privately for now.
A clock is actually a bit like wraparound as well. What's an hour from 12 PM? 1 PM.
Quote:
; For odd reason on last code, the Zero Flag isn't turn on.
That's why I had you do that one. Tepples wrote a brief explanation why, but there's some information about how to find out how the flags are affected in the lesson post.
The key thing to take away, not all instructions affect flags. Not all instructions affect all flags. You can (and should) always check
the documentation if you're not 100% sure how a flag will be affected by an instruction.
And again, you can ignore the stuff on that page you haven't learned, but compare what it says about how lda affects the zero flag to what it says about how sta affects the zero flag. I'll teach you how to read more parts of it when we get further.
Anyway, next comes branching. I'm skipping the other status flags for now because they give you more theory than practice. Branches gives you a toolbox you can then immediately apply when you learn of the other flags. I may or may not cover an addressing mode or two as well. It depends how long it gets when I actually write it >_>
tepples wrote:
If you're curious about which flags get flipped, see "Processor Status after use" in any
6502 reference.
Kasumi wrote:
Quote:
I'm sure Kasumi will expand on these ideas. Just think about this now; it will get easier with time.
Oh, man, you have no idea. I wrote a 700 word tutorial on that sort of thing to teach numbering systems, but I'll probably only keep reworking it privately for now.
A clock is actually a bit like wraparound as well. What's an hour from 12 PM? 1 PM.
Quote:
; For odd reason on last code, the Zero Flag isn't turn on.
That's why I had you do that one. Tepples wrote a brief explanation why, but there's some information about how to find out how the flags are affected in the lesson post.
The key thing to take away, not all instructions affect flags. Not all instructions affect all flags. You can (and should) always check
the documentation if you're not 100% sure how a flag will be affected by an instruction.
And again, you can ignore the stuff on that page you haven't learned, but compare what it says about how lda affects the zero flag to what it says about how sta affects the zero flag. I'll teach you how to read more parts of it when we get further.
Anyway, next comes branching. I'm skipping the other status flags for now because they give you more theory than practice. Branches gives you a toolbox you can then immediately apply when you learn of the other flags. I may or may not cover an addressing mode or two as well. It depends how long it gets when I actually write it >_>
Do you notice how hard it is for me to understand very well or accurate on stuff like 6502 Reference stuff? I mean, I have absolutely no qualifications to complain since this is exactly what I wanted; to know what is the entire 6502 Assembly Opcodes used to make the best games ever on NES / [SNES???????????] ... But the explanation is beyond horrible for people who has one of tough times in understanding languages, english, autism, etc. when comparing two and two together. I get that stuff like this IS hard, but the one harder thing is the one without sense of teachings for all. If Archimedes never existed, we wouldn't be understanding how to multiply, divide, and such! [I feel it's actually Nicomachus. But you get where I come from?]
Or maybe......again... I didn't read the entire thing first...
But your right that it's more of a clock than a wheel.
DocWaluigean wrote:
unregistered wrote:
DocWaluigean wrote:
; Due to wheel-styles on numerical engine on 6502, it will always revert back to 0 on forward after 255, OR it will always revert back to 255 on backward before 0.
Since there are also "wheel-styles" in our base 10 number system... what you talk about in this quote from your code section makes using numbers greater than #255 on the 6502 really easy to learn about.
Have you noticed the "wheel-style" when you are counting? Adding 1 to 09 gives you 10. The ones digit just reverted back to 0 on forward after 9. Also, "the carry" was set and so it added 1 to the tens place.
This same logic works the same way with numbers-within-bytes on the 6502. I'm sure Kasumi will expand on these ideas. Just think about this now; it will get easier with time.
Yeah, I didn't know about that when I'm counting. XD
Haha
Yes, I didn't know about that either before tokumaru or Kasumi explained that to me. Glad you understand that now!
"Learning" is so much fun, for me at least, when I'm actually learning.
unregistered wrote:
Haha
Yes, I didn't know about that either before tokumaru or Kasumi explained that to me. Glad you understand that now!
"Learning" is so much fun, for me at least, when I'm actually learning.
True.. but it's not as fun for people who has hard times comprehending.
When people prefer to watch cartoons, movies, comic, they learn or think more from it than from reading books without pictures. Just words.
So.. I keep having hard time what is real "learning" for me at the moment.
DocWaluigean wrote:
unregistered wrote:
Haha
Yes, I didn't know about that either before tokumaru or Kasumi explained that to me. Glad you understand that now!
"Learning" is so much fun, for me at least, when I'm actually learning.
True.. but it's not as fun for people who has hard times comprehending.
When people prefer to watch cartoons, movies, comic, they learn or think more from it than from reading books without pictures. Just words.
So.. I keep having hard time what is real "learning" for me at the moment.
Never give up. Keep applying yourself. Your brain will grow.
Mine surely did... there were times where my sister helped me understand what I was trying to think about. tokumaru replied something like, "Maybe your sister should program the game then.
". I laughed so much
just never give up and keep applying yourself.
unregistered wrote:
DocWaluigean wrote:
unregistered wrote:
Haha
Yes, I didn't know about that either before tokumaru or Kasumi explained that to me. Glad you understand that now!
"Learning" is so much fun, for me at least, when I'm actually learning.
True.. but it's not as fun for people who has hard times comprehending.
When people prefer to watch cartoons, movies, comic, they learn or think more from it than from reading books without pictures. Just words.
So.. I keep having hard time what is real "learning" for me at the moment.
Never give up. Keep applying yourself. Your brain will grow.
Mine surely did... there were times where my sister helped me understand what I was trying to think about. tokumaru replied something like, "Maybe your sister should program the game then.
". I laughed so much
just never give up and keep applying yourself.
Thanks... Your very lucky to have someone who tries to help you much. I tried much to convince my Dad to help me, but he didn't want to progress because, "it's an old code." this and, "It doesn't help with your career." that.
I'll be here waiting for Kasumi or others.
--
I'm re-reading Week 3 Nerdy Nights, and more often, I'm started to feel insulted on how unorganized and how unprofessional it starting to look for me, and this is used as the best of the best sources for beginner's lectures. [Sorry?]
"It doesn't help with your career."
Haunted: Halloween '85 and The Curse of Possum Hollow beg to differ.
tepples wrote:
"It doesn't help with your career."
Haunted: Halloween '85 and The Curse of Possum Hollow beg to differ.
The shock or surprised give me excuse to use two questions:
1:
I COULD LITERALLY SUBMIT AN NES GAME TO STEAM AS MY JOB, IN A HYBRID LOVE OF UNDERTALE AND SHOVEL KNIGHT!?!?!!?!?!2:
SO ALL OF ALL [At least 99%] 6502 ASSEMBLY CODE I AM LEARNING FOR NES ALSO WORKS FOR SNES!?! I COULD RE-MAKE SUPER MARIO WORLD J.U.M.P MOD, OR I COULD LITERALLY MAKE A 100% HIGH QUALITY SNES GAME FROM SCRATCH FROM JUST PORTING NES LESSONS TO SNES ENTIRELY?!!?!?
Yes, there are emulators that you can license to port an NES game to Itch, Steam, or possibly even consoles.
Yes, both CPUs in the Super NES chipset are 6502 derivatives. The main CPU (Ricoh 5A22) contains a 65816 core licensed from WDC, and the audio CPU (Sony SPC700) is 98 percent a clone of the 65C02. So yes, your skills would transfer into making an original Super NES game.
This is horribly, HORRIBLY off-topic and should be its own thread. Period. But I'll answer anyway:
A1. NES games are to be used on NES emulators or the NES console itself. For a NES game to work on Steam, you would have to package your game with an integrated NES emulator that works on the PC, and try to release that on Steam. This has complications, mainly stemming from licensing costs. A better person to ask would be rainwarrior, who did this with Lizard (although I think Lizard actually got "ported" to PC directly, I can't remember. Brad, can you clarify? Tepples probably knows something about this as well.
As for the general idea of "can NES programming help you get a job?" -- the answer is "maybe". Understanding *how* a video game system works, and *how* to program (and design) a video game can get you a job if you can find a place that wants to hire such a person. It's complicated. In general, I would not advise a person to go into video game development/programming as a career. The industry involves very long hours, crappy pay, and a lot of stress. You also need to think about something: changing a hobby into a job/career changes the purpose. This is why I intentionally have never gone into the video game industry for work. I prefer to keep doing this kind of thing for fun, not to put food on the table.
A2. Yes, you can run 6502 code on the SNES. The SNES's 65816 CPU is backwards-compatible with the 6502, and the 65816 includes a 65C02 emulation mode (sec / xce is all it takes). It introduces a lot of new technology at the CPU level, though (hundreds of more instructions, for example). But the big one is that you have 16-bit registers, not 8-bit. The SNES is an EXTREMELY different system to develop on, though -- a lot of things you will learn about the NES design/etc. won't apply to the SNES (you have a lot more control on the SNES, and as such, it's more complex).
But yes, you could make a NES game, and then "port" it to SNES while learning its architecture. But, respectfully, you are no where even close to being able to do that. Not even close. You may be one day, but not now.
I strongly recommend you stay focused on what Kasumi is teaching you. Learn 6502. Learn the NES. Don't think about the SNES; worry about learning that once you have an actual NES game. Don't think about steam; worry about learning the NES.
tepples wrote:
Yes, there are emulators that you can license to port an NES game to Steam or possibly even consoles.
Yes, both CPUs in the Super NES CPUs are 6502 derivatives. The main CPU (Ricoh 5A22) contains a 65816 core licensed from WDC, and the audio CPU (Sony SPC700) is 98 percent a clone of the 65C02.
Jesus Christ...! There's waay more things than I thought...!
[Sorry for poor reply. Like I said, I don't want to be another people who doesn't pay attention.]
koitsu wrote:
This is horribly, HORRIBLY off-topic and should be its own thread. Period. But I'll answer anyway:
A1. NES games are to be used on NES emulators or the NES console itself. For a NES game to work on Steam, you would have to package your game with an integrated NES emulator that works on the PC, and try to release that on Steam. This has complications, mainly stemming from licensing costs. A better person to ask would be rainwarrior, who did this with Lizard (although I think Lizard actually got "ported" to PC directly, I can't remember. Brad, can you clarify? Tepples probably knows something about this as well.
As for the general idea of "can NES programming help you get a job?" -- the answer is "maybe". Understanding *how* a video game system works, and *how* to program (and design) a video game can get you a job if you can find a place that wants to hire such a person. It's complicated. In general, I would not advise a person to go into video game development/programming as a career. The industry involves very long hours, crappy pay, and a lot of stress. You also need to think about something: changing a hobby into a job/career changes the purpose. This is why I intentionally have never gone into the video game industry for work. I prefer to keep doing this kind of thing for fun, not to put food on the table.
A2. Yes, you can run 6502 code on the SNES. The SNES's 65816 CPU is backwards-compatible with the 6502, and the 65816 includes a 65C02 emulation mode (sec / xce is all it takes). It introduces a lot of new technology at the CPU level, though (hundreds of more instructions, for example). But the big one is that you have 16-bit registers, not 8-bit. The SNES is an EXTREMELY different system to develop on, though -- a lot of things you will learn about the NES design/etc. won't apply to the SNES (you have a lot more control on the SNES, and as such, it's more complex).
But yes, you could make a NES game, and then "port" it to SNES while learning its architecture. But, respectfully, you are no where even close to being able to do that. Not even close. You may be one day, but not now.
I strongly recommend you stay focused on what Kasumi is teaching you. Learn 6502. Learn the NES. Don't think about the SNES; worry about learning that once you have an actual NES game. Don't think about steam; worry about learning the NES.
Very... thick skin reply to me? But I understand. I'm still waiting for her though.
Yes, I'm known for being brash/to the point. :-)
koitsu wrote:
Yes, I'm known for being brash/to the point.
So you sound "passive-aggressive" on purpose?
On one point, it's cool to act like those.
But on other point, it kind of.. potentially pushes away the people whose literally serious with wanting to learn, but very shy to try to speak because of personal stories they have that only they know. o-o
Sorry, but letting ya know in some point?
DocWaluigean wrote:
Thanks... Your very lucky to have someone who tries to help you much. I tried much to convince my Dad to help me, but he didn't want to progress because, "it's an old code." this and, "It doesn't help with your career." that.
I'll be here waiting for Kasumi or others.
You're welcome.
Actually, I am very blessed. I, not this forum, also recommend you to bring personal problems to God in prayer and let Him worry about them. That has given me so much peace!
I don't want to change your thread's subject. Perhaps, you could reply to my post here, if you intend to, in a PM.
unregistered wrote:
DocWaluigean wrote:
Thanks... Your very lucky to have someone who tries to help you much. I tried much to convince my Dad to help me, but he didn't want to progress because, "it's an old code." this and, "It doesn't help with your career." that.
I'll be here waiting for Kasumi or others.
You're welcome.
Actually, I am very blessed. I, not this forum, also recommend you to bring personal problems to God in prayer and let Him worry about them. That has given me so much peace!
I don't want to change your thread's subject. Perhaps, you could reply to my post here, if you intend to, in a PM.
That reminded me of an old friend who I used to love the most, but he disappeared completely. Except he loves My Little Pony, and he would love to make NES / SNES games in Panel De Pon in Pony styles. Before he left, I tried to teach him how to NES by trying to make learning fun, but all of a sudden, he disappeared completely...
Hopefully one day, he and I would make a cool NES programs when he return...
DocWaluigean wrote:
an old friend who I used to love the most, but he disappeared completely. Except he loves My Little Pony, and he would love to make NES / SNES games in Panel De Pon in Pony styles. Before he left, I tried to teach him how to NES by trying to make learning fun, but all of a sudden, he disappeared completely...
I'm sorry.
DocWaluigean wrote:
Hopefully one day, he and I would make a cool NES programs when he return...
That would be great!
Just make sure to never give up and keep applying yourself.
unregistered wrote:
DocWaluigean wrote:
an old friend who I used to love the most, but he disappeared completely. Except he loves My Little Pony, and he would love to make NES / SNES games in Panel De Pon in Pony styles. Before he left, I tried to teach him how to NES by trying to make learning fun, but all of a sudden, he disappeared completely...
I'm sorry.
DocWaluigean wrote:
Hopefully one day, he and I would make a cool NES programs when he return...
That would be great!
Just make sure to never give up and keep applying yourself.
It's alright. Thanks for encouragements.
Now if Kasumi is ready...
DocWaluigean wrote:
So you sound "passive-aggressive" on purpose?
Being brash means being curt, stern, up front, not "beating around the bush", or being brutally honest (i.e. do not "water things down"). This can sometimes be considered rude, yes, though I try not to be too much of that these days.
Passive-aggressive is very different. PA people are often unwilling to compromise or act stubborn (the word "act" here is important). For example, if someone asked a PA person "are you annoyed?" they'd respond "not really", even though they were actually fuming. Another example of PA behaviour would be to do a task *intentionally* with as little effort/capability as possible. During a disagreement, PA folks tend to feign innocence and try to make the other person feel guilty for however they're feeling. And as a final example, a PA person might *intentionally* make a joke to upset/disparage someone (i.e. that was their goal, not by accident), but then when questioned about it, say something like "I was being sarcastic, sheesh".
I think every person has done some form of PA behaviour throughout their life (sometimes it's all you can do to deal with a situation), but people who are PA tend to do this regularly/constantly.
I wasn't being passive-aggressive, I was answering your questions honestly (and they're great questions!) while simultaneously advising (respectfully) that you stay focused on what Kasumi is teaching you. So yes, I sounded stern, but not passive-aggressive. You're doing a really good job. I actually look forward to reading this thread every day!
koitsu wrote:
DocWaluigean wrote:
So you sound "passive-aggressive" on purpose?
Being brash means being curt, stern, up front, not "beating around the bush", or being brutally honest (i.e. do not "water things down"). This can sometimes be considered rude, yes, though I try not to be too much of that these days.
Passive-aggressive is very different. PA people are often unwilling to compromise or act stubborn (the word "act" here is important). For example, if someone asked a PA person "are you annoyed?" they'd respond "not really", even though they were actually fuming. Another example of PA behaviour would be to do a task *intentionally* with as little effort/capability as possible. During a disagreement, PA folks tend to feign innocence and try to make the other person feel guilty for however they're feeling. And as a final example, a PA person might *intentionally* make a joke to upset/disparage someone (i.e. that was their goal, not by accident), but then when questioned about it, say something like "I was being sarcastic, sheesh".
I think every person has done some form of PA behaviour throughout their life (sometimes it's all you can do to deal with a situation), but people who are PA tend to do this regularly/constantly.
I wasn't being passive-aggressive, I was answering your questions honestly (and they're great questions!) while simultaneously advising (respectfully) that you stay focused on what Kasumi is teaching you. So yes, I sounded stern, but not passive-aggressive. You're doing a really good job. I actually look forward to reading this thread every day!
Oooooooooooooooh! I get it. For a second each by each, I thought I would've made worse impressions where... I'm no longer welcome.
But thanks about good job! It's frustrating for me to grasp every knowledge, but I'm glad people like you didn't give up on me, especially the, "I want to make NES tutorial." band-wagon where I need to understand first.
koitsu wrote:
A better person to ask would be rainwarrior, who did this with Lizard (although I think Lizard actually got "ported" to PC directly, I can't remember. Brad, can you clarify? Tepples probably knows something about this as well.
I'd say it'd be better to ask Gradual, who wrote
GGVM specifically to package NES games for Steam/etc. release, and then used it to release two of his NES games on Steam.
Lizard is running native code on Steam, not an emulation. If you really want to get down to it, Lizard is a PC game that got ported to NES.
Neither version is emulated. (I believe HH85 is also native on PC, but HH86 is an emulator package, but my memory might be incorrect.)
Correct. Haunted: Halloween '85 is a native port by a different developer, which explains its lack of bugs in jumping from a downhill. But the sequel is emulated.
Oh wow, this thread got a lot of replies.
Quote:
Do you notice how hard it is for me to understand very well or accurate on stuff like 6502 Reference stuff?
I do, but that's why I gave very specific steps on how to read it in the lesson post with how to see what I wanted you to see from it. Were the instructions not specific enough? If not, what part did you get stuck on?
I know you don't like the documentation, but eventually you will
have to learn to read it. It is something that
cannot be avoided to be successful at this. I'm trying to teach it to you a step at a time, so please, if the given step isn't clear tell me how it wasn't.
I actually looked into the SNES recently and it really keeps one on one's toes.
Quote:
Now if Kasumi is ready...
Here's the lesson! Even when I say they're coming, I wouldn't necessarily wait around for it. There are likely to be higher priority things for me that keep me from getting to this even if I seem active in short bursts.
Also understand they can be time consuming to put together! Even though I'm piggybacking off easy6502's way to run code, I'm not copying and pasting information from other sources. This is brand new content. Not trying to guilt you, but I have to write it, then spend time making sure there aren't technical errors that will send you down the wrong path.
BranchingBut first, one more part about the 6502's state.
The PC is the Program Counter. It keeps track of the address of the next instruction the CPU will execute. Previously when we used the word "address" it was referring specifically to RAM addresses. However each byte of your code has an address too. Step through this (very simple) code and watch the Program Counter in easy6502.
Code:
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
You'll notice that it goes up by two every time. this is because lda #$00 is two bytes. One byte for an LDA opcode. One byte for the number to load. Now step through this (very simple) code and watch the Program Counter again.
Code:
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
Here, it goes up by three each time. One byte for an LDA opcode. Two bytes for the address.
While writing and thinking about 6502 code, you basically never give any thought to the Program Counter. (Or at least, I don't!) It helps the CPU, but not you as the programmer that much. Unlike A, X and Y where you can change and then use the contents, and unlike the flags which are used for the decision making, the Program Counter is basically not interactive. I teach you about it now, so that you can better track the branching examples. Also, having learned it, you now know more than half of 6502 CPU's state!
In easy6502, your first instruction is put at the address $0600. This is also where easy6502 starts executing from. Everything we have done until now starts at the top of our code ($0600) and then runs each instruction one line at a time going down. There are a few families of instructions that let you go someplace other than the instruction immediately below. The family this post introduces is the "branch" family. These are instructions that will either allow the CPU to go to the next instruction below OR go to a different address in the code specified by the branch. Which happens depends on the "condition" associated with that branch.
BEQ/BNE are the only two branch instructions we can cover right now, but the others are very similar. (Sort of like how TAY, TYA, TAX and TXA were all very similar.)
BEQ is Branch on EQual (to zero). It will go ("branch") to the address specified after the branch if the zero flag is set. Otherwise, it will go to the next instruction like we've gotten used to happening. (To the very technically minded reading this: Yes, I realize part of this explanation is not-quite-true. But to me it makes more sense to introduce the "exception" when a bit more knowledge is gained.)
Here is a simple example:
Code:
restart:
lda #$00;This sets the zero flag
beq restart
lda #$FF
"restart:" in this program is a "label". A label is created by typing a name, followed by a colon ( : ) in most assemblers. Then that name becomes (roughly) equivalent to the address of whichever byte follows it. Usually an instruction. Labels don't take up space in the finished program, they just help you keep you track of things (rather than memorizing which addresses various parts of your code begin at.)
To be as safe as possible in as many things that use labels as there are, labels should only contain underscores ( _ ), letters (A-Z), and numbers (0-9). But they also shouldn't START with a number. (skip9: is okay, 9skip: may not be.)
In the program above, because easy6502's first instruction gets the address $0600, and because a label is not an instruction, the "restart" label becomes (roughly) equivalent to the address $0600. That is, it becomes a name for the address where the first instruction is.
Now step through the code above and watch the Program Counter. It will start at $0600. (the address for lda #$00). Then it will go to $0602 (the address for beq restart). But if you step again, something new happens! Rather than get higher, it goes back to $0600! Keep stepping and it will alternate between $0600 and $0602! The lda #$FF will never be reached or executed by the CPU.
The 6502 does things for very simple reasons.
"Why did you set the zero flag, 6502?"
"Because the result was zero."
"Why did you branch here, 6502?"
"Because the zero flag was set."
The above example sets the zero flag by loading zero, then follows it with a branch that triggers if the zero flag is set. Because the zero flag is set, it goes to the address specified, effectively restarting the program. Let's modify that example slightly.
Code:
restart:
lda #$80;This clears the zero flag
beq restart
lda #$FF
Step through that one. The PC starts at $0600 (lda #$80) like before. It goes to $0602 (beq restart) like before. But stepping again DOES continue to go up. It goes to $0604 (lda #$FF). This time, the lda #$FF is reached.
And again, the 6502 does things for very simple reasons.
"Why did you clear the zero flag, 6502?"
"Because the result was not zero."
"Why didn't you branch here, 6502?"
"Because the zero flag wasn't set."
IF the zero flag is set, BEQ will make the CPU go to the address specified by the label that follows the BEQ instruction.
IF the zero flag is clear, BEQ will make the CPU go to the next instruction.
BNE is Branch if Not Equal (to zero). And it branches if the zero flag is clear. Let's try it in the example code, in place of BEQ.
Code:
restart:
lda #$00;This sets the zero flag
bne restart
lda #$FF
This does NOT branch, and the lda #$FF IS reached because bne branches when the zero flag is clear, and beq branches when the zero flag is set.
Code:
restart:
lda #$80;This clears the zero flag
bne restart
lda #$FF
This DOES branch, and the lda #$FF is NOT reached.
One more note: You can branch forward.
Code:
lda #$FF;The zero flag is clear
bne skip;Because the zero flag is clear, we branch to the skip label
lda #$04;This is never executed
skip:
Your assignment is to comment each branch with whether or not it will branch, and why. Also mark any code the CPU will never execute (get to).
Code:
restart:
ldx #$00
inx
beq restart
dex
bne restart
beq skip
lda #$00
beq restart
skip:
Code:
restart:
ldy #$04
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
If this seems simple, it is. But if there's something that's not clear, please ask. Also, hah, I'm not doing the addressing modes. This got long.
But actually, I'll end with this. You technically have all the information you need to write a program that adds two numbers. (Granted, there's a way better way to do it with things you do not yet know!) The last example (with all the dey instructions) is a part of the key. Do you notice any correspondence between the value Y starts with and how it ends up branching? Count some things!
And now, think about how you might write a program that adds the number in X and Y together, and stores the result in $00. Assume the values you'll be adding will be 1, 2, 3, or 4. So before your code would be
Code:
ldx #$??
ldy #$??
;Your code here
Where each ?? could be any of those 4 values. Your program would store the added result in $00. So if your program was given:
Code:
ldx #$03
ldy #$01
;Your code here
After "Your code here" runs, $04 would be held by ram location $00.
The adding numbers it not a
required assignment to complete. It's actually pretty difficult. But I do want you to give it some serious thought. Reason about it. You do know all the tools needed complete the task. Even if you don't get it, write out some things you thought about or tried.
(And again, for the technically minded reading, yes, I realize some ways this might be solved and it's why I'm limiting the input to 1, 2, 3 and 4 and leaving 0 out of the picture so as not to make the code super tedious to write even for the "larger" solutions.)
Edit: Oh yeah. And I guess next up will be discussion about the add numbers exercise. But also those addressing modes. One you learn the new addressing modes, we can return to your face code and make it way shorter.
Kasumi wrote:
Oh wow, this thread got a lot of replies.
Quote:
Do you notice how hard it is for me to understand very well or accurate on stuff like 6502 Reference stuff?
I do, but that's why I gave very specific steps on how to read it in the lesson post with how to see what I wanted you to see from it. Were the instructions not specific enough? If not, what part did you get stuck on?
I know you don't like the documentation, but eventually you will
have to learn to read it. It is something that
cannot be avoided to be successful at this. I'm trying to teach it to you a step at a time, so please, if the given step isn't clear tell me how it wasn't.
I actually looked into the SNES recently and it really keeps one on one's toes.
Quote:
Now if Kasumi is ready...
Here's the lesson! Even when I say they're coming, I wouldn't necessarily wait around for it. There are likely to be higher priority things for me that keep me from getting to this even if I seem active in short bursts.
Also understand they can be time consuming to put together! Even though I'm piggybacking off easy6502's way to run code, I'm not copying and pasting information from other sources. This is brand new content. Not trying to guilt you, but I have to write it, then spend time making sure there aren't technical errors that will send you down the wrong path.
BranchingBut first, one more part about the 6502's state.
The PC is the Program Counter. It keeps track of the address of the next instruction the CPU will execute. Previously when we used the word "address" it was referring specifically to RAM addresses. However each byte of your code has an address too. Step through this (very simple) code and watch the Program Counter in easy6502.
Code:
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
You'll notice that it goes up by two every time. this is because lda #$00 is two bytes. One byte for an LDA opcode. One byte for the number to load. Now step through this (very simple) code and watch the Program Counter again.
Code:
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
Here, it goes up by three each time. One byte for an LDA opcode. Two bytes for the address.
While writing and thinking about 6502 code, you basically never give any thought to the Program Counter. (Or at least, I don't!) It helps the CPU, but not you as the programmer that much. Unlike A, X and Y where you can change and then use the contents, and unlike the flags which are used for the decision making, the Program Counter is basically not interactive. I teach you about it now, so that you can better track the branching examples. Also, having learned it, you now know more than half of 6502 CPU's state!
In easy6502, your first instruction is put at the address $0600. This is also where easy6502 starts executing from. Everything we have done until now starts at the top of our code ($0600) and then runs each instruction one line at a time going down. There are a few families of instructions that let you go someplace other than the instruction immediately below. The family this post introduces is the "branch" family. These are instructions that will either allow the CPU to go to the next instruction below OR go to a different address in the code specified by the branch. Which happens depends on the "condition" associated with that branch.
BEQ/BNE are the only two branch instructions we can cover right now, but the others are very similar. (Sort of like how TAY, TYA, TAX and TXA were all very similar.)
BEQ is Branch on EQual (to zero). It will go ("branch") to the address specified after the branch if the zero flag is set. Otherwise, it will go to the next instruction like we've gotten used to happening. (To the very technically minded reading this: Yes, I realize part of this explanation is not-quite-true. But to me it makes more sense to introduce the "exception" when a bit more knowledge is gained.)
Here is a simple example:
Code:
restart:
lda #$00;This sets the zero flag
beq restart
lda #$FF
"restart:" in this program is a "label". A label is created by typing a name, followed by a colon ( : ) in most assemblers. Then that name becomes (roughly) equivalent to the address of whichever byte follows it. Usually an instruction. Labels don't take up space in the finished program, they just help you keep you track of things (rather than memorizing which addresses various parts of your code begin at.)
To be as safe as possible in as many things that use labels as there are, labels should only contain underscores ( _ ), letters (A-Z), and numbers (0-9). But they also shouldn't START with a number. (skip9: is okay, 9skip: may not be.)
In the program above, because easy6502's first instruction gets the address $0600, and because a label is not an instruction, the "restart" label becomes (roughly) equivalent to the address $0600. That is, it becomes a name for the address where the first instruction is.
Now step through the code above and watch the Program Counter. It will start at $0600. (the address for lda #$00). Then it will go to $0602 (the address for beq restart). But if you step again, something new happens! Rather than get higher, it goes back to $0600! Keep stepping and it will alternate between $0600 and $0602! The lda #$FF will never be reached or executed by the CPU.
The 6502 does things for very simple reasons.
"Why did you set the zero flag, 6502?"
"Because the result was zero."
"Why did you branch here, 6502?"
"Because the zero flag was set."
The above example sets the zero flag by loading zero, then follows it with a branch that triggers if the zero flag is set. Because the zero flag is set, it goes to the address specified, effectively restarting the program. Let's modify that example slightly.
Code:
restart:
lda #$80;This clears the zero flag
beq restart
lda #$FF
Step through that one. The PC starts at $0600 (lda #$80) like before. It goes to $0602 (beq restart) like before. But stepping again DOES continue to go up. It goes to $0604 (lda #$FF). This time, the lda #$FF is reached.
And again, the 6502 does things for very simple reasons.
"Why did you clear the zero flag, 6502?"
"Because the result was not zero."
"Why didn't you branch here, 6502?"
"Because the zero flag wasn't set."
IF the zero flag is set, BEQ will make the CPU go to the address specified by the label that follows the BEQ instruction.
IF the zero flag is clear, BEQ will make the CPU go to the next instruction.
BNE is Branch if Not Equal (to zero). And it branches if the zero flag is clear. Let's try it in the example code, in place of BEQ.
Code:
restart:
lda #$00;This sets the zero flag
bne restart
lda #$FF
This does NOT branch, and the lda #$FF IS reached because bne branches when the zero flag is clear, and beq branches when the zero flag is set.
Code:
restart:
lda #$80;This clears the zero flag
bne restart
lda #$FF
This DOES branch, and the lda #$FF is NOT reached.
One more note: You can branch forward.
Code:
lda #$FF;The zero flag is clear
bne skip;Because the zero flag is clear, we branch to the skip label
lda #$04;This is never executed
skip:
Your assignment is to comment each branch with whether or not it will branch, and why. Also mark any code the CPU will never execute (get to).
Code:
restart:
ldx #$00
inx
beq restart
dex
bne restart
beq skip
lda #$00
beq restart
skip:
Code:
restart:
ldy #$04
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
If this seems simple, it is. But if there's something that's not clear, please ask. Also, hah, I'm not doing the addressing modes. This got long.
But actually, I'll end with this. You technically have all the information you need to write a program that adds two numbers. (Granted, there's a way better way to do it with things you do not yet know!) The last example (with all the dey instructions) is a part of the key. Do you notice any correspondence between the value Y starts with and how it ends up branching? Count some things!
And now, think about how you might write a program that adds the number in X and Y together, and stores the result in $00. Assume the values you'll be adding will be 1, 2, 3, or 4. So before your code would be
Code:
ldx #$??
ldy #$??
;Your code here
Where each ?? could be any of those 4 values. Your program would store the added result in $00. So if your program was given:
Code:
ldx #$03
ldy #$01
;Your code here
After "Your code here" runs, $04 would be held by ram location $00.
The adding numbers it not a
required assignment to complete. It's actually pretty difficult. But I do want you to give it some serious thought. Reason about it. You do know all the tools needed complete the task. Even if you don't get it, write out some things you thought about or tried.
(And again, for the technically minded reading, yes, I realize some ways this might be solved and it's why I'm limiting the input to 1, 2, 3 and 4 and leaving 0 out of the picture so as not to make the code super tedious to write even for the "larger" solutions.)
Edit: Oh yeah. And I guess next up will be discussion about the add numbers exercise. But also those addressing modes. One you learn the new addressing modes, we can return to your face code and make it way shorter.
THIS feels like it's going to be an overwhelming problem because I feel very lazy to read or demotivated to try to listen as it looks complex for me. Possibly one of first to admit something bad about it.
I'm going to read unthinkably so maybe when I read it again, I'll understand again.
---
So branching has NOTHING to do with peeling off the bark off the wood branch stick.
Part of me say, "Who cares!? I just want to play and make my own video games!!!" about counting each by each programs.
I'm feeling the PC, Program Counter, is actually "What line of code are you on now."
You'll notice that it goes up by two every time. this is because lda #$00 is two bytes. One byte for an LDA opcode. One byte for the number to load.That starting to actually make no sense. I am not sure how High-byte and Low-byte works well, but byte for LDA code? Okay, that make sense because opcode is inside the coding. But another for number to load? Even though it's already been used for LDA code?
Here, it goes up by three each time. One byte for an LDA opcode. Two bytes for the address.Doesn't make sense more. Two bytes? Is it the High-Byte and Low-Byte? Or is it the "$0245 = $02 and $45" that's reason why it's two bytes?
Part of me want to skip EVERYTHING. Maybe this is the peak of concentration of learning-love I'm feeling, and I don't feel care at the moment. It happens with every kids in school. Maybe I'm starting to realize why for 1 week, we had to learn the exact same thing over and over again.
So the label is the same thing as DEF / DIM opcode on BASIC language, right?
Understand, because if the number is first, the coding will see WHY it's number. Maybe it could be Address, HEX, Immediate Number, etc. With words in front, it will explode with errors.
I have no idea why I can't read enough to care atm. Maybe today isn't my good day to force myself to learn.
Now step through the code above and watch the Program Counter. It will start at $0600. (the address for lda #$00). Then it will go to $0602 (the address for beq restart). But if you step again, something new happens! Rather than get higher, it goes back to $0600! Keep stepping and it will alternate between $0600 and $0602! The lda #$FF will never be reached or executed by the CPU.So it IS "The Address you are on now!" Is it?
The 6502 does things for very simple reasons.
"Why did you set the zero flag, 6502?"
"Because the result was zero."
"Why did you branch here, 6502?"
"Because the zero flag was set."I want to make sarcastic or Bart Simpson remarks about it.
Again, my mind is not interested to read much. I don't know why.
------
So sorry about it. Because at least I'm showing what I think about it instead of simply, "I don't know. I can't read." cliche many beginners faced in NESDev years ago.
It's one of those days that I want to learn differently.
I'm starting to sympathize for people in school who suffer similar fate as I did.
Quote:
I feel very lazy to read or demotivated to try to listen as it looks complex for me.
It only gets more complex. I want to be motivating, but that's the reality of it.
Quote:
Part of me say, "Who cares!? I just want to play and make my own video games!!!" about counting each by each programs.
Conditionals (branching) are literally the thing that gives interactivity to games. For example, the face code had no conditionals, so it could only ever draw one thing.
Conditionals are what make the character only move IF a button is pressed. Die IF you fall too low. Stomp a goomba IF Mario is falling and IF Mario is colliding with the goomba.
Quote:
But another for number to load? Even though it's already been used for LDA code?
Hm. Let's reason about this. Suppose it was only one byte. You can load 256 values into A. So if each instruction were only one byte, the only thing the CPU could do is load every value into A. There could not be any other instructions.
Reasoning further, there are 65536 possible addresses to load from. So similarly, if you wanted to load from all the addresses with only two bytes, that's all you could do.
The mnemonic (three letter code, like LDA) groups multiple opcodes to make it easier on the programmer. The different opcodes specify the task as well as the METHOD of the task to the CPU. (Also known as the addressing mode.)
lda #$00 and lda $0200 both copy a value into A. But HOW they get the value differs.
LDA #$?? is the "immediate" addressing mode. $A9 is LDA immediate, but you still need another byte so you can load any of the 256 values a byte can hold.
lda $???? is the absolute addressing mode. $AD is LDA absolute, but you still need two more bytes so you can load from any of the 65536 addresses.
So
$A9 $FF = lda #$FF
$A9 $00 = lda #$00
$AD $00 $00 = lda $0000
You can see how long each version of each instruction will be in the documentation:
http://www.obelisk.me.uk/6502/reference.html#LDAIt lists the addressing modes, the opcode (the byte the CPU reads to determine what to do), bytes (which is how many bytes the instruction is total. Including the opcode for the byte) and cycles (which is how long it takes to complete, in a somewhat abstract measurement.)
Quote:
Two bytes? Is it the High-Byte and Low-Byte? Or is it the "$0245 = $02 and $45" that's reason why it's two bytes?
It is indeed the high byte and low byte of the address. $0200 = $02 and $00, yes, that's the reason it's two bytes. You can't represent all addresses with one byte. That said, the order is different than you might expect, but it only matters for something that would be covered way less.
Quote:
So the label is the same thing as DEF / DIM opcode on BASIC language, right?
No a label is closer to a line number in BASIC. (Or actual labels in BASIC, because some versions of BASIC have the exact same concept.)
A branch in 6502 is a bit like an if statement and a goto all in one.
Quote:
So it IS "The Address you are on now!" Is it?
Yes. The post says that right away.
The short version of the other post:
A label is alphanumeric text followed by a colon. (mario:) Although its alphanumeric, you should not start with a number. (9mario: is not okay, mario9 is.) It allows you to easily get the address of whatever instruction follows it.
BEQ goes to the instruction after the label that follows (is on the same line as) the BEQ if the zero flag is set.
BEQ goes to the instruction after the BEQ (which is usually on the next line in the code) if the zero flag is clear.
BNE goes to the instruction after the label that follows (is on the same line as) the BNE if the zero flag is clear.
BNE goes to the instruction after the BNE (which is usually on the next line in the code) if the zero flag is set.
I can certainly only do the short versions if you find them more helpful, but I feel like part of your problem with documentation is lack of examples.
Edit2: One more thought, actually. It seems you particularly did not like the cuteness of the conversation with the 6502 CPU. This makes me curious what sort of cartoons or comics you want to create. Because if I were to have made a comic, I'd have made that comic.
Anyway, the ball is in your court.
Edit: Fixed some errors caused by aggressive copy-pasting.
Kasumi wrote:
You can see how long each version of each instruction will be in the documentation:
http://www.obelisk.me.uk/6502/reference.html#LDADocWaluigean, if you are scared by that site's design cause of its all-text-and-thin-table-lines ilk, than you share that fear with me. After finding the creator of the 6502 (MOS Technology)'s 6502 programming manual and printing out its Appendices it made finding the length of each instruction more fun for me.
starting at pdf page 204, I think, is where the MOS Technology helpful, to me at least, info starts.
Kasumi wrote:
Quote:
I feel very lazy to read or demotivated to try to listen as it looks complex for me.
It only gets more complex. I want to be motivating, but that's the reality of it.
Quote:
Part of me say, "Who cares!? I just want to play and make my own video games!!!" about counting each by each programs.
Conditionals (branching) are literally the thing that gives interactivity to games. For example, the face code had no conditionals, so it could only ever draw one thing.
Conditionals are what make the character only move IF a button is pressed. Die IF you fall too low. Stomp a goomba IF Mario is falling and IF Mario is colliding with the goomba.
Quote:
But another for number to load? Even though it's already been used for LDA code?
Hm. Let's reason about this. Suppose it was only one byte. You can load 256 values into A. So if each instruction were only one byte, the only thing the CPU could do is load every value into A. There could not be any other instructions.
Reasoning further, there are 65536 possible addresses to load from. So similarly, if you wanted to load from all the addresses with only two bytes, that's all you could do.
The mnemonic (three letter code, like LDA) groups multiple opcodes to make it easier on the programmer. The different opcodes specify the task as well as the METHOD of the task to the CPU. (Also known as the addressing mode.)
lda #$00 and lda $0200 both copy a value into A. But HOW they get the value differs.
LDA #$?? is the "immediate" addressing mode. $A9 is LDA immediate, but you still need another byte so you can load any of the 256 values a byte can hold.
lda $???? is the absolute addressing mode. $AD is LDA absolute, but you still need two more bytes so you can load from any of the 65536 addresses.
So
$A9 $FF = lda #$FF
$A9 $00 = lda #$00
$AD $00 $00 = lda $0000
You can see how long each version of each instruction will be in the documentation:
http://www.obelisk.me.uk/6502/reference.html#LDAIt lists the addressing modes, the opcode (the byte the CPU reads to determine what to do), bytes (which is how many bytes the instruction is total. Including the opcode for the byte) and cycles (which is how long it takes to complete, in a somewhat abstract measurement.)
Quote:
Two bytes? Is it the High-Byte and Low-Byte? Or is it the "$0245 = $02 and $45" that's reason why it's two bytes?
It is indeed the high byte and low byte of the address. $0200 = $02 and $00, yes, that's the reason it's two bytes. You can't represent all addresses with one byte. That said, the order is different than you might expect, but it only matters for something that would be covered way less.
Quote:
So the label is the same thing as DEF / DIM opcode on BASIC language, right?
No a label is closer to a line number in BASIC. (Or actual labels in BASIC, because some versions of BASIC have the exact same concept.)
A branch in 6502 is a bit like an if statement and a goto all in one.
Quote:
So it IS "The Address you are on now!" Is it?
Yes. The post says that right away.
The short version of the other post:
A label is alphanumeric text followed by a colon. (mario:) Although its alphanumeric, you should not start with a number. (9mario: is not okay, mario9 is.) It allows you to easily get the address of whatever instruction follows it.
BEQ goes to the instruction after the label that follows (is on the same line as) the BEQ if the zero flag is set.
BEQ goes to the instruction after the BEQ (which is usually on the next line in the code) if the zero flag is clear.
BNE goes to the instruction after the label that follows (is on the same line as) the BNE if the zero flag is clear.
BNE goes to the instruction after the BNE (which is usually on the next line in the code) if the zero flag is set.
I can certainly only do the short versions if you find them more helpful, but I feel like part of your problem with documentation is lack of examples.
Edit2: One more thought, actually. It seems you particularly did not like the cuteness of the conversation with the 6502 CPU. This makes me curious what sort of cartoons or comics you want to create. Because if I were to have made a comic, I'd have made that comic.
Anyway, the ball is in your court.
Edit: Fixed some errors caused by aggressive copy-pasting.
Even after hours of thinking or trying to do something before going here, I'm still feeling, "I don't want to learn this, and I want different subject."
Is it alright to give me a famous beloved video game examples of how Branch, or the topic of this lesson, is used? Something that will REALLY spark a revolution, like the scene in Kirby's Adventure when the tower is 3D rotating until the finish.
unregistered wrote:
Kasumi wrote:
You can see how long each version of each instruction will be in the documentation:
http://www.obelisk.me.uk/6502/reference.html#LDADocWaluigean, if you are scared by that site's design cause of its all-text-and-thin-table-lines ilk, than you share that fear with me. After finding the creator of the 6502 (MOS Technology)'s 6502 programming manual and printing out its Appendices it made finding the length of each instruction more fun for me.
starting at pdf page 204, I think, is where the MOS Technology helpful, to me at least, info starts. That's very kind, Unregistered. But It's more of how awfully dull it looks. There is no legend or meaning when looking through it. It's like looking at a map of California, but there's no bus, restaurant, city, etc. It's no soul or heart into trying to teach everyone who DEEPLY want to learn how to program 6502.
I mean sure, this IS advanced, and it's expected to give a sense of "low point of motivations" where 99% of beginners decide to quit, and stuff. But I don't ever want to be like those.
If I were to read it again, I maaay give different replies, but I don't ever want to offend anyone.
Quote:
"I don't want to learn this, and I want different subject."
I mean. You're certainly able to find a different subject. I would be doing fun examples if I could, because that's also more fun for me, but they all rely on these dull things I'm trying to cover.
Right now you've only got like 24% of the 6502 toolbox, 0% of the NES toolbox and 0% of Kirby's Adventure's cartridge's toolbox. How the tower works would go like 90% over your head. Even medium level stuff like how Mario jumps would. And even really simple stuff like how Super Mario Bros. decides whether or not a game over should happen after he dies uses a flag you don't yet know. And while you could do similar with the flag you do know, it's not anymore interesting than adding the numbers.
If you want more immediate results, you can try other platforms as has been said before. This doesn't mean you never learn 6502, it just means you get more immediate results while learning skills you can then apply to 6502. It's hard to make recommendations, since all the stuff I learned from is pretty dead. Lots of people dig
pico8, though.
Someone I respect recommends Light Bot:
http://lightbot.com/flash.html (A different version, but it's hard to find that version on a website that's not overrun with ads.) It's not a programming language, but it teaches programming concepts as a game.
Regardless. The ball is in your court.
Kasumi wrote:
Someone I respect recommends Light Bot:
http://lightbot.com/ (A different version, but it's hard to find that version on a website that's not overrun with ads.) It's not a programming language, but it teaches programming concepts as a game.
Off-topic reply from me, but: interesting/neat. We had a game akin to this on the Apple II called
Robot Odyssey (
video) (
web-based remake of the game) (
PDF of original manual). This game was from 1984, BTW. The premise is the same, except instead of a "programming language", you're learning types of digital circuits, logic gates (AND/OR/XOR/NOT), and flip-flops to solve puzzles.
Robot Odyssey has really cool visuals. I tried it and it requires SUPER full focus, though.
A person I met who wasn't a programmer talked about liking this game:
https://store.steampowered.com/app/370360/TIS100/That developer has a few others in the genre.
I made some basic plans for an adventure game that teaches 6502 (or maybe just executable hacking), but it's the kind of thing I'll probably never actually spend the time to do. I guess the closest thing to the plan it'd be is
Hack 'n' Slash (one more programmy game for the pile). I'm probably more into the tech of it than the game. (Breaking user created infinite loops, verifying they don't place KIL instructions, RAM viewer built into the actual game.) That's probably why some of these games exists.
Educational games feel pretty on topic in this topic, actually. "How does one best present the information?"
DocWaluigean wrote:
Is it alright to give me a famous beloved video game examples of how Branch, or the topic of this lesson, is used? Something that will REALLY spark a revolution, like the scene in Kirby's Adventure when the tower is 3D rotating until the finish.
The problem is that these kinds of real life examples require a lot of code, and often rely on several aspects of the game engine, which is even more complex. Making a character jump doesn't take 3 or 4 instructions, it may take hundreds of them, and they're scattered around the ROM because some parts run at different times (the first part runs when the button is pressed, another runs every frame during the game logic, etc.).
We understand that this is not how you like to learn, but every NES programmer to this day has learned to make NES games by reading technical documents or tutorials and experimenting to see the results. You have to stop saying "this is not how I learn" and start trying to modify your own behavior, get out of your comfort zone, if you ever want to get anything done, because the world will not modify itself to accommodate you. You're already extremely lucky that Kasumi is taking the time to tutor you, this never happens around here.
For a lot of people, assembly language is fun. Learning what all the instructions do and figuring out how they can be used together to accomplish bigger things is just as much fun as setting the results on the screen. If you're "bored" by the CPU, than I'm sorry to say that this is most of what you'll be doing when making games. Even when you know the CPU and the NES 100%, nobody makes a game like it's nothing, we still have to stop and think, analyze problems and figure out how to solve them, plan stuff out, debug code... Nobody sits down without planning and writes Kirby in a couple of days.
THIRD TIME! Third time is a lucky number time. I'm going to read it, and I'm going to pretend that you never wrote this, so I can get it out of my system.
I'm SOOO sorry, always, in advance, letting you know.
If I learn TOO fast from the BunnyBoy problems, maybe I should try again on this one...
------
Branching
But first, one more part about the 6502's state.
The PC is the Program Counter. It keeps track of the address of the next instruction the CPU will execute. Previously when we used the word "address" it was referring specifically to RAM addresses. However each byte of your code has an address too. Step through this (very simple) code and watch the Program Counter in easy6502.
Code:
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
lda #$00
You'll notice that it goes up by two every time. this is because lda #$00 is two bytes. One byte for an LDA opcode. One byte for the number to load. Now step through this (very simple) code and watch the Program Counter again.
Code:
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
Here, it goes up by three each time. One byte for an LDA opcode. Two bytes for the address.-----
What's the purpose of Program Counter if I don't find or see one if I were to make REAL NES applications? If I were to start making games, and writing codes on NotePad ++, I will never able to play nor see, so what's the point if I may never know where to find "step" debug?
Why do you have to make this like other works? I don't see, "-----" this and "***SPECIAL IMPORTANT!!!***" that?
I know it's my fault on earlier part, because I had this similar but weaker feelings of uncaring on the Register post, but I did put effort to read and finally understand. But on this one.. it looks dull or... look like a chore to read! Kids and teens and autism people wouldn't enjoy reading the entire things, or might get really bored SUPER fast about this.
But on other hand... there is no existences for love or soul put into the perfected-Elementary document for 6502 Assembly program, compare to C# or BASIC languages... so I got to keep going and keep trying for real for us to make it happen for us.
I don't understand what you mean address as in RAM address. I'm guessing you should say, "For this lesson, we'll focus on specific Address: The Random-Access Memory Address!"
Previously when we used the word "address" it was referring specifically to RAM addresses. However each byte of your code has an address too.THIS one doesn't make sense, because if each byte of code also has address, then why isn't there any "Anatomy or Map of Address for byte" the SAME way there is a map of Address for PPU? [I feel it's Overview, but I'm putting all my thoughts instead of random nonsense thoughts MANY beginners always decided to say that gives up.]
However, from the each byte of the code has address your saying, are you referring to, "Each byte of the code inside the Address ALSO has another address."? Like the PPU where, in pseudocode of $C000, a color palette code, #$01 represent color red, #$02 represent color green, etc. Is THIS what your talking about?
What's the purpose of LDA #$02 so many times? For people with OCD, or mental conflicts that they have to write 7 times to feel normal, it will make sense, but why?
***Using Easy6502: So the Program Counter
is actually memory containment?----------
Code:
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
lda $0200
Here, it goes up by three each time. One byte for an LDA opcode. Two bytes for the address.
----------
So three zeros increases the counter by 3?
Why LDA $0200 again? Your not adding any number there! Unless it's zeros many times.
----------
While writing and thinking about 6502 code, you basically never give any thought to the Program Counter. (Or at least, I don't!) It helps the CPU, but not you as the programmer that much. Unlike A, X and Y where you can change and then use the contents, and unlike the flags which are used for the decision making, the Program Counter is basically not interactive. I teach you about it now, so that you can better track the branching examples. Also, having learned it, you now know more than half of 6502 CPU's state!
In easy6502, your first instruction is put at the address $0600. This is also where easy6502 starts executing from. Everything we have done until now starts at the top of our code ($0600) and then runs each instruction one line at a time going down. There are a few families of instructions that let you go someplace other than the instruction immediately below. The family this post introduces is the "branch" family. These are instructions that will either allow the CPU to go to the next instruction below OR go to a different address in the code specified by the branch. Which happens depends on the "condition" associated with that branch.
BEQ/BNE are the only two branch instructions we can cover right now, but the others are very similar. (Sort of like how TAY, TYA, TAX and TXA were all very similar.)
----------
I STILL have no idea what you mean. =w=
you basically never give any thought to the Program Counter. (Or at least, I don't!) So all this reading for nothing???
----------
BEQ/BNE are the only two branch instructions we can cover right now, but the others are very similar. (Sort of like how TAY, TYA, TAX and TXA were all very similar.)
BEQ is Branch on EQual (to zero). It will go ("branch") to the address specified after the branch if the zero flag is set. Otherwise, it will go to the next instruction like we've gotten used to happening. (To the very technically minded reading this: Yes, I realize part of this explanation is not-quite-true. But to me it makes more sense to introduce the "exception" when a bit more knowledge is gained.)
Here is a simple example:
Code:
restart:
lda #$00;This sets the zero flag
beq restart
lda #$FF
----------
I got to stop this, because I'm STILL no idea about Branch and PC.
*******
I want to reply the other one, but NOW my mind is allll messed up now. We gotta start over on Branching slow by slow. Like one at a time! It's WAYYYY too overwhelming for people like me to learn with love. No wonder people complains much years and years ago.
****************************************************
I'm feeling the PC, Program Counter, is actually "What line of code are you on now."
Is THIS correct? If it is, then why do I move by 2 or 3 address number up? Two on regular number, three on Address load [or zero?]Doesn't make sense more. Two bytes? Is it the High-Byte and Low-Byte? Or is it the "$0245 = $02 and $45" that's reason why it's two bytes?
Is THIS correct? I don't absolutely know how High-Byte and Low-Byte really works. The only time I saw is the PPU example on Nerdy Nights 4 when they mention on putting colors.So it IS "The Address you are on now!" Is it?Is THIS correct, about the Program COUNTER, where it's not about how many times your using the same opcodes in a row, but it's the location?!
Let's try and see what we [I HOPE WE, NOT JUST me.] learned:
The Register of NES/6502 is three unique box that carry funny numbers around. HEX [#$], Binary [%$], and "Immediate Decimal" or actually normal numbers. [#$].
The A, Accumulator, X and Y can all carry the number and wait for the further code and commands.
Like Box of Apples, cooked X-Ray Fish, and Yuzu, a yellow-green citrus fruit that hails from Japan. [Where NES was born, haha.]
Since this is the present day, each A, X, and Y has genetic-modified DNA stuff that provides different vitamins, different health benefits, and etc.
And it's a futuristic restaurant, founded by you.
You deliver the box of Apples [Accumulator] to certain house [Address $NNNN] and each house has a job, like policeman [RAM], museum [PPU], etc.
Hmmmm..
A, X, and Y is the exact same thing as:
"Yo! Let's carry this number, A! I got 21"
"Sure thing, Y! I'll carry this number 3! How about you, X?"
"I'll try. I'm carrying this funny number as $FF"
And they're all holding the variable/numbers forEVER until the system restarts OR they're replacing numbers like LDA / LDX / LDY / TAX / TAY / INX / INY / INC
So...
Register is like THREE machine claw carrying GIANT numbers and the address is a funny cubical boxes where each address code represent what they do for 6502 CPU. Claw red is A, claw blue is X, and yellow claw is Y, aside the transfer/increment differences, the colors doesn't matter, because it's fun to put colorful stuff in it. The giant number 20 fell into Address $2000, which for this example, is an Address Code for coloring fluffy cute bunnies. And the example would be:
LDA #$20
STA $2000
And according to the pseudocode for $2000, the 2 digits at end [$XX??] represent one of few sprites that paint the fluffy bunny red.
[I'm putting way too much effort just to show how hard I'm trying to learn and think well.]
The Branch Post wrote:
The PC is the Program Counter. It keeps track of the address of the next instruction the CPU will execute.
Quote:
DocWaluigean wrote:
So it IS "The Address you are on now!" Is it?
Yes. The post says that right away.
DocWaluigean wrote:
***Using Easy6502: So the Program Counter is actually memory containment?
I introduced the concept with a one sentence introduction of it. You asked for clarification, and I gave it. And then you came up with an entirely different explanation of it. Can you understand how this might be confusing to me? It makes it hard to keep track of what you have actually learned.
Edit: Or here:
DocWaluigean wrote:
you basically never give any thought to the Program Counter. (Or at least, I don't!)
So all this reading for nothing???
the post wrote:
I teach you about it now, so that you can better track the branching examples.
So let's try something different.
The 6502 can "see" (has immediate access to) 65536 "addresses". They occupy $0000-$FFFF. For purposes of this lesson, all the addresses can be read from (lda $????) or written to (sta $????). All addresses are a "home" for a single byte. The address is where to find that byte.
When you click "Assemble" in easy6502, your code is turned into bytes and placed starting at $0600. That is to say that the address or "home" of the first byte of the first instruction that you type will be $0600. That's where to find it.
Is there anything here that is not clear?
Kasumi wrote:
The Branch Post wrote:
The PC is the Program Counter. It keeps track of the address of the next instruction the CPU will execute.
Quote:
DocWaluigean wrote:
So it IS "The Address you are on now!" Is it?
Yes. The post says that right away.
DocWaluigean wrote:
***Using Easy6502: So the Program Counter is actually memory containment?
I introduced the concept with a one sentence introduction of it. You asked for clarification, and I gave it. And then you came up with an entirely different explanation of it. Can you understand how this might be confusing to me? It makes it hard to keep track of what you have actually learned.
Edit: Or here:
DocWaluigean wrote:
you basically never give any thought to the Program Counter. (Or at least, I don't!)
So all this reading for nothing???
the post wrote:
I teach you about it now, so that you can better track the branching examples.
So let's try something different.
The 6502 can "see" (has immediate access to) 65536 "addresses". They occupy $0000-$FFFF. For purposes of this lesson, all the addresses can be read from (lda $????) or written to (sta $????). All addresses are a "home" for a single byte. The address is where to find that byte.
When you click "Assemble" in easy6502, your code is turned into bytes and placed starting at $0600. That is to say that the address or "home" of the first byte of the first instruction that you type will be $0600. That's where to find it.
Is there anything here that is not clear?
I have aaabsolutely no idea what your saying with the quotes. o-o Well... tiny bit if I read it again.
-I'm guessing I'm right about the lesson on Branching is "The Program Counter is where are you in Address now."
-When the Program Counter is going up, the Opcode goes up by 2, and the Address goes up by 3. When it's number/HEX/Decimals, it's only 2 code upward, in favor for the opcode, that's used in the Address code, and the number that's also used for the Address code. I'm guessing high-byte and low-byte doesn't count here.
-While for Address, it goes up by 3 because of Opcode being used, and Address code's high-byte and low-byte. Because of $12 and the $34 represent $1234, THAT's why it goes up by 3. They work differently. Because the $12 represent the "street" of the code, while $34 represent the "house of the code. $12 might be CPU, PPU, RAM. And the $34 might be the lever or role/job for what they do FOR CPU, PPU, RAM.
-Labels are a type of BIG box you can use for later codings.
-It's like writing a paper or note, where PC Opcode is a pen, while PC Address is a BOLD pen.
-----------
Code:
restart:
; $0600
ldx #$00 ;Put number 0 into X Register. Use up 2 bytes; $0602.
inx ; Increase X Register by one. Resulting X=1 The ALREADY-USED opcode is not using up in the Address Code because it's already in there. Still one code = one waste.
;$0603
beq restart ;@GOTO restart, do the same thing, then go back to here. Used up 2 bytes for 2 code-lines.
;$0605
dex ; Decrese X Register by one, resulting X=0. The ALREADY-USED opcode is not using up in the Address Code because it's already in there. Still one code = one waste.
;$0606
bne restart ; @GOTO restart, repeat the same thing but after finish, go back to here instead of the first BNE. Same thing, used up 2 bytes for 2 code-lines.
;$0608
;-------
beq skip ; If the Zero Flag is turned on, or "Set", then @GOTO "skip" label. If the Zero Flag is turned OFF, then proceed on the coding lines.
lda #$00 ; Put 0 into Register A.
beq restart ; Repeat the entire same process, but this time, Register A is on the whole time.
skip: ; Go to this code if the Zero Flag is turned on. As one by one line goes through, it wast so many bytes.
;$060E
;Apparently ONLY Register A can give commands to Branch of BEQ and BNE.
---
Quote:
So let's try something different.
The 6502 can "see" (has immediate access to) 65536 "addresses". They occupy $0000-$FFFF. For purposes of this lesson, all the addresses can be read from (lda $????) or written to (sta $????). All addresses are a "home" for a single byte. The address is where to find that byte.
When you click "Assemble" in easy6502, your code is turned into bytes and placed starting at $0600. That is to say that the address or "home" of the first byte of the first instruction that you type will be $0600. That's where to find it.
Is there anything here that is not clear?
I guess it's all clear for a while? A little permanent marker but clean enough.
EDIT: by the way, if you sound a little bit upset, I'm sorry.
DocWaluigean wrote:
THIRD TIME! Third time is a lucky number time. I'm going to read it, and I'm going to pretend that you never wrote this, so I can get it out of my system.
Just wanted to make it clear that I wasn't trying to be rude or anything, I was just warning you to be careful with your expectations. Programming games isn't always fun, most of it is actually solving problems. If you don't find problem-solving fun, programming games will always feel like a chore to you.
tokumaru wrote:
DocWaluigean wrote:
THIRD TIME! Third time is a lucky number time. I'm going to read it, and I'm going to pretend that you never wrote this, so I can get it out of my system.
Just wanted to make it clear that I wasn't trying to be rude or anything, I was just warning you to be careful with your expectations. Programming games isn't always fun, most of it is actually solving problems. If you don't find problem-solving fun, programming games will always feel like a chore to you.
Actually, that was a fun-sentences like if cartoony people were to say, "Welp! Third time's the charm!" It's more of "I'm starting to feel little more comfortable, I guess I should say it." attitude.
I'm sorry if I'm being the one whose rude though. It's, sadly, just who I am. Alongside I said earlier that it took me 5 years from beginning to learning all the way to last month to try to really learn 6502.
Also, I don't want to be view as, "This thug is up to something bad." this and other that. Obviously the internet is like the real world with illegal crimes and stuff. I'm not anything like those.
Quote:
-I'm guessing I'm right about the lesson on Branching is "The Program Counter is where are you in Address now."
This is correct. Or at least. It's correct that the program counter is where the CPU will next execute an instruction. You are not correct that that was the goal of the lesson. The Program Counter was taught only to make it easier to follow the real lesson, which was branching.
Quote:
-When the Program Counter is going up, the Opcode goes up by 2, and the Address goes up by 3. When it's number/HEX/Decimals, it's only 2 code upward, in favor for the opcode, that's used in the Address code, and the number that's also used for the Address code. I'm guessing high-byte and low-byte doesn't count here.
This is not. Each instruction always has an opcode. This is one byte. Most instructions then have an operand of either 1 or 2 bytes. So if you are using an instruction that is dealing with an address (that isn't $0000-$00FF) it is three bytes. One byte for the opcode. Two bytes for the operand which is an address.
Some instructions are exactly one byte total (just the opcode), we just haven't covered any of those yet.
Way simpler: The CPU just "knows" how many bytes each instruction is. It will add the size in bytes of the current instruction to the PC and then the PC will have the address of the next instruction.
Edit:
Quote:
Because the $12 represent the "street" of the code, while $34 represent the "house of the code. $12 might be CPU, PPU, RAM. And the $34 might be the lever or role/job for what they do FOR CPU, PPU, RAM.
This is actually a reasonably solid way to look at it. It is correct that the byte in $12's place usually does defines a "profession" (like construction), while the byte in $34's place usually chooses the role within that profession. (Flag Man, cement truck driver.) RAM isn't really delegated into jobs, though.
Quote:
-Labels are a type of BIG box you can use for later codings.
They're actually more like the label you put ON the box. Labels don't really "store" anything. They just name things.
How you've commented the example isn't correct, but I'm going another way for now.
Everyone following this topic will probably think I'm crazy for even trying this example here, but I think it will actually help.
I will explain why I'm doing this upfront. I want to make it clear that everything is just bytes. That the 6502 CPU doesn't care that much about things. Most context is created to help the programmer.
Order is VERY IMPORTANT. Do these things step by step. If you do anything out of order, you will need to navigate to the page again and follow the steps again starting from 1.
1. Go to an easy6502 code box.
2. Erase what's in the box.
3. Type (but don't assemble) the following code.
Code:
lda #$A2
sta $0600
This address should look familiar. It is the address of the first byte of the first instruction, if you recall.
4. Type 0600 next to Start: $
5. Check the checkbox next to "Monitor"
Your easy6502 box should now look like this:
6. Click assemble
7. Check the checkbox next to "Debugger"
8. Click step.
9. Type out (in notepad or something, not easy6502) the values to the right of 0600: under the monitor checkbox. These are the bytes that the code (lda #$A2, sta $0600) became.
10. Click run.
11. Type out which values are in in A, X and Y underneath the bytes you typed out earlier.
12. In your document, type out the values to the right of 0600: under the monitor again. They've changed, but this should make sense. After all, you just stored a number there.
13. Click reset.
14. Click run.
15. Type out which values are in A, X, and Y underneath the bytes you typed out earlier.
What changed? Do you have a guess as to why this might be?
Code:
A=$00 X=$00 Y=$00
SP=$ff PC=$0600
NV-BDIZC
00110000
-
0600: a9 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=====
run
=====
A=$00 X=$a2 Y=$00
SP=$ff PC=$0606
NV-BDIZC
10110000
-
0600: 00 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=====
2nd run
=====
A=$00 X=$00 Y=$00
SP=$ff PC=$0601
NV-BDIZC
00110000
-
0600: 00 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
You only need the values immediately to the right of 0600. Not below. (i.e .not the 0610, 0620 etc columns which are all zero.)
Something tells me the steps weren't followed exactly. The PC would not be $0600 at any of the points where you were meant to note what A, X and Y were, so your first run's value seem to be after either reset or assemble, not after run or step.
Your second run's results are also not what I want to show. You need to start entirely over with the steps if any mistake is made during them.
Also important: You are getting the values from A, X and Y and the values to the right of $0600 at DIFFERENT times, this is why they are not together in the steps.
You have the state of A, X and Y (step 11) before the values to the right of 0600 (step 9)
Kasumi wrote:
You only need the values immediately to the right of 0600. Not below. (i.e .not the 0610, 0620 etc columns which are all zero.)
Something tells me the steps weren't followed exactly. The PC would not be $0600 at any of the points where you were meant to note what A, X and Y were, so your first run's value seem to be after either reset or assemble, not after run or step.
Your second run's results are also not what I want to show. You need to start entirely over with the steps if any mistake is made during them.
Also important: You are getting the values from A, X and Y and the values to the right of $0600 at DIFFERENT times, this is why they are not together in the steps.
You have the state of A, X and Y (step 11) before the values to the right of 0600 (step 9)
6. Click assembleCode:
0600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Preprocessing ...
Indexing labels ...
Found 0 labels.
Assembling code ...
Code assembled successfully, 5 bytes.
A=$00 X=$00 Y=$00
SP=$ff PC=$0600
NV-BDIZC
00110000
=================
8. Click step.
9. Type out (in notepad or something, not easy6502) the values to the right of 0600: under the monitor checkbox. These are the bytes that the code (lda #$A2, sta $0600) became. A=$a2 X=$00 Y=$00
SP=$ff PC=$0602
NV-BDIZC
10110000
Code:
0600: a9 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Preprocessing ...
Indexing labels ...
Found 0 labels.
Assembling code ...
Code assembled successfully, 5 bytes.
=====
10. Click run.A=$00 X=$8d Y=$00
SP=$ff PC=$0604
NV-BDIZC
10110000
0600: a2 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =====
13. Click reset.
14. Click run.A=$a2 X=$00 Y=$00
SP=$ff PC=$0606
NV-BDIZC
10110000
Code:
0600: a2 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
0610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
While re-reading it, I keep seeing missing info.
Instead of, "Below the box where you put the code, there's Monitor, Start, and Length. Type 0600 next to "Start: $"
It's "4. Type 0600 next to Start: $" .....
I'm really trying this time..
It's true I could have been more specific about where to type 0600, but there is an image very shortly after that shows what it should look like when the steps are completed. Even if there were not, there is only one place with text that says "Start: $" and only one place you can type into next to it.
This has come up a bit, and I promise I'm not trying to pick on you. But sometimes the key to understanding something is very shortly after the part you don't understand. If you always stop immediately on the first confusing thing, you may end up stuck when the answer was actually really close. For things like steps, it's often helpful to read all the steps once before actually doing any of them.
We are still getting different results, which is also strange. I'm not going to have you do it again, but just out of curiosity what's your browser/OS?
Here's what I get for step 9:
0600: a9 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
I click run, and for step 11 I get:
A=$a2 X=$00 Y=$00
And for 12 I get:
0600: a2 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
I click reset, and run, and for step 15 I get:
A=$00 X=$a2 Y=$00
The only way I can get $8d into X is to reset and run multiple times instead of just once. But again, I won't have you do it again. These are my results. And the context for these results is the following. You assemble the program.
Code:
lda #$A2
sta $0600
The program becomes these bytes starting at address $0600:
Code:
0600: a9 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
Some of them should look familiar. For instance, the a2 is from the lda #$A2 in the code that was assembled. And the 00 and 06 are from the sta $0600 in the code that was assembled. (The bytes are "backwards", yes. That is simply how the 6502 CPU stores addresses.)
This means $a9 is the opcode for LDA #??.
Because lda #?? needs another byte for the value (which is its operand), this means the next byte will be used to fill in the ?s. The next byte is $A2. Altogether, that's lda #$A2. Exactly what was typed in.
The 6502 completes that instruction and is now at the next instruction. The byte following the last byte of the last instuction (which was $A2) is the opcode of the next instruction.
This means $8d is the opcode for STA $????.
Because sta $???? needs TWO bytes for the address (which is its operand), this means the next two bytes will be used to fill in the ?s. The next two bytes are $00 and $06. Since 6502 stores them flipped, if you flip them back you get $0600. Altogether, that's sta $0600. Exactly what was typed in.
After the program is run, you get these values in A, X and Y.
Code:
A=$a2 X=$00 Y=$00
This should make sense, because there is an LDA #$A2 as the first instruction in the code. Now the bytes starting at address $0600 look like this:
Code:
0600: a2 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00
This should also make sense, because you stored $A2 to address $0600.
Then you click reset, which sends easy6502's CPU back to $0600. (Where the opcode for the first instruction should be.)
After the program is run, you get these values in A, X and Y:
Code:
A=$00 X=$a2 Y=$00
What is different in A, X and Y from when the program was run the first time?
Thinking about the explanation above, why do you think it ends up different?
I will try and read it fourth time...Again...
-Despite importance of this is very less, Program Counter allows you to to see where "you are now" on the location of the code.
-For HEX/Binary/number, it goes up by two. Because the opcode is stored into the assembly for the code to proceed, and the variables stored FOR/IN the opcode.
-For Address Code, it goes up by three. Because also the opcode is stored into the assembly for the code to proceed. BUT the Address has two separated numbers: high-byte and low-byte. the two separated numbers is two of three reasons for it to go up by three.
-Judging what you say about, "While writing and thinking about 6502 code, you basically never give any thought to the Program Counter. (Or at least, I don't!) It helps the CPU, but not you as the programmer that much." ---- This is less important for learning, but it's great to learn what this does. "I teach you about it now, so that you can better track the branching examples. Also, having learned it, you now know more than half of 6502 CPU's state!"
-BEQ/BNE is a new opcode I/you/we all will learn. It's a Lever-On-or-Off.
-BEQ: If the Zero Flag is turned on, while the code-line is onto BEQ, it will perform specific code upon it. OR it will go to the label of the code before returning here.
-If the Zero Flag is turned off, while the code-line is onto BEQ, it will be ignored and proceed like comment code.
-BNE is the polar opposite of BEQ. If Zero flag is OFF, while the code line is onto BNE, it will perform specific code, or go to label before returning here.
-If the Zero Flag is turned ON, while code line is onto BEQ, it will be ignored and proceed like comment code.
-Label is used to make re-using the code much faster and easier. And save a lot of spaces.
-----
? - Program Counter counts how many bytes you wasted. Potentially show you if you are wasting any memory to fit into NES or Mapper.
? - The High-Byte is $12. The Low-Byte is $34. The result is $1234.
X - The High-Byte and Low-Byte is not understood at this time for me.
========
I could see stern talk earlier. So I'm sorry if I was any rude to you. The Branching, at this time, is the hardest new lesson I had to see.
The best communication is to best understand each other.
What you've written about beq/bne is still not quite correct. Ignore the branching post.
Read this post:
viewtopic.php?p=225445#p225445And answer the questions at the bottom. Or ask questions about it.
Edit for the questions:
Quote:
-Despite importance of this is very less, Program Counter allows you to to see where "you are now" on the location of the code.
This is correct.
Quote:
-BEQ: If the Zero Flag is turned on, while the code-line is onto BEQ, it will perform specific code upon it. OR it will go to the label of the code before returning here.
-If the Zero Flag is turned off, while the code-line is onto BEQ, it will be ignored and proceed like comment code.
If the zero flag is turned on, while the code is on the line of the beq, it will go to the label next to it. There is no or. It also won't return.
If the zero flag is turned off, while the code is on the line of the beq, it will do nothing and proceed.
If the zero flag is turned on, it will do exactly one thing. If the zero flag is turned off, it will do exactly one thing. It can do one thing OR the other because the zero flag can be turned on OR turned off.
But given a turned on zero flag, it will always do one thing. And given a turned off zero flag, it will always do one thing.
Quote:
-Label is used to make re-using the code much faster and easier. And save a lot of spaces.
It makes it easier to read/write code because you don't have to memorize numbered addresses, but it saves no space at all.
Quote:
? - Program Counter counts how many bytes you wasted. Potentially show you if you are wasting any memory to fit into NES or Mapper.
No. Your other explanation was right. The explanation in the post was "The PC is the Program Counter. It keeps track of the address of the next instruction the CPU will execute." I'm not sure of a better way to make it clear.
The 6502 is very simple. I get the impression you've got it in your head that it can't be that simple, so you're trying to introduce new concepts to it. Basically everything related to 6502 does exactly one simple thing, keeps track of exactly one simple thing, or chooses between two simple things based on the state of one simple thing.
Quote:
? - The High-Byte is $12. The Low-Byte is $34. The result is $1234.
This is correct. Given $1234, the high byte is $12 and the low byte is $34. The 6502 would store them "backwards" like $34 $12, but they still represent $1234.
What is different in A, X and Y from when the program was run the first time?
Thinking about the explanation above, why do you think it ends up different?
My browser is Firefox atm.
Upon first running program:
A=$a2 X=$00 Y=$00
SP=$ff PC=$0606
NV-BDIZC
10110000
2nd time:
A=$00 X=$a2 Y=$00
SP=$ff PC=$0606
NV-BDIZC
10110000
3rd time [Press run 2 times]:
A=$00 X=$8d Y=$00
SP=$ff PC=$0604
NV-BDIZC
10110000
---
..........................I don't ever want this to be Bunnyboy nerdy nights all over again...............
The difference in running second time, is that upon reset, the tiny pieces of memories inside the CPU is still kept, and goes different ways because the memory from first run was partially kept, and then second memory..
I'll ask a more specific question.
Why does this specific code do something different each time you run it? It can't be just that memory is kept around, because no other code you've written or tried would get a different result after running it again. What is it about this code that makes it get a different result?
Kasumi wrote:
I'll ask a more specific question.
Why does this specific code do something different each time you run it? It can't be just that memory is kept around, because no other code you've written or tried would get a different result after running it again. What is it about this code that makes it get a different result?
When you run the first time, the code is stored into Address $0600.
0600: a2 a2 8d 00 06 00 00 00 00 00 00 00 00 00 00 00When you run the second time, while this code above is in there, it will give the same value, but in X instead of A.
Is this lesson well thought out for difficult thinking or is it trying to "prove me if I have what it takes to be part of NESDev or kick me out" test???
Is it because according to DISASSEMBLE on first time:
Address Hexdump Dissassembly
-------------------------------
$0600 a2 a2 LDX #$a2
$0602 8d 00 06 STA $0600
and on the second time:
Address Hexdump Dissassembly
-------------------------------
$0600 00 BRK
$0601 a2 8d LDX #$8d
$0603 00 BRK
$0604 06 00 ASL $00
There is an extra hidden code placed called BRK [Break Opcode], Load Data X, then ASL???
The BRK is a hidden opcode that appear out of nowhere when you reset the code?
Bingo! Or, more or less bingo. That BRK doesn't come from nowhere, though.
So the first time you run it, it's actually an LDA #$?? opcode, not LDX #$??. It starts with
$A9 $A2. LDA #$A2
And this is why at the end A has $A2 in it.
Then it stores that to $A2 to $0600. And, remember, that's where the first instruction is! So we overwrite the opcode for LDA #$?? with the opcode for LDX #$??. (Which is $A2).
When we reset, it means the PC will start again at the instruction at $0600. But it just got changed!
So the second time you run it, it starts with:
$A2 $A2. LDX #$A2.
And this is why at the end of second run, X (instead of A) has $A2 in it.
But there's still an sta $0600 rather than stx $0600. On easy6502, A starts with $00 in it.
So once again, the first instruction gets changed to a different one. ($00). And when you reset, you get BRK. That's the part you noticed.
This was a long way to get to this point, I admit. But does this make sense? The 6502 can see the addresses from $0000 to $FFFF. It can attempt to read from, attempt to write to, or attempt to execute (run the opcode at) any of those addresses. You have learned 3 ways to attempt a read from an address. lda $????, ldx $???? and ldy $????. And you have learned 3 ways to attempt to write to an address. sta $????, stx $????, sty $????. And, if you understand the above, you understand how an address is "executed". That is, how it looks up the opcode at that address, and does the action associated with that opcode then arrives at (sets the PC to) the address of the next instruction.
It does not care what "type" of address it is in any of those cases. It doesn't care if it's RAM. It doesn't care if it's a register. It doesn't check if the write will even have an effect. (It will always ATTEMPT to write, but the value that was attempted to be written is not necessarily stored, depending on the address.) In this example, you wrote to an address "meant for" code, but the 6502 doesn't care what an address is"meant for". You can also read addresses "meant for" code, and you can execute addresses "meant for" variables. The 6502 does not care about what any given address is "meant for".
Does any of that not make sense? It is vitally important that especially the last two paragraphs make sense.
Edit: It was not meant to be purposefully difficult, though I do realize it IS/WAS difficult. I was running out of ways to make addresses clear which I still believe to be a large part of your confusion. The 6502 considers all addresses to be the same type of thing (with arguably two exceptions we'll cover later), regardless of whether its reading from, or writing to, or executing that address. They're different for the programmer, that's why a memory map exists. For the programmer. The 6502 itself is basically unconcerned by the memory map.
If we're all clear here, I'll test your knowledge of the PC/labels. And then we'll get back to branching.
Kasumi wrote:
Bingo! Or, more or less bingo. That BRK doesn't come from nowhere, though.
So the first time you run it, it's actually an LDA #$?? opcode, not LDX #$??. It starts with
$A9 $A2. LDA #$A2
And this is why at the end A has $A2 in it.
Then it stores that to $A2 to $0600. And, remember, that's where the first instruction is! So we overwrite the opcode for LDA #$?? with the opcode for LDX #$??. (Which is $A2).
When we reset, it means the PC will start again at the instruction at $0600. But it just got changed!
So the second time you run it, it starts with:
$A2 $A2. LDX #$A2.
And this is why at the end of second run, X (instead of A) has $A2 in it.
But there's still an sta $0600 rather than stx $0600. On easy6502, A starts with $00 in it.
So once again, the first instruction gets changed to a different one. ($00). And when you reset, you get BRK. That's the part you noticed.
This was a long way to get to this point, I admit. But does this make sense? The 6502 can see the addresses from $0000 to $FFFF. It can attempt to read from, attempt to write to, or attempt to execute (run the opcode at) any of those addresses. You have learned 3 ways to attempt a read from an address. lda $????, ldx $???? and ldy $????. And you have learned 3 ways to attempt to write to an address. sta $????, stx $????, sty $????. And, if you understand the above, you understand how an address is "executed". That is, how it looks up the opcode at that address, and does the action associated with that opcode then arrives at (sets the PC to) the address of the next instruction.
It does not care what "type" of address it is in any of those cases. It doesn't care if it's RAM. It doesn't care if it's a register. It doesn't check if the write will even have an effect. (It will always ATTEMPT to write, but the value that was attempted to be written is not necessarily stored, depending on the address.) In this example, you wrote to an address "meant for" code, but the 6502 doesn't care what an address is"meant for". You can also read addresses "meant for" code, and you can execute addresses "meant for" variables. The 6502 does not care about what any given address is "meant for".
Does any of that not make sense? It is vitally important that especially the last two paragraphs make sense.
Edit: It was not meant to be purposefully difficult, though I do realize it IS/WAS difficult. I was running out of ways to make addresses clear which I still believe to be a large part of your confusion. The 6502 considers all addresses to be the same type of thing (with arguably two exceptions we'll cover later), regardless of whether its reading from, or writing to, or executing that address. They're different for the programmer, that's why a memory map exists. For the programmer. The 6502 itself is basically unconcerned by the memory map.
If we're all clear here, I'll test your knowledge of the PC/labels. And then we'll get back to branching.
This information is literally illogical to me, I'm starting to feel really upset or really mad at myself since the Easy6502/Nerdy Night issues again..and I do not qualify to complain about this...
Quote:
So the first time you run it, it's actually an LDA #$?? opcode, not LDX #$??. It starts with
$A9 $A2. LDA #$A2
And this is why at the end A has $A2 in it.
Okay, I understand that. Needs better wording on the last sentences though. "At the end, [the A Register] has $A2 in it."
Quote:
Then it stores that to $A2 to $0600. And, remember, that's where the first instruction is! So we overwrite the opcode for LDA #$?? with the opcode for LDX #$??. (Which is $A2).
When we reset, it means the PC will start again at the instruction at $0600. But it just got changed!
What do you mean? or why? You didn't told me we had to re-write or replace LDA with LDX.
Quote:
So the second time you run it, it starts with:
$A2 $A2. LDX #$A2.
And this is why at the end of second run, X (instead of A) has $A2 in it.
But there's still an sta $0600 rather than stx $0600. On easy6502, A starts with $00 in it.
So once again, the first instruction gets changed to a different one. ($00). And when you reset, you get BRK. That's the part you noticed.
There is a LOT of questions I'm literally missing. I don't see LDA turned into LDX alongside with BRK. Or you never told me I need to disassemble...
Quote:
This was a long way to get to this point, I admit. But does this make sense? The 6502 can see the addresses from $0000 to $FFFF. It can attempt to read from, attempt to write to, or attempt to execute (run the opcode at) any of those addresses. You have learned 3 ways to attempt a read from an address. lda $????, ldx $???? and ldy $????. And you have learned 3 ways to attempt to write to an address. sta $????, stx $????, sty $????. And, if you understand the above, you understand how an address is "executed". That is, how it looks up the opcode at that address, and does the action associated with that opcode then arrives at (sets the PC to) the address of the next instruction.
No, it does not. Okay, $0000 - FFFF, I understand. and then read, write to, or excecute. Okay LDA/X/Y. But I'm still not understanding to your certain questions.
Quote:
Edit: It was not meant to be purposefully difficult, though I do realize it IS/WAS difficult. I was running out of ways to make addresses clear which I still believe to be a large part of your confusion. The 6502 considers all addresses to be the same type of thing (with arguably two exceptions we'll cover later), regardless of whether its reading from, or writing to, or executing that address. They're different for the programmer, that's why a memory map exists. For the programmer. The 6502 itself is basically unconcerned by the memory map.
If we're all clear here, I'll test your knowledge of the PC/labels. And then we'll get back to branching.
Let's try do a drawing of examples of how Branching works. So I can get the idea if we're on the same page. I need one-by-one step for it...
Edit: I don't want to put emotions in here. But I am NOT and NEVER giving up. I am
never going to wait another 5 years to learn the same program that I struggled 5 years ago just for confusion about A X Y Register.
Quote:
What do you mean? or why? You didn't told me we had to re-write or replace LDA with LDX.
I didn't tell you you had to replace LDA with LDX because you didn't have to do that. The code did it to itself.
I told you that in easy6502, your code starts at address $0600. This means the first opcode of the first instruction is at $0600. The code I gave you
writes to $0600 which changes what the first instruction is. Does that make sense?
Quote:
Or you never told me I need to disassemble...
You didn't need to disassemble, but I'm very glad you found that resource without me directing you to it. What I was hoping for is that you'd make the connection that since your code starts at $0600 and the program writes to $0600, that that might change the code. I left a bunch of hints about it in the post.
Anyway. Does it make sense now? Even if not, I guess I'm cool with it so long as you understand about how 6502 deals with addresses. Not every example is gonna land. If you wanna get back to branching, give me the address of all of these instructions, and tell me how you found those addresses. Edit: I guess I should say, assume the first one starts at $0600.
Code:
lda #$00
sta $0201
tay
lda $0200
Knowing the purpose of the PC should help.
Kasumi wrote:
Quote:
What do you mean? or why? You didn't told me we had to re-write or replace LDA with LDX.
I didn't tell you you had to replace LDA with LDX because you didn't have to do that. The code did it to itself.
I told you that in easy6502, your code starts at address $0600. This means the first opcode of the first instruction is at $0600. The code I gave you
writes to $0600 which changes what the first instruction is. Does that make sense?
Quote:
Or you never told me I need to disassemble...
You didn't need to disassemble, but I'm very glad you found that resource without me directing you to it. What I was hoping for is that you'd make the connection that since your code starts at $0600 and the program writes to $0600, that that might change the code. I left a bunch of hints about it in the post.
Anyway. Does it make sense now? Even if not, I guess I'm cool with it. Not every example is gonna land. If you wanna get back to branching, give me the address of all of these instructions, and tell me how you found those addresses.
Code:
lda #$00
sta $0201
tay
lda $0200
Knowing the purpose of the PC should help.
If I want to know everything, I can't risk skipping branching..........I told a lot to myself about how bad and/or difficult the 6502 lectures could be...and I do not want to fail and lie to myself that I ignore and refuse to help and skip... Would I even respect myself if I skip even tiny lessons about it after I said how I keep struggling to learn? it happens to everyone on everything in any time, and the potentials become decayed or destroyed. I do never want it happen to here...
I am not racist, yet potentially, I could be delusional, but if the whole people in Japan accept skipping and refusal to keep going and understanding even tiniest problems, what qualities of life and inventions would we be missing out, or worse, never come true?
Is there another example about branching................?
Just to note something: From now on, I'm going to be writing way less. I'm gonna take advantage of the format of having you reply. Why risk writing a long document when I can just write parts at a time and immediately course correct for understanding?
So, remember that literally all the Program Counter does is keep track of the address of the next instruction to run. The "Step" button in easy6502 runs exactly one instruction. With these two pieces of knowledge, that assignment should be complete-able.
(Seriously, though, does how the code ends up getting changed make sense after the post you just quoted? "No," is an acceptable answer but I
did ask because I actually wanted to know.)
Quote:
Is there another example about branching................?
Probably not! I'll probably give you the old examples and the old assignments again once I'm sure you understand about the PC and labels. We're not skipping branching. We're handling the prerequisite knowledge for branching.
Kasumi wrote:
Just to note something: From now on, I'm going to be writing way less. I'm gonna take advantage of the format of having you reply. Why risk writing a long document when I can just write parts at a time and immediately course correct for understanding?
So, remember that literally all the Program Counter does it keep track of the address of the next instruction to run. The "Step" button in easy6502 runs exactly one instruction. With these two pieces of knowledge, that assignment should be complete-able.
(Seriously, though, does how the code ends up getting changed make sense after the post you just quoted? "No," is an acceptable answer but I
did ask because I actually wanted to know.)
Quote:
Is there another example about branching................?
Probably not! I'll probably give you the old examples and the old assignments again once I'm sure you understand about the PC and labels. We're not skipping branching. We're handling the prerequisite knowledge for branching.
No on the code changed making sense...
I don't like change, but we'll see if this less-write format would help more effectively than long-write like before.
Maybe I have to start drawing and show-and-tell to give examples of what I think or HOW it works. Like the quote I show:
Attachment:
83687ea12f0290b392644e7ae37d1b8a.jpg [ 93.68 KiB | Viewed 1598 times ]
Attachment:
index.jpg [ 7.34 KiB | Viewed 1598 times ]
...not sure if off-topic, but this would help encourage me to try to do different explanation in the future...
DocWaluigean wrote:
unregistered wrote:
Kasumi wrote:
You can see how long each version of each instruction will be in the documentation:
http://www.obelisk.me.uk/6502/reference.html#LDADocWaluigean, if you are scared by that site's design cause of its all-text-and-thin-table-lines ilk, than you share that fear with me. After finding the creator of the 6502 (MOS Technology)'s 6502 programming manual and printing out its Appendices it made finding the length of each instruction more fun for me.
starting at pdf page 204, I think, is where the MOS Technology helpful, to me at least, info starts. That's very kind, Unregistered. But It's more of how awfully dull it looks. There is no legend or meaning when looking through it. It's like looking at a map of California, but there's no bus, restaurant, city, etc. It's no soul or heart into trying to teach everyone who DEEPLY want to learn how to program 6502.
I mean sure, this IS advanced, and it's expected to give a sense of "low point of motivations" where 99% of beginners decide to quit, and stuff. But I don't ever want to be like those.
If I were to read it again, I maaay give different replies, but I don't ever want to offend anyone.
You aren't offending me.
There is a "legend" of sorts on page 204. It describes the meanings of each of the characters/symbols used in that Appendix. Obviously, it's not a detailed explanation; but, it was enough to make me have fun learning how to use that Appendix. When Kasumi, or someone else, talks about the high bytes, for instance, it was really fun and helpful for me to go to page 204, read the line where MOS Technology gives a symbol for "high byte", and then look through that Appendix to see how MOS Technology uses that symbol. It's not instantly useable, but the journey learning how that Appendix works was very fun for me.
And, it's a super helpful Appendix so I recommend it to you.
p.s. I didn't mention that the inclusion of lots of whitespace by MOS Technology is what makes their Appendix much better, for me, than the link Kasumi provided.
unregistered wrote:
You aren't offending me.
There is a "legend" of sorts on page 204. It describes the meanings of each of the characters/symbols used in that Appendix. Obviously, it's not a detailed explanation; but, it was enough to make me have fun learning how to use that Appendix. When Kasumi, or someone else, talks about the high bytes, for instance, it was really fun and helpful for me to go to page 204, read the line where MOS Technology gives a symbol for "high byte", and then look through that Appendix to see how MOS Technology uses that symbol. It's not instantly useable, but the journey learning how that Appendix works was very fun for me.
And, it's a super helpful Appendix so I recommend it to you.
p.s. I didn't mention that the inclusion of lots of whitespace by MOS Technology is what makes their Appendix much better, for me, than the link Kasumi provided.
Hmmm... you may have a point... but remember that I don't know completely on 6502 Assembly.
Also, reading an old code from decades past, on the timeline where C++ rules all just feels like insult and waste of time... I admit it's my ignorances about the fact that even people like you can read more better and more concentrated than I am, but like I said earlier, the fact that I understood BASIC, C# increasingly, Java, yet I can't understand 6502, just means something is wrong with lectures before I came here, and something is wrong with myself, Unregistered.
So soon for the lesson, I'll try to draw as alternative of my answers or explanations if I couldn't explain well about it. Thanks for the MOS guideline, though!
I gave an assignment. You did not complete, nor ask questions about the assignment. What should I say?
Kasumi wrote:
I gave an assignment. You did not complete, nor ask questions about the assignment. What should I say?
Wait what??? The assignment??? Where was it???
Kasumi wrote:
Just to note something: From now on, I'm going to be writing way less. I'm gonna take advantage of the format of having you reply. Why risk writing a long document when I can just write parts at a time and immediately course correct for understanding?
So, remember that literally all the Program Counter does is keep track of the address of the next instruction to run. The "Step" button in easy6502 runs exactly one instruction. With these two pieces of knowledge, that assignment should be complete-able.
(Seriously, though, does how the code ends up getting changed make sense after the post you just quoted? "No," is an acceptable answer but I
did ask because I actually wanted to know.)
Quote:
Is there another example about branching................?
Probably not! I'll probably give you the old examples and the old assignments again once I'm sure you understand about the PC and labels. We're not skipping branching. We're handling the prerequisite knowledge for branching.
This was the last reply. I didn't see any assignment?
I thought you were making a big assignment for days about the next one?????
Kasumi wrote:
Quote:
What do you mean? or why? You didn't told me we had to re-write or replace LDA with LDX.
I didn't tell you you had to replace LDA with LDX because you didn't have to do that. The code did it to itself.
I told you that in easy6502, your code starts at address $0600. This means the first opcode of the first instruction is at $0600. The code I gave you
writes to $0600 which changes what the first instruction is. Does that make sense?
Quote:
Or you never told me I need to disassemble...
You didn't need to disassemble, but I'm very glad you found that resource without me directing you to it. What I was hoping for is that you'd make the connection that since your code starts at $0600 and the program writes to $0600, that that might change the code. I left a bunch of hints about it in the post.
Anyway. Does it make sense now? Even if not, I guess I'm cool with it so long as you understand about how 6502 deals with addresses. Not every example is gonna land. If you wanna get back to branching, give me the address of all of these instructions, and tell me how you found those addresses. Edit: I guess I should say, assume the first one starts at $0600.
Code:
lda #$00
sta $0201
tay
lda $0200
Knowing the purpose of the PC should help.
THIS is the assignment?? I thought it was overview of what we learned while you said bingo???
There is a poor or big miscommunications here, and I'm lost right now.
It says, "Give me the address of all these instructions, and tell me how you found these addresses." How could it be overview?
Kasumi wrote:
It says, "Give me the address of all these instructions, and tell me how you found these addresses." How could it be overview?
If you have the same mindset as me, you'd understand about my random or unknown explanations and emotions. T-T And you'd understand struggling in life in my shoes, even forgetting it...
---
I'll see about all instructions you mentioned with address.
; PC=$0600
lda #$00 ; Put number 0 into Register A.
; PC=$0602
sta $0201 ; Place number 0 into Address Code $0201.
; PC=$0605
tay ; Copy-and-Paste number 0 from Register A into Register Y.
; PC=$0606
lda $0200 ; Put numbers contained inside Address Code $0200 into Register A. [WRONG!?]
; PC=$0609
DocWaluigean wrote:
If you have the same mindset as me, you'd understand about my random or unknown explanations and emotions. T-T And you'd understand struggling in life in my shoes, even forgetting it...
I say this with sympathy, but all I can do is offer content. If the content can't be understood because of a real mental block, I can't realistically help. I don't have the training for it. I understand you're trying really hard, but I don't have infinite time or patience.
I can't do this forever. You've got another week of this. Ideally I'd like to get you to a point where you'll know enough to get past the blocks you've had in other online resources. Let's try to get there. We're going to take very small steps.
I have other things I need the time for. This doesn't mean no more help from nesdev at large, nor does it necessarily mean I won't answer
any more questions, but I can't keep providing this level of attention forever.
---
Your answers are correct.
Except it's put the "number" from address $0200 into A, rather than the "numbers". It always is, and always will be just one 8 bit value.
Now it's time for labels again. All a label does is provide a name for the address of whatever byte is below it. So imagine there was a label above all the instructions I gave you.
Code:
label1:
lda #$00
label2:
sta $0201
label3:
tay
label4:
lda $0200
label5:
label1 is now a name for $0600.
label2 is now a name for $0602.
label3 is now a name for $0605.
label4 is now a name for $0606.
label5 is now a name for $0609.
As you can see, it matches what the Program Counter was when the 6502 CPU was about to run each instruction.
It's very simple, but just to prove you've got it, tell me what address each of the labels below would be a name for.
Code:
start:
ldx #$FF
afterload:
txa
aftertransfer:
tay
drawpixel:
stx $0200
changecolor:
inx
drawpixel2:
stx $0201
drawpixel3:
sty $0202
Use the format above for your answers.
"start" is now a name for ????
"afterload" is now a name for ???
etc.
DocWaluigean wrote:
unregistered wrote:
You aren't offending me.
There is a "legend" of sorts on page 204. It describes the meanings of each of the characters/symbols used in that Appendix. Obviously, it's not a detailed explanation; but, it was enough to make me have fun learning how to use that Appendix. When Kasumi, or someone else, talks about the high bytes, for instance, it was really fun and helpful for me to go to page 204, read the line where MOS Technology gives a symbol for "high byte", and then look through that Appendix to see how MOS Technology uses that symbol. It's not instantly useable, but the journey learning how that Appendix works was very fun for me.
And, it's a super helpful Appendix so I recommend it to you.
p.s. I didn't mention that the inclusion of lots of whitespace by MOS Technology is what makes their Appendix much better, for me, than the link Kasumi provided.
Hmmm... you may have a point... but remember that I don't know completely on 6502 Assembly.
I understand... I did say that that Appendix wouldn't be instantly useable.
DocWaluigean wrote:
Also, reading an old code from decades past, on the timeline where C++ rules all just feels like insult and waste of time... I admit it's my ignorances about the fact that even people like you can read more better and more concentrated than I am, but like I said earlier, the fact that I understood BASIC, C# increasingly, Java, yet I can't understand 6502, just means something is wrong with lectures before I came here, and something is wrong with myself, Unregistered.
Remember that MOS Technology created the 6502. This is their Appendix and yes, it's an old Appendix... but, it helped me to get more comfortable using concepts like "high byte" and it became so helpful to me after I became familiar with it and learned how to use it. 6502 assembly language requires you to problem solve tremendously. To start assembly problem solving you have to understand basic assembly concepts such as the addresses of instructions that Kasumi is helping you to learn. Assembly language is really powerful though (I explained why in a much earlier post in your thread). Something, at least, is wrong with everyone here... including me. I was diagnosed with Skitzophrenia and my medicine destroyed my brain but, now I'm doing much better!! PRAISE GOD!!
Never give up and keep applying yourself.
edit:
lumosity.com really helped and helps my brain. It's a brain training program where you spend money to sign up and then you are able to play all of their brain training games until your subscription expires... renew it just like a magazine subscription. It's run by
Lumos Labs and they just added "ity" to the end of "lumos". Pretty cool/creative and that is an easy way to remember the url.
Or if you have a Nintendo DS or Nintendo 3DS, you could buy used copies of Brain Age and Big Brain Academy.
Kasumi wrote:
DocWaluigean wrote:
If you have the same mindset as me, you'd understand about my random or unknown explanations and emotions. T-T And you'd understand struggling in life in my shoes, even forgetting it...
I say this with sympathy, but all I can do is offer content. If the content can't be understood because of a real mental block, I can't realistically help. I don't have the training for it. I understand you're trying really hard, but I don't have infinite time or patience.
I can't do this forever. You've got another week of this. Ideally I'd like to get you to a point where you'll know enough to get past the blocks you've had in other online resources. Let's try to get there. We're going to take very small steps.
I have other things I need the time for. This doesn't mean no more help from nesdev at large, nor does it necessarily mean I won't answer
any more questions, but I can't keep providing this level of attention forever.
---
Your answers are correct.
Except it's put the "number" from address $0200 into A, rather than the "numbers". It always is, and always will be just one 8 bit value.
Now it's time for labels again. All a label does is provide a name for the address of whatever byte is below it. So imagine there was a label above all the instructions I gave you.
Code:
label1:
lda #$00
label2:
sta $0201
label3:
tay
label4:
lda $0200
label5:
label1 is now a name for $0600.
label2 is now a name for $0602.
label3 is now a name for $0605.
label4 is now a name for $0606.
label5 is now a name for $0609.
As you can see, it matches what the Program Counter was when the 6502 CPU was about to run each instruction.
It's very simple, but just to prove you've got it, tell me what address each of the labels below would be a name for.
Code:
start:
ldx #$FF
afterload:
txa
aftertransfer:
tay
drawpixel:
stx $0200
changecolor:
inx
drawpixel2:
stx $0201
drawpixel3:
sty $0202
Use the format above for your answers.
"start" is now a name for ????
"afterload" is now a name for ???
etc.
I sadly understand, because your a living being, and your not a robot to do this forever. And as human beings, we all need some time for ourselves or for something far more important than lectures. So I guess I'm on my own again after 1 week? [
You've got another week of this.] Try and understand I had to take break for 2 days due to personal anxiety. I'm back but possibly calm to learn and listen.
I understand most of it is my fault, but I don't know more words to say....It's personal and off-topic to blur out like I did earlier post.
---
Code:
start: ; $0600
ldx #$FF ; $0602
afterload:
txa ; $0604
aftertransfer:
tay ; $0606
drawpixel:
stx $0200 ; $0609
changecolor:
inx ; $060B
drawpixel2:
stx $0201 ; $060D
drawpixel3:
sty $0202 ; $060F
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Address = 3 bytes. Opcodes = 2 bytes.
unregistered wrote:
DocWaluigean wrote:
unregistered wrote:
You aren't offending me.
There is a "legend" of sorts on page 204. It describes the meanings of each of the characters/symbols used in that Appendix. Obviously, it's not a detailed explanation; but, it was enough to make me have fun learning how to use that Appendix. When Kasumi, or someone else, talks about the high bytes, for instance, it was really fun and helpful for me to go to page 204, read the line where MOS Technology gives a symbol for "high byte", and then look through that Appendix to see how MOS Technology uses that symbol. It's not instantly useable, but the journey learning how that Appendix works was very fun for me.
And, it's a super helpful Appendix so I recommend it to you.
p.s. I didn't mention that the inclusion of lots of whitespace by MOS Technology is what makes their Appendix much better, for me, than the link Kasumi provided.
Hmmm... you may have a point... but remember that I don't know completely on 6502 Assembly.
I understand... I did say that that Appendix wouldn't be instantly useable.
DocWaluigean wrote:
Also, reading an old code from decades past, on the timeline where C++ rules all just feels like insult and waste of time... I admit it's my ignorances about the fact that even people like you can read more better and more concentrated than I am, but like I said earlier, the fact that I understood BASIC, C# increasingly, Java, yet I can't understand 6502, just means something is wrong with lectures before I came here, and something is wrong with myself, Unregistered.
Remember that MOS Technology created the 6502. This is their Appendix and yes, it's an old Appendix... but, it helped me to get more comfortable using concepts like "high byte" and it became so helpful to me after I became familiar with it and learned how to use it. 6502 assembly language requires you to problem solve tremendously. To start assembly problem solving you have to understand basic assembly concepts such as the addresses of instructions that Kasumi is helping you to learn. Assembly language is really powerful though (I explained why in a much earlier post in your thread). Something, at least, is wrong with everyone here... including me. I was diagnosed with Skitzophrenia and my medicine destroyed my brain but, now I'm doing much better!! PRAISE GOD!!
Never give up and keep applying yourself.
edit:
lumosity.com really helped and helps my brain. It's a brain training program where you spend money to sign up and then you are able to play all of their brain training games until your subscription expires... renew it just like a magazine subscription. It's run by
Lumos Labs and they just added "ity" to the end of "lumos". Pretty cool/creative and that is an easy way to remember the url.
That's kind of true, but here's the differences; I'm on maximum legal dose in US of Sertraline [200mg?]..and it did absolutely nothing on me. People kept saying I'm waay smarter than I think I am, yet I keep struggling with self-learning things like this. If I get tutor for a month on artist, expect my name as lead director of the best Disney 2D animated movies. That's how fast I can learn if the teachings is really good and on pace. Let's just say, "My mind is too stubborn to stop suffering over something stupid."
Also, thanks on never giving up! And praise God too.
P.S. I don't trust Lumosity who uses knowledges and brain training for monetary gains. I agree on Brain Age though.
You're only on your own if everyone else stops answering your questions. You simply no longer get the same level of attention from me. By "a week", I meant a week from that post. Can I extend this to account for the break? Well, we'll see based on progress I guess. But the date wasn't really chosen arbitrarily, there are things happening near the 18th in my life.
Your answers are not correct. A label provides a name for the address of the byte below. It takes up no space by itself. Also remember "step"'s function is to run a single instruction, only. Labels aren't instructions.
Code:
start:
someotherlabel:
test:
lda #$00
We've talked about how in easy6502 the address for the first byte of the first instruction is usually at $0600. There are only two bytes in the example above. One for the opcode for lda # (which specifies the CPU should load the accumulator with the 8 bit value following the opcode). One for the operand $00. This means the address for the opcode is $0600. (And the address for the operand is $0601.)
Labels provide a name for the address of the byte below.
The byte below "test" is the first byte of the first instruction.
So "test" is a name for $0600.
"test" is below "someotherlabel", but "test" is a label. Because labels don't take up space by themselves, the byte below "someotherlabel" is also the first byte of the first instruction.
So "someotherlabel" is a name for $0600 as well.
"test" and "someotherlabel" are both below "start". But since labels don't take up space by themselves, the byte below "start" is also the first byte of the first instruction.
So "start" is a name for $0600 as well.
All three labels in the above example refer to the same address. (The address of the first instruction.) Try the other exercise again. Realize while you step through that labels aren't instructions, and "step" only runs instructions. So think about which instruction is about to be run. Then think about what label is above that instruction. And then you will have the label's address from the PC.
Edit: To perhaps explain it simpler:
Code:
; $0600;The address for the next byte
start:
; $0600;The address for the next byte
ldx #$FF
afterload:
txa
aftertransfer:
tay
drawpixel:
stx $0200
changecolor:
inx
drawpixel2:
stx $0201
drawpixel3:
sty $0202
Both start AND ldx #$FF get the same address, because a label's purpose is only to give a name to something to make things easier on you as a programmer. The CPU is actually unaware of what labels were/are there, they don't exist at all in the program the CPU executes.
Edit: One more note. TXA/TAY/INX are only one byte. You can use step to avoid having to do the address math manually. It's not a test for whether you know the size of the instructions by heart. Step will tell you through the address in the PC, the assignment only tests if you understand how a label gets which address it names.
Edit more: You can label it like you did before since it did help me see where the errors were coming from. But please ALSO use the format in the post for your final answers like the post requested:
Quote:
label1 is now a name for $0600.
label2 is now a name for $0602.
label3 is now a name for $0605.
label4 is now a name for $0606.
label5 is now a name for $0609.
Use the format above for your answers.
"start" is now a name for ????
"afterload" is now a name for ???
etc.
Otherwise there's room for some ambiguity.
Code:
lda #$FF;$0602;Does this mean the address for lda #$FF is $0602? Or does it mean the address for the byte below lda #$FF is $0602?
It's possible your only errors were instruction size, but the ambiguity of the format you used is why I specifically requested the format that I did.
Kasumi wrote:
You're only on your own if everyone else stops answering your questions. You simply no longer get the same level of attention from me. By "a week", I meant a week from that post. Can I extend this to account for the break? Well, we'll see based on progress I guess. But the date wasn't really chosen arbitrarily, there are things happening near the 18th in my life.
Your answers are not correct. A label provides a name for the address of the byte below. It takes up no space by itself. Also remember "step"'s function is to run a single instruction, only. Labels aren't instructions.
Code:
start:
someotherlabel:
test:
lda #$00
We've talked about how in easy6502 the address for the first byte of the first instruction is usually at $0600. There are only two bytes in the example above. One for the opcode for lda # (which specifies the CPU should load the accumulator with the 8 bit value following the opcode). One for the operand $00. This means the address for the opcode is $0600. (And the address for the operand is $0601.)
Labels provide a name for the address of the byte below.
The byte below "test" is the first byte of the first instruction.
So "test" is a name for $0600.
"test" is below "someotherlabel", but "test" is a label. Because labels don't take up space by themselves, the byte below "someotherlabel" is also the first byte of the first instruction.
So "someotherlabel" is a name for $0600 as well.
"test" and "someotherlabel" are both below "start". But since labels don't take up space by themselves, the byte below "start" is also the first byte of the first instruction.
So "start" is a name for $0600 as well.
All three labels in the above example refer to the same address. (The address of the first instruction.) Try the other exercise again. Realize while you step through that labels aren't instructions, and "step" only runs instructions. So think about which instruction is about to be run. Then think about what label is above that instruction. And then you will have the label's address from the PC.
Edit: To perhaps explain it simpler:
Code:
; $0600;The address for the next byte
start:
; $0600;The address for the next byte
ldx #$FF
afterload:
txa
aftertransfer:
tay
drawpixel:
stx $0200
changecolor:
inx
drawpixel2:
stx $0201
drawpixel3:
sty $0202
Both start AND ldx #$FF get the same address, because a label's purpose is only to give a name to something to make things easier on you as a programmer. The CPU is actually unaware of what labels were/are there, they don't exist at all in the program the CPU executes.
Edit: One more note. TXA/TAY/INX are only one byte. You can use step to avoid having to do the address math manually. It's not a test for whether you know the size of the instructions by heart. Step will tell you through the address in the PC, the assignment only tests if you understand how a label gets which address it names.
Edit more: You can label it like you did before since it did help me see where the errors were coming from. But please ALSO use the format in the post for your final answers like the post requested:
Quote:
label1 is now a name for $0600.
label2 is now a name for $0602.
label3 is now a name for $0605.
label4 is now a name for $0606.
label5 is now a name for $0609.
Use the format above for your answers.
"start" is now a name for ????
"afterload" is now a name for ???
etc.
Otherwise there's room for some ambiguity.
Code:
lda #$FF;$0602;Does this mean the address for lda #$FF is $0602? Or does it mean the address for the byte below lda #$FF is $0602?
It's possible your only errors were instruction size, but the ambiguity of the format you used is why I specifically requested the format that I did.
Happy Birthday? Wedding? New job? But sadly, I understand and I got to take responsibility for my lack of progress on past few days...I may repeat myself, but yeah. Mindset wise.
Or maybe I misread it again.
-
If I get this one wrong, I'll see if I could draw to see what's going on.
[Or maybe I'll draw this time.]
So label is the same power as the comment? Or it's to save time when re-using the code like:
AERIAL-MARIO:
LDA #$01
INC #$5000
IF #$FF
DEC #$5000
STA AERIAL-MARIO #$3000
??????????????????
------
Code:
; HEX = $00-FF : Binary = %$0000 - 1111 : Immediate Decimal = #$00-FF <=== ?????
start: ; $0600 --If this was NES, would it always start at $0000?--
ldx #$FF ; $0602 = For HEX/Binary/number, it goes up by two. Because the opcode is stored into the assembly for the code to proceed, and the variables stored FOR/IN the opcode.
afterload: ; $0602 = Labels; not wasting space at all no matter what.
txa ; $0603 = [i]TXA/TAY/INX are only one byte. [/i]
aftertransfer: ; $0603 = Labels
tay ; $0604 = [i]TXA/TAY/INX are only one byte. [/i]
drawpixel: ; $0604 = Labels
stx $0200 ; $0607 = For Address Code, it goes up by three. Because also the opcode is stored into the assembly for the code to proceed. BUT the Address has two separated numbers: high-byte and low-byte.
changecolor: ; $0607 = Labels
inx ; $0609 = For HEX/Binary/number, it goes up by two. Because the opcode is stored into the assembly for the code to proceed, and the variables stored FOR/IN the opcode.
drawpixel2: ; $0609 = Labels
stx $0201 ; $060C = For Address Code, it goes up by three. Because also the opcode is stored into the assembly for the code to proceed. BUT the Address has two separated numbers: high-byte and low-byte.
drawpixel3: ; $060C = Labels
sty $0202 ; $060E = For Address Code, it goes up by three. Because also the opcode is stored into the assembly for the code to proceed. BUT the Address has two separated numbers: high-byte and low-byte.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Address = 3 bytes. Opcodes = 2 bytes. TXA/TAY/INX = 1 byte.
Edit: I'm removing the reply with the answers to some questions, I feel it's getting off track. (It is saved locally so I can answer your questions later.) I am trying to give you less information at once so there's less to digest and be confused by.
Please use the format I requested for the answers. Again, the format you used is ambiguous. It looks like there are still a couple of errors (but again, ambiguity, please use the requested format or BOTH, not just what was used in your last post!).
The requested format is fill in the blank:
"start" is now a name for ????
"afterload" is now a name for ????
"aftertransfer" is now a name for ????
"drawpixel" is now a name for ????
"changecolor" is now a name for ????
"drawpixel2" is now a name for ????
"drawpixel3" is now a name for ????
Fill in the ???? for each line with the correct address.
I think the errors are primarily because you're doing the address math manually? Just step and look at the Program Counter. You have no need to memorize how big instructions are. The program counter will automatically skip the right number of bytes and just tell you the address for the next instruction that will be run.
I guess it wasn't quite right to say labels don't take up space. Label definitions don't. If you put a name in your code followed by a colon (like changecolor:), you have defined a label. Label definitions are sort of like comments in that the CPU doesn't know they existed when it's running the code.
But labels can also be used in place of an address in an instruction. "lda label" takes the same amount of space as "lda $0200" (assuming label was the name for $0200). We'll get to why they're useful and lots of other stuff you asked later when we start to use the labels. For now, it's important to understand how they're defined.
Then we can use them.
Then we can jmp.
Then we can branch.
edit: cleaned up some other wording.
Code:
start: ; Name for $0600
ldx #$FF
afterload: ; Name for $0602
txa
aftertransfer: ; Name for $0603
tay
drawpixel: ; Name for $0604
stx $0200
changecolor: ; Name for $0607
inx
drawpixel2: ; Name for $0608
stx $0201
drawpixel3: ; Name for $060B
sty $0202
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Address = 3 bytes. Opcodes = 2 bytes. TXA/TAY/INX = 1 byte.
Correct. Now for JMP, a new instruction. I "skipped" JMP because I wanted to try to get you to more interesting things which you craved, but this was probably a mistake.
Remember when I described "TXA" as like "LDA X" in that it copies the value from X into A?
Well, "JMP" is like LDPC. It copies the address that follows it into the Program Counter. (Except it copies the actual address, not the value stored at that address.)
The Program Counter (PC) stores the address of the next instruction to run. So this instruction effectively tells the CPU to start executing code at a different address than the one immediately below the instruction (unless the address you provide IS the one immediately below the instruction!). It's basically directly equivalent to GOTO.
Here is a simple example. Step through this code:
Code:
inx
lda #$FF
If you keep clicking step for it, the PC will keep going up to new places in memory.
Now step through this code:
Code:
inx
jmp $0600
lda #$FF
The first click of step will run the inx. The next click of step will run jmp $0600.
JMP copies $0600 into the PC, like I just described. Since the PC contains the address for the next instruction that will be run, this means the next instruction that will be run when you next click step is the one at address $0600. (Which like we've covered a few times, is usually the first instruction in easy6502. So here it's inx.)
If you keep clicking step, X will increase by 1 every other time. inx, jmp $0600, inx, jmp $0600. Forever. This is called an "infinite loop." Unlike the inx example that had no jmp, the program counter never gets a value higher than $0601. In this case, the jmp sends it back to an earlier address before it can get that high. This means that lda #$FF below the jmp is never executed. The PC never reaches its address.
And now, we get to one use of labels:
Code:
start:
inx
jmp start
If you know what instruction you want to run next, you just put a label above it. Then you can jmp to the label. And then you never need to figure out (or even know) the actual address for that instruction. And you can even put instructions before the label, and not have to update the jmp. (You would have to update the jmp if it were an address, because putting things before inx would give it a higher address. By putting things above the label, the label will get a new address automatically. Then things that use the label will use the address from the label. This is why no updates are needed.)
Code:
ldx #$80
start:
inx
jmp start
With labels, we can now basically forget about numbered addresses for code for the rest of forever.
Your next assignment: Tell me which instruction will be run after each of these jmps:
Code:
jmp storecolor;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
Code:
jmp storezerotozero;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
Code:
jmp addtox;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
Finally, mark which instructions will NOT be run in the following code:
Code:
ldx #$FF
dex
jmp continue
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
continue:
dex
end:
Kasumi wrote:
Correct. Now for JMP, a new instruction. I "skipped" JMP because I wanted to try to get you to more interesting things which you craved, but this was probably a mistake.
Remember when I described "TXA" as like "LDA X" in that it copies the value from X into A?
Well, "JMP" is like LDPC. It copies the address that follows it into the Program Counter. (Except it copies the actual address, not the value stored at that address.)
The Program Counter (PC) stores the address of the next instruction to run. So this instruction effectively tells the CPU to start executing code at a different address than the one immediately below the instruction (unless the address you provide IS the one immediately below the instruction!). It's basically directly equivalent to GOTO.
Here is a simple example. Step through this code:
Code:
inx
lda #$FF
If you keep clicking step for it, the PC will keep going up to new places in memory.
Now step through this code:
Code:
inx
jmp $0600
lda #$FF
The first click of step will run the inx. The next click of step will run jmp $0600.
JMP copies $0600 into the PC, like I just described. Since the PC contains the address for the next instruction that will be run, this means the next instruction that will be run when you next click step is the one at address $0600. (Which like we've covered a few times, is usually the first instruction in easy6502. So here it's inx.)
If you keep clicking step, X will increase by 1 every other time. inx, jmp $0600, inx, jmp $0600. Forever. This is called an "infinite loop." Unlike the inx example that had no jmp, the program counter never gets a value higher than $0601. In this case, the jmp sends it back to an earlier address before it can get that high. This means that lda #$FF below the jmp is never executed. The PC never reaches its address.
And now, we get to one use of labels:
Code:
start:
inx
jmp start
If you know what instruction you want to run next, you just put a label above it. Then you can jmp to the label. And then you never need to figure out (or even know) the actual address for that instruction. And you can even put instructions before the label, and not have to update the jmp. (You would have to update the jmp if it were an address, because putting things before inx would give it a higher address. By putting things above the label, the label will get a new address automatically. Then things that use the label will use the address from the label. This is why no updates are needed.)
Code:
ldx #$80
start:
inx
jmp start
With labels, we can now basically forget about numbered addresses for code for the rest of forever.
Your next assignment: Tell me which instruction will be run after each of these jmps:
Code:
jmp storecolor;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
Code:
jmp storezerotozero;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
Code:
jmp addtox;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
Finally, mark which instructions will NOT be run in the following code:
Code:
ldx #$FF
dex
jmp continue
storecolor:
lda #$01
sta $0200
jmp end
addtox:
inx
continue:
dex
end:
FINALLY a good one. This might be fun!
====================1======================
So JMP = "Go Directly To" "[Address/Labels/???]
Code:
jmp storecolor; Which instruction will be run after this jmp runs?
storecolor: ; The destination of where JMP wants from the first line!
lda #$01
sta $0200
jmp end ; Go directly to "end" label.
addtox:
inx
jmp end ; Go directly to "end" label.
storezerotozero:
lda #$00
sta $0000
end:
=======================2====================
Code:
jmp storezerotozero;Which instruction will be run after this jmp runs?
storecolor: ; label. [It's ignored because JMP's fault.]
lda #$01
sta $0200
jmp end
addtox:
inx
jmp end
storezerotozero: ; The destination where JMP wants from first line!
lda #$00
sta $0000
end:
======================3======================
Code:
jmp addtox;Which instruction will be run after this jmp runs?
storecolor:
lda #$01
sta $0200
jmp end
addtox: ; The destination of where the JMP wants you to go from first line!
inx
jmp end
storezerotozero:
lda #$00
sta $0000
end:
======================4=========================
Ooooohoohooohoohoo, you trying to trick me, huh?!
Code:
ldx #$FF ; Load number 255 into Register X
dex ; decrement / subtract 1 from Register X.
jmp continue ; Go directly to "continue" label.
storecolor: ; IGNORE!!! ALL CODE IN STORECOLOR IS A BAD BOY!
lda #$01 ;IGNORE!!!
sta $0200 ;IGNORE!!!
jmp end ;IGNORE!!!
addtox: ;IGNORE!!!
inx ;IGNORE!!!
continue: The destination where JMP wants you to go!
dex ; decrement / subtract 1 from Register X.
end: ; label. Nothing happens.
And again, all correct! Seems you're getting this. It's really is mostly simple, small pieces you just have to not overthink it. Though there are some complicated things upcoming.
Let's get back to branching. If this post sounds familiar, it's because it's actually mostly copy-pasted from the last post.
BEQ is Branch on EQual (to zero). It will jmp ("branch") to the address/label specified after the BEQ instruction if the zero flag is set. Otherwise, it will go to the next instruction like we've gotten used to happening.
This means if the zero flag is set when the instruction is run, it is equivalent to jmp. (Except... for an exception we'll get to.)
Otherwise, it decides to do nothing and the instruction below it will be run next.
Here is a simple example:
Code:
restart:
lda #$00;This sets the zero flag
beq restart
lda #$FF
Now step through the code above and watch the Program Counter. It will start at $0600. (the address for lda #$00). Then it will go to $0602 (the address for beq restart). But if you step again, something new happens! Rather than get higher, it goes back to $0600! Keep stepping and it will alternate between $0600 and $0602! The lda #$FF will never be reached or executed by the CPU.
The above example sets the zero flag by loading zero, then follows it with a branch that triggers if the zero flag is set. Because the zero flag is set, it goes to the address specified, effectively restarting the program. That demonstrated how BEQ is like JMP when the zero flag is set.
Let's modify that example slightly.
Code:
restart:
lda #$80;This clears the zero flag
beq restart
lda #$FF
Step through that one. The PC starts at $0600 (lda #$80) like before. It goes to $0602 (beq restart) like before. But stepping again DOES continue to go up. It goes to $0604 (lda #$FF). This time, the lda #$FF is reached. That example demonstrates how it goes to the next instruction when the zero flag is clear.
BNE is Branch if Not Equal (to zero). It will jmp ("branch") to the address/label specified after the BNE instruction if the zero flag is clear. Otherwise, it will go to the next instruction like how most other instructions work.
Let's try it in the example code, in place of BEQ.
Code:
restart:
lda #$00;This sets the zero flag
bne restart
lda #$FF
This does NOT branch, and the lda #$FF IS reached because bne branches when the zero flag is clear, and beq branches when the zero flag is set.
Code:
restart:
lda #$80;This clears the zero flag
bne restart
lda #$FF
This DOES branch, and the lda #$FF is NOT reached.
One more note: You can branch forward. (Just like you can jmp forward.)
Code:
lda #$FF;The zero flag is clear
bne skip;Because the zero flag is clear, we branch to the skip label
lda #$04;This is never executed
skip:
Your assignment is to comment each branch with whether or not it will branch, and why. Also mark any code the CPU will never execute (get to).
Code:
restart:
ldx #$00
inx
beq restart
dex
bne restart
beq skip
lda #$00
beq restart
skip:
Code:
restart:
ldy #$04
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
I'll end with this. You technically have all the information you need to write a program that adds two numbers. (Granted, there's a way better way to do it with things you do not yet know!) The last example (with all the dey instructions) is a part of the key. Do you notice any correspondence between the value Y starts with and how it ends up branching? Count some things!
And now, think about how you might write a program that adds the number in X and the number in Y together, and stores the result in $00. Assume the values you'll be adding will be 1, 2, 3, or 4. So before your code would be
Code:
ldx #$??
ldy #$??
;Your code here
Where each ?? could be any of those 4 values. Your program would store the added result in $00. So if your program was given:
Code:
ldx #$03
ldy #$01
;Your code here
After "Your code here" runs, #$04 would be held by ram location $00.
The adding numbers it not a
required assignment to complete. It's actually pretty difficult. But I do want you to give it some serious thought. Reason about it. You do know all the tools needed complete the task. Even if you don't get it, write out some things you thought about or tried.
(And again, for the technically minded reading, yes, I realize some ways this might be solved and it's why I'm limiting the input to 1, 2, 3 and 4 and leaving 0 out of the picture so as not to make the code super tedious to write even for the "larger" solutions.)
Since the adding numbers task is difficult, I will leave you some KING SIZE hints. You know how to set the value stored in an address to a specific value. And you know how to add one to the value stored inside an address. So the only thing you have to figure out is how to add one to address a specific number of times.
(PS, I won't be around too much for tonight, but this gives you time to reason about the number adding exercise.)
DocWaluigean wrote:
That's kind of true,
I was going to say I was only speaking truth about my life but, now I realize that you ment, "That's kind of true about me,"
DocWaluigean wrote:
Also, thanks on never giving up! And praise God too.
You're welcome.
And
DocWaluigean wrote:
P.S. I don't trust Lumosity who uses knowledges and brain training for monetary gains. I agree on Brain Age though.
Lumos Labs spent and spends lots of time creating the many brain training games that improve my brain. They also bought and maintain the countless servers that allow Lumosity users all over the world to log in and train their brains daily, if people want to. They created LPI Lumosity Points Index which is a number that helps each user to know how well their brain is doing. They employ a help center staff that answers questions. It's a pretty extravagant outreach to help us improve our brains and it's very helpful and so much fun, for me, so I am more than happy to spend the subscription fee. That's why I recommend the service.
Brain Age is cheaper, but, for me, it's like eating sand. Sand is not nutritious for me. I seriously hope Brain Age helps you tons more than it helped me.
And it could, I guess, cause I've been playing Lumosity and haven't played Brain Age in many years.
eoLumosity talk.
Kasumi wrote:
And again, all correct! Seems you're getting this. It's really is mostly simple, small pieces you just have to not overthink it. Though there are some complicated things upcoming.
Let's get back to branching. If this post sounds familiar, it's because it's actually mostly copy-pasted from the last post.
BEQ is Branch on EQual (to zero). It will jmp ("branch") to the address/label specified after the BEQ instruction if the zero flag is set. Otherwise, it will go to the next instruction like we've gotten used to happening.
This means if the zero flag is set when the instruction is run, it is equivalent to jmp. (Except... for an exception we'll get to.)
Otherwise, it decides to do nothing and the instruction below it will be run next.
Here is a simple example:
Code:
restart:
lda #$00;This sets the zero flag
beq restart
lda #$FF
Now step through the code above and watch the Program Counter. It will start at $0600. (the address for lda #$00). Then it will go to $0602 (the address for beq restart). But if you step again, something new happens! Rather than get higher, it goes back to $0600! Keep stepping and it will alternate between $0600 and $0602! The lda #$FF will never be reached or executed by the CPU.
The above example sets the zero flag by loading zero, then follows it with a branch that triggers if the zero flag is set. Because the zero flag is set, it goes to the address specified, effectively restarting the program. That demonstrated how BEQ is like JMP when the zero flag is set.
Let's modify that example slightly.
Code:
restart:
lda #$80;This clears the zero flag
beq restart
lda #$FF
Step through that one. The PC starts at $0600 (lda #$80) like before. It goes to $0602 (beq restart) like before. But stepping again DOES continue to go up. It goes to $0604 (lda #$FF). This time, the lda #$FF is reached. That example demonstrates how it goes to the next instruction when the zero flag is clear.
BNE is Branch if Not Equal (to zero). It will jmp ("branch") to the address/label specified after the BNE instruction if the zero flag is clear. Otherwise, it will go to the next instruction like how most other instructions work.
Let's try it in the example code, in place of BEQ.
Code:
restart:
lda #$00;This sets the zero flag
bne restart
lda #$FF
This does NOT branch, and the lda #$FF IS reached because bne branches when the zero flag is clear, and beq branches when the zero flag is set.
Code:
restart:
lda #$80;This clears the zero flag
bne restart
lda #$FF
This DOES branch, and the lda #$FF is NOT reached.
One more note: You can branch forward. (Just like you can jmp forward.)
Code:
lda #$FF;The zero flag is clear
bne skip;Because the zero flag is clear, we branch to the skip label
lda #$04;This is never executed
skip:
Your assignment is to comment each branch with whether or not it will branch, and why. Also mark any code the CPU will never execute (get to).
Code:
restart:
ldx #$00
inx
beq restart
dex
bne restart
beq skip
lda #$00
beq restart
skip:
Code:
restart:
ldy #$04
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
dey
beq restart
I'll end with this. You technically have all the information you need to write a program that adds two numbers. (Granted, there's a way better way to do it with things you do not yet know!) The last example (with all the dey instructions) is a part of the key. Do you notice any correspondence between the value Y starts with and how it ends up branching? Count some things!
And now, think about how you might write a program that adds the number in X and the number in Y together, and stores the result in $00. Assume the values you'll be adding will be 1, 2, 3, or 4. So before your code would be
Code:
ldx #$??
ldy #$??
;Your code here
Where each ?? could be any of those 4 values. Your program would store the added result in $00. So if your program was given:
Code:
ldx #$03
ldy #$01
;Your code here
After "Your code here" runs, #$04 would be held by ram location $00.
The adding numbers it not a
required assignment to complete. It's actually pretty difficult. But I do want you to give it some serious thought. Reason about it. You do know all the tools needed complete the task. Even if you don't get it, write out some things you thought about or tried.
(And again, for the technically minded reading, yes, I realize some ways this might be solved and it's why I'm limiting the input to 1, 2, 3 and 4 and leaving 0 out of the picture so as not to make the code super tedious to write even for the "larger" solutions.)
Since the adding numbers task is difficult, I will leave you some KING SIZE hints. You know how to set the value stored in an address to a specific value. And you know how to add one to the value stored inside an address. So the only thing you have to figure out is how to add one to address a specific number of times.
(PS, I won't be around too much for tonight, but this gives you time to reason about the number adding exercise.)
I wasn't here few days ago because I had therapy and other big personal assistance that needed me.
---------1---------
Code:
restart:
ldx #$00 ; Put 0 into Register X; Zero Flag turn on.
inx ; Add 1 into Register X; now Zero Flag turn off.
beq restart ; Zero Flag is not on, this does NOTHING.
dex ; Subtract 1 from Register X; now Zero Flag turns on.
bne restart ; Zero Flag is turn on, this also does NOTHING.
beq skip ; Zero Flag is turn on; this means, "Go Directly to label "skip"!
;---WORTHLESS---;
lda #$00 ; Load 0 into Register A.
beq restart ; Go to restart label if the Zero Flag is turned on.
;---WORTHLESS---;
skip:
-----------------2-----------------
Code:
restart:
ldy #$04 ; Load, or put, number 4 into Register Y.
dey ; Decrement, or subtract 1, from Register Y.
;Now Y = 3
beq restart ; Ignored, because Zero Flag is turned off. [Y = 4 does NOT work for BEQ. As 4 != 0, or 4 not equal to zero.]
dey ; Decrement, or subtract 1, from Register Y...Again.
; Y = 2
beq restart ; Ignored, because Zero Flag is turned off. [2 != 0]
dey ; Subtract 1 from Register Y.
beq restart ; Ignored; 1 != 0.
dey ; Subtract 1 from Register Y.
; Y = 0, so the Zero Flag is turned on.
beq restart ; Because the Zero Flag is turned on, BEQ now works : Go directly to label "restart".
;Y = 0 = 0 = Y
;---WORTHLESS---;
dey ; Subtract 1 from Register Y.
beq restart ; If Zero Flag is turned on, go directly to label "restart."
;---WORTHLESS---;
This is going to be VERY interesting to make cartoons to teach people, and kids, about this programming.
unregistered wrote:
DocWaluigean wrote:
That's kind of true,
I was going to say I was only speaking truth about my life but, now I realize that you ment, "That's kind of true about me,"
DocWaluigean wrote:
Also, thanks on never giving up! And praise God too.
You're welcome.
And
DocWaluigean wrote:
P.S. I don't trust Lumosity who uses knowledges and brain training for monetary gains. I agree on Brain Age though.
Lumos Labs spent and spends lots of time creating the many brain training games that improve my brain. They also bought and maintain the countless servers that allow Lumosity users all over the world to log in and train their brains daily, if people want to. They created LPI Lumosity Points Index which is a number that helps each user to know how well their brain is doing. They employ a help center staff that answers questions. It's a pretty extravagant outreach to help us improve our brains and it's very helpful and so much fun, for me, so I am more than happy to spend the subscription fee. That's why I recommend the service.
Brain Age is cheaper, but, for me, it's like eating sand. Sand is not nutritious for me. I seriously hope Brain Age helps you tons more than it helped me.
And it could, I guess, cause I've been playing Lumosity and haven't played Brain Age in many years.
eoLumosity talk.
Ya didn't mention the sandwich, did ya?
Also, there's a question I got for you:
Imagine a world without free knowledge. Would you love it?It's good there's Lumosity about it, but it's also bad making profit by forces about it excluding free trials when it should really help the people instead.
Let see if I got at least 99% right on it...
*********************************************************************************************************
*********************************************************************************************************
*********************************************************************************************************
The limitations of 6502 CPU is 255. The HEX version is FF. The Binary version is 1111 1111 [or 11111111. Space in the middle helps a little?]
The number system in this style is wheels. It means if you go over 255, it will go back to 0.
6502 } 255 + 2 = 001.
It's the same thing in backwards. If you go below 0, it will go back to 255.
6502 } 3 - 5 = 254.
... 253, 254, 255, 0, 1, 2, ...
... 3, 2, 1, 0, 255, 254, 253, ...
Works either way.
The code line is always read from TOP to BOTTOM.
-------------------------
-------------------------
-------------------------
Any number / digit / variable / value = N
The "lever", or on [1] and off [0] = B
HEX number written >>> #$NN
Normal Number / Immediate Decimals number written >>> #NN
Binary number written >>> %$BBBBBBBB
Immediate Decimals Minimum Written = #N
Maximum usages Maximum Written = #NNN
----------
The Address [The location, destination, and objective of the code] >>> $NNNN
$NN = $00NN
$NNN = $0NNN
$N = 000N
$NNNN = $NNNN
The zeros is not used, while N is.
--------------------------
--------------------------
--------------------------
A label is a type of directive that makes it easier to go "back in time", or go directly to the label that's in the future OR the past of the codings using JMP/BEQ/BNE.
======EXAMPLES=====
cupcakes:
LDA $03
pancakes:
LDA $05
toilet:
LDA $FF
STA $FFFF
--
Think of something like a magical teleportation pod that said "@GOTO" with the name of the label in front of it. Except a little different.
***
A comment is a type of extremely simple code used to organize things. No matter how much you write in this, it will never be operated nor used inside the comment.
It's always a comment when it's after the [ ; ] symbol.
===EXAMPLES===
LDA $01 ; Yo man. Wanna go to a stag party?
LDX $02 ; Sounds dope, bruh! I hope I can bring some grasses in!
LDY $03 ; I happen to be a vegetarian! I'm so offended you mention grasses; my Dad was a tree trunk!
=============
All the hilarious comments above will never be implemented into the code. So write whatever you want.
--------------------------
--------------------------
--------------------------
Register is simple number carrying system with fancy name that holds number, awaiting for commands to be replaced, or to placed.
The numbers never disappeared once assigned, or given a number, regardless. You always have to replace it to change the number/value/digit/variable.
With this, you can carry up to three numbers, maximum of 255 for each.
-----------
The limitations for each is:
A = You cannot increment, or fancy word of adding one, to the number stored into Register A directly. [INC/INX/INY] You have to do the INC to the Address that got the number from Register A to do that.
X/Y = You cannot transfer numbers from Register X and Y together. [TAX, TAY]
You can only transfer numbers from Y to A, and from X to A. But never X to Y and Y to X back again.
--------------------------
--------------------------
--------------------------
LDA / LDX / LDY - "Load Data into A/X/Y Register"
You put any number into the register A, X, or Y.
===EXAMPLE1===
LDA #$0F
STA $0001
---
A = 15 [The F number for HEX.]
"Put_Number_From_A_Into" Address-0001
The Address $0001 is now carrying number 15.
===EXAMPLE2===
LDX #13
STA $0030
---
X = 13
Address = 0030
The Address $0030 is now carrying number 13.
===EXAMPLE3===
LDY %#00001010
STA $13
---
Y = 10 [The number from Binary]
Address = 0013.
The Address $0013 is now carrying number 10.
--------------------------
--------------------------
--------------------------
TAX / TAY = Transfer Register A to X. or. Transfer Register A to Y.
TXA / TXY = Same thing as above, but other way.
Despite the name, the TXA/TXY/TAX/TAY copies the number from one register to another. It never loses its number, just copy.
If there is no program written in A/X/Y, nor any number placed into any Register, than it will copy to targeted Register as zero.
===EXAMPLE1===
LDA #$10
TAX
---
Register A is carrying number 15, or 10 in HEX number.
Register A has "transfer", or COPY, number 15 into Register X.
Right now, Register A and Register X has number 15 ready to be placed or replaced.
===EXAMPLE 2===
TAY
LDX #18
LDA #$FF
---
Register A has no number inside it, so it always has zero as default. As such, Register Y is now carrying number 0.
Register X is now carrying number 18.
Register A is now carrying 255 [FF in HEX number, the maximum for 8-bit.]
For this code:
A = 255
X = 18
Y = 0
===EXAMPLE 3===
LDA $01
TAX
TAY
LDY $05
TYA
---
Register A is now carrying number 1.
Register A is "copy and paste" number 1 for Register X ::: X is now carrying number 1.
Register A is also "copy and paste" number 1 for Register Y. ::: Y is also carrying number 1.
Register Y is being given number 5 to carry. Because Y already has number 1, it get's replaced and now it's number 5. ::: Y is now carrying number 5.
Register Y is "copying and paste" [TYA] number 5 for A.
A was carrying number 1, but as A is holding number 5 now, it replaces number 1 with number 5. ::: A is now carrying number 5 instead.
As a result from this ----
A = 5
X = 1
Y = 5
--------------------------
--------------------------
--------------------------
Increment - The smarty word for addition by one.
Decrement - The smarty word for subtraction from one.
INC / INX / INY = Increment, or add one, to the Address / Register X / Register Y.
***NOTICE***
For other programs, you could do INC STEP 2, INC STEP 5, to increment by addition of 2, or 5, or any number. Same thing with decrement.
But for 6502 Assembly, you can only do increment / decrement by 1.
************
===EXAMPLE1===
LDX #20
INX
---
X is now carrying number 20.
Increment X. Meaning you add by 1 to the X Register.
X is now carrying number 21.
===EXAMPLE2===
LDA $#0D
STA $0010
INC $0010
---
Put number 13 [D in HEX number] into Register A.
Store number 13 from Register A into Address $0010
Increment Address $0010 by one. It does NOT mean $0011! It only increments/decrements INSIDE the Address that the Register stored!
Address $0010 is now carrying 14.
===EXAMPLE3===
LDY #02
DEY
DEY
DEY
DEY
STY $1000
---
Put number 2 into Register Y.
Decrement Register Y FOUR times according to the code.
2 - 1 = 1
1 - 1 = 0
0 - 1 = 255
255 - 1 = 254
[The math is wrong, but it's right ONLY in 6502 CPU programming!]
Store number 254 from Register Y into Address $1000.
Now Address $1000 is holding number 254.
--------------------------
--------------------------
--------------------------
JMP = Jump.
This code will jump to any labels.
VERY simple, but can also be effective. An empty label will also work.
===EXAMPLES===
LDX $01
letsdoitagain:
INX
JMP letsdoitagain
---
Register X is now carrying number 1.
The label "letsdoitagain" is made.
Increment, or add 1, to Register X. Now carrying 2.
JMMP, [Jump] to the label letsdoitagain. Or in other words, "Go directly to the label named, "letsdoitagain" !!!"
You are now on the label "letsdoitagain".
Increment Register X, now carrying 3.
Jump to, or go to, the label "letsdoitagain".
IT NEVER ENDS!!!!!!!!
Your branch answers are correct. No thoughts on the number adding exercise?! Well, read on.
Quote:
Binary number written >>> %$BBBBBBBB
It's '%'. (Usually. Many things depend on which assembler you use.)
easy6502 doesn't support binary at all, as far as I know.
'$' = hexadecimal.
'%' = binary.
Neither = decimal.
If you use '#' you want the value. If you leave out the '#' it's an address.
Quote:
than it will copy to targeted Register as zero.
True in easy6502. Not really true in any other context, so do not rely on this. Never rely on any values in RAM/Addresses/Registers or otherwise that you didn't put there yourself, and that aren't a documented part of the hardware. Don't transfer from X without putting a known value there first, for example. Don't rely on RAM to be zero unless you are sure you stored zero there beforehand.
Some examples have read and copied from things without writing there first, but only so the focus could be on addresses rather than the values themselves.
Quote:
Register A is carrying number 15, or 10 in HEX number.
$10 = 16, not 15.
Quote:
===EXAMPLE 3===
LDA $01
TAX
TAY
LDY $05
TYA
---
Register A is now carrying number 1.
No. It's carrying the value inside address 1.
Quote:
Register Y is being given number 5 to carry. Because Y already has number 1, it get's replaced and now it's number 5. ::: Y is now carrying number 5.
Also no. It's carrying the value inside address 5. If you don't precede the number with a '#' it's an address.
Quote:
LDA $#0D
'#' has to be used before the '$'.
#$, not $#.
Quote:
LDX $01
letsdoitagain:
INX
JMP letsdoitagain
---
Register X is now carrying number 1.
Nope, it's carrying the value inside address 1. I'm drilling this into your head now, it creates some obscure bugs if you don't get used to using # when you want to load a value rather than from an address.
I'm not sure I caught every error, but you totally do get it even if there are mistakes.
Anyway, next up is a new addressing mode (and a really tiny crash course on loops). We're finally getting back to the face. It's been a while, yeah?
Very early on, I mentioned how one of the differences between the registers are which instructions and addressing modes are available. And that some addressing modes wouldn't make sense for some registers. (Or, at least. I think I did! I'm not gonna look for it.)
We've done quite a lot with Absolute Addressing. That's lda $0000 or sta $0000. It deals with the value stored at the given address.
The next thing is, again, very simple. Absolute,x and Absolute,y addressing. They deal with the value stored in the address that is X or Y places away from the given address.
The syntax is LDA $????,x for absolute,x and LDA $????,y for absolute,y.
If X is zero, the result of absolute,x will be essentially identical to absolute addressing.
If Y is zero, the result of absolute,y will be essentially identical to absolute addressing.
Code:
ldx #$00
ldy #$00
lda $0200;Fetch the value from address $0200.
lda $0200,x;Fetch the value from address $0200+x. Since X is 0, and $0200+0=$0200
;It will still fetch the value from address $0200.
lda $0201;Fetch the value fom address $0201.
lda $0201,y;Fetch the value from address $0201+y. Since Y is 0, and $0201+0=$0201
;It will still fetch the value from address $0201.
The magic happens when X or Y is not zero when you use the corresponding addressing mode.
I'll pause here to make one thing clear here. X or Y is added to the address itself, and then that address is used to get the actual value. X or Y is NOT added to the actual value stored inside the address.
Code:
lda #$0F
sta $0200
lda #$02
sta $0201
lda #$08
sta $0202
ldx #1
lda $0200,x;A now holds the value 2. $0200+X (which holds 1) is $0201. Inside $0201 is #$02
inx;Now X = 2
lda $0200,x;A now holds the value 8. $0200+X (which holds 2) is $0202. Inside $0201 is #$08
Note that wrapping at 255 does NOT apply to the addition or X or Y to the address in this context.
Code:
lda #$0B
sta $0300
ldy #$01
lda $02FF,y;$02FF+Y (which holds 1) is $0300. Inside $0300 is #$0B. So now A holds #$0B
So perhaps now you see one of the reasons for multiple registers. And also why they're slightly different. It'd be a bit weird to do LDY $0200,Y, but you can do LDY $0200,X.
What is this addressing mode useful for? It allows you to access data that is grouped in addresses. Remember how the pixels in easy6502 are in sequential addresses? Check out this code.
Code:
lda #$02
ldx #$00
loop:
sta $0200,x
inx
bne loop
This makes 256 pixels of the screen red in easy6502. With your previous knowledge, you would have had to write 256 writes to do that. One for each pixel. Here there's only one write, used for all 256 pixels.
How does it work?
It gets the color to draw with in A.
It starts X with the value 0.
It stores the value in A to $0200+x, which colors one pixel red.
Then in adds one to X. Because 1 is not zero, it goes back to the loop label.
It stores the value in A to $0200+x. But because this time X is 1 and not zero, it is coloring a different pixel than before.
It does 256 pixels because eventually X gets to 255. The inx will then make it zero. And then the branch won't go to the label and the program ends.
This concept is a "loop" in programming. It's one of the fundamental concepts. They are usually set up to do the same (or nearly) the same operation on slightly different pieces of data.
And you may have already noticed how this will tie back to the face.
this postContains your code for the face. Any horizontal line can be done with a loop.
Let's take a look at how to turn your top horizontal line code:
Code:
lda #$04
sta $0200
sta $0201
sta $0202
sta $0203
sta $0204
sta $0205
sta $0206
sta $0207
sta $0208
sta $0209
sta $020A
sta $020B
sta $020C
sta $020D
sta $020E
sta $020F
sta $0210
sta $0211
sta $0212
sta $0213
sta $0214
sta $0215
sta $0216
sta $0217
sta $0218
sta $0219
sta $021A
sta $021B
sta $021C
sta $021D
sta $021E
sta $021F
into a loop.
First, load X with how many pixels across the line is minus 1. (That is, if you want to draw 32 pixels, you must load X with 31). Then load A with the color you want. Then, store the value in A using absolute,x addressing (the address should be the one for the leftmost pixel in the horizontal line.) Then decrement X, and branch if not equal above the store. Immediately after the loop, store to the address of the leftmost pixel (using absolute addressing.)
Code:
lda #$04
ldx #$1F
toplineloop:
sta $0200,x
dex
bne toplineloop
sta $0200
Way shorter, yes? And to briefly explain this one. Imagine you want to draw a 2 pixel line.
You'd load X with 1. After a single dex, there wouldn't be a branch and you've only drawn one pixel. So you draw the next one after the loop. If you had loaded X with 2, it would take two dex before the branches would stop. ETC.
Your assignment this time is to convert ALL horizontal lines in your old face code to loops like this.
PS: Perhaps this helps with the adding numbers exercise?
To be honest, I'm not entirely sure what to cover next. Most of the remaining concepts get a little denser, and I'm not sure which is best to do first.
There's pointers. (The two hardest addressing modes. One of two, I have actually never used, so I wouldn't teach it. The other one is super useful, but hard to explain immediately how. It's abstract...)
There's addition/subtraction/comparing. (This is easyish to give a quick explanation to, but hard to
really cover.)
There's signed/unsigned numbers. (The above somewhat relies on this? Hmm...)
There's bitwise logic. (Easy so long as you don't overthink it)
And the stack. (easyish to give a quick explanation to, but hard to really cover...)
I'll think about it! I guess technically the addition circuit gives you the most fun tools, and starts to get meaty... and from there bitwise logic gets easier, with those then you'll know basically all the instructions.
DocWaluigean wrote:
unregistered wrote:
DocWaluigean wrote:
That's kind of true,
I was going to say I was only speaking truth about my life but, now I realize that you ment, "That's kind of true about me,"
DocWaluigean wrote:
Also, thanks on never giving up! And praise God too.
You're welcome.
And
DocWaluigean wrote:
P.S. I don't trust Lumosity who uses knowledges and brain training for monetary gains. I agree on Brain Age though.
Lumos Labs spent and spends lots of time creating the many brain training games that improve my brain. They also bought and maintain the countless servers that allow Lumosity users all over the world to log in and train their brains daily, if people want to. They created LPI Lumosity Points Index which is a number that helps each user to know how well their brain is doing. They employ a help center staff that answers questions. It's a pretty extravagant outreach to help us improve our brains and it's very helpful and so much fun, for me, so I am more than happy to spend the subscription fee. That's why I recommend the service.
Brain Age is cheaper, but, for me, it's like eating sand. Sand is not nutritious for me. I seriously hope Brain Age helps you tons more than it helped me.
And it could, I guess, cause I've been playing Lumosity and haven't played Brain Age in many years.
eoLumosity talk.
Ya didn't mention the sandwich, did ya?
Also, there's a question I got for you:
Imagine a world without free knowledge. Would you love it?It's good there's Lumosity about it, but it's also bad making profit by forces about it excluding free trials when it should really help the people instead.
Lumos Labs is a company; they provide a service; that service
does help many people.
People like my uncle, for instance, whose brain has improved. He has thanked me many times for introducing him to Lumosity. He says their service keeping all parts of his brain active helps him think more clearly when he needs it to... like when he runs his business/company, which provides service that helps people too. His business/company collects money too.
I used to have your mindset about Lumosity, but it vanished, for me, after being encouraged to think about this for a bit.
Sorry for looong time. You pretty much know why. It's bad luck days for me earlier.
Could you give me another examples or mnemonics about the ,x ,y stuff? I been reading it and I don't get it.
---
-So the ,x ,y situations is that it allows you to copy from one Address Code into another Address Code upon the directions of what 'Address Code + X/Y = 2ND Address Code'?
$0001 has 5
$0004 has 10
-
LDX #2
LDA $1, x ; === $0003 now has number 0
INX ; Making X = 3
LDA $0001, X ; Now copied number 5 from Address $0001 into the "additions of X locations", which means Address $0004 now is carrying number 5, replacing the previous number, 10.
-
I'm guessing I'm going to call it, "Map Comma" tech. Or "Sextant Comma" or "Charter Comma" or something that involves map and directions to Address. Maybe Compass Comma.
Been wondering if I should give every tech. new names so anyone can learn more easier with mnemonic or idioms.
Whenever it seems complicated, take a step back.
The mnemonic is separate from the addressing mode.
LDA always copies a new number into A. It reads, rather than writes. It does nothing else. So LDA absolutely anything will never change a value stored at an address. (Well... in some specific hardware cases a read can appear to change the value stored at an address, but it's something else. And the something else affects all reads, not just ,x or ,y ones. )
In LDA's case, the addressing mode specifies how to get the value to copy to A.
In STA's case, the addressing mode specifies how to get the address to write A's value to.
$???? is one addressing mode.
LDA $0000 means copy the value from $0000. $0000 is the "given address".
STA $0002 means write the value in A into address $0002. $0002 is the "given address".
Let's call the address that LDA ends up copying from/the address STA ends up writing to the "final address." In the $???? addressing mode, the given address and the final address are always the same.
The $????,x addressing mode lets you use an address that's X places from the given address (Address $????).
Like in
LDA $0001,x
$0001 is the given address, but what's in $0001 doesn't matter for the calucation of the final address. X is added to the given address' number itself ($0001 in the example) to get the final address, and then A gets the value stored at that final address as usual.
For STA, similarly, the value in A would get written to that final address.
If X is 0, the final address is the given address just like the $???? addressing mode. If X is 1, the final address is the given address + 1.
If X is 5, and the address is $0100, the final address is $0105 because $0100+5=$0105.
Code:
ldx #5
lda $0100,x
;will use the same address to get the value for A as
lda $0105
inx;Now X is 6
;So now
lda $0100,x
;will use the same address to get the value for A as
lda $0106
If X is 7 and the address is $02FF, the address used is $0306 because $02FF+7=$0306.
Code:
ldx #7
lda $02FF,x
;will use the same address to get the value for A as
lda $0306
dex;Now X is 6
lda $02FF,x
;will use the same address to get the value for A as
lda $0305
Kasumi wrote:
Whenever it seems complicated, take a step back.
The mnemonic is separate from the addressing mode.
LDA always copies a new number into A. It reads, rather than writes. It does nothing else. So LDA absolutely anything will never change a value stored at an address. (Well... in some specific hardware cases a read can appear to change the value stored at an address, but it's something else. And the something else affects all reads, not just ,x or ,y ones. )
In LDA's case, the addressing mode specifies how to get the value to copy to A.
In STA's case, the addressing mode specifies how to get the address to write A's value to.
$???? is one addressing mode.
LDA $0000 means copy the value from $0000. $0000 is the "given address".
STA $0002 means write the value in A into address $0002. $0002 is the "given address".
Let's call the address that LDA ends up copying from/the address STA ends up writing to the "final address." In the $???? addressing mode, the given address and the final address are always the same.
The $????,x addressing mode lets you use an address that's X places from the given address (Address $????).
Like in
LDA $0001,x
$0001 is the given address, but what's in $0001 doesn't matter for the calucation of the final address. X is added to the given address' number itself ($0001 in the example) to get the final address, and then A gets the value stored at that final address as usual.
For STA, similarly, the value in A would get written to that final address.
If X is 0, the final address is the given address just like the $???? addressing mode. If X is 1, the final address is the given address + 1.
If X is 5, and the address is $0100, the final address is $0105 because $0100+5=$0105.
Code:
ldx #5
lda $0100,x
;will use the same address to get the value for A as
lda $0105
inx;Now X is 6
;So now
lda $0100,x
;will use the same address to get the value for A as
lda $0106
If X is 7 and the address is $02FF, the address used is $0306 because $02FF+7=$0306.
Code:
ldx #7
lda $02FF,x
;will use the same address to get the value for A as
lda $0306
dex;Now X is 6
lda $02FF,x
;will use the same address to get the value for A as
lda $0305
LDA always copies a new number into A. It reads, rather than writes. It does nothing else. So LDA absolutely anything will never change a value stored at an address. (Well... in some specific hardware cases a read can appear to change the value stored at an address, but it's something else. And the something else affects all reads, not just ,x or ,y ones. )
In LDA's case, the addressing mode specifies how to get the value to copy to A.
In STA's case, the addressing mode specifies how to get the address to write A's value to.
$???? is one addressing mode.
LDA $0000 means copy the value from $0000. $0000 is the "given address".
STA $0002 means write the value in A into address $0002. $0002 is the "given address".Why does everything need to have complex explanation, when people like I could understand it more if the wording was much simpler? Re-reading in my calm mood, it's basically unnecessary-complex repeat of the early tutorials of what we learnt. Like I said earlier, it's more of a "Map Comma", "Carto-Comma" "Cartographic Comma" to me. If I somehow forgot and reread the previous post about Register, I'd understand it more than this...
=====
Code:
LDA #$04
LDX #$1F
TOPHAT1:
STA $0200, X
DEX
BNE TOPHAT1
SIDEHAT:
sta $0200
sta $0220
sta $023F
sta $0240
sta $025F
sta $0260
sta $027F
sta $0280
sta $029F
sta $02A0
sta $02BF
sta $02C0
sta $02DF
sta $02E0
sta $02FF
sta $0300
sta $031F
sta $0320
sta $033F
sta $0340
sta $035F
sta $0360
sta $037F
sta $0380
sta $039F
;-------
HATLOOP:
STA $03A0, X
DEX
BNE HATLOOP
I/easy6502/Nerdy Nights/whatever think way more about how to present information than I think you give us credit for. To be really frank, I do not think the simplest explanations are the ones that have had the most success here. "LDA will never change the value stored at an address." is a valid and simple response to your last post. I spent extra time presenting something I thought would be more helpful.
Remember that how I present the information in my posts is based on your posts. If I explain something again, reexamine if you really know it or just think you do because it means something you said implied to me that you didn't understand. If I thought you understood it, why would I spend time trying to explain it a different way especially after the 18th when I said I'd help much less?
Always think about this. "Why did they spend the time?" If ever you think an explanation is complex (and not just one of mine), it can be very helpful to think about what factors may have gone into deciding to spend more time to present the explanation that way. Often when someone thinks something can be made simpler, they're missing something. Flipping the perspective can help one realize the holes in one's understanding without needing to ask.
If you think you've got the concepts, then complete the assignment.
Kasumi wrote:
I/easy6502/Nerdy Nights/whatever think way more about how to present information than I think you give us credit for. To be really frank, I do not think the simplest explanations are the ones that have had the most success here. "LDA will never change the value stored at an address." is a valid and simple response to your last post. I spent extra time presenting something I thought would be more helpful.
Remember that how I present the information in my posts is based on your posts. If I explain something again, reexamine if you really know it or just think you do because it means something you said implied to me that you didn't understand. If I thought you understood it, why would I spend time trying to explain it a different way especially after the 18th when I said I'd help much less?
Always think about this. "Why did they spend the time?" If ever you think an explanation is complex (and not just one of mine), it can be very helpful to think about what factors may have gone into deciding to spend more time to present the explanation that way. Often when someone thinks something can be made simpler, they're missing something. Flipping the perspective can help one realize the holes in one's understanding without needing to ask.
If you think you've got the concepts, then complete the assignment.
I don't understand the concepts. There's an error I found which draws the entire line like paintbrush I submitted a while ago.
EDIT: Sorry for my behaviour though.
Help me help you. What specifically don't you understand about the concepts? Assume whenever I make a post, I feel I have already made it as simple and clear as I can.
So telling me the explanation is complicated is not really feedback I can use beyond trying to explain some different way which may not target the part you don't understand. If I reexplain addressing modes (which I've done in the the rest of the post), but your issue is with looping then no one has won. You've got to be specific about the issues you're having or I have to guess.
In the ,x addressing mode. X is treated as a number. The 16 bit address before the ,x (not the value stored in that address) is treated as a number. These two numbers are added together to get a new number. This new number is the address that gets used.
In LDA, the value from the new address is copied to A.
In STA, the value in A is stored to the new address.
Edit: To help you help me, with the descriptions above, look at the code examples. The behavior exactly matches. Which of the steps from which example gives you a result you do not fully understand? Walk through each step of what should happen. (X is added to the address. So the result in the example should be this.) And stop whenever your result following the steps is different than what I said the result should be. And then I'll try to explain that difference.
Edit2: Assuming the paintbrush error you described was in your last piece of code. Above the "TOPHAT1" label, you initialize X to 31. Then you use dex and bne in a loop together. This loops 31 times, because to get below the bne, X must be zero.
Above the "HATLOOP" label, you do not initialize X. This means it is still zero from after the TOPHAT1 loop. You still use dex and bne in a loop together. This loops 256 times, because to get below the bne, X must be zero.
It starts at 0. 1 is subtracted to get 255. 255 is not equal to zero, so it loops.
Then 254, etc.
Kasumi wrote:
Help me help you. What specifically don't you understand about the concepts? Assume whenever I make a post, I feel I have already made it as simple and clear as I can.
So telling me the explanation is complicated is not really feedback I can use beyond trying to explain some different way which may not target the part you don't understand. If I reexplain addressing modes (which I've done in the the rest of the post), but your issue is with looping then no one has won. You've got to be specific about the issues you're having or I have to guess.
In the ,x addressing mode. X is treated as a number. The 16 bit address before the ,x (not the value stored in that address) is treated as a number. These two numbers are added together to get a new number. This new number is the address that gets used.
In LDA, the value from the new address is copied to A.
In STA, the value in A is stored to the new address.
Edit: To help you help me, with the descriptions above, look at the code examples. The behavior exactly matches. Which of the steps from which example gives you a result you do not fully understand? Walk through each step of what should happen. (X is added to the address. So the result in the example should be this.) And stop whenever your result following the steps is different than what I said the result should be. And then I'll try to explain that difference.
Edit2: Assuming the paintbrush error you described was in your last piece of code. Above the "TOPHAT1" label, you initialize X to 31. Then you use dex and bne in a loop together. This loops 31 times, because to get below the bne, X must be zero.
Above the "HATLOOP" label, you do not initialize X. This means it is still zero from after the TOPHAT1 loop. You still use dex and bne in a loop together. This loops 256 times, because to get below the bne, X must be zero.
It starts at 0. 1 is subtracted to get 255. 255 is not equal to zero, so it loops.
Then 254, etc.
I'll try...
Code:
HATLOOP:
STA $03A0, X
DEX
BNE HATLOOP
On this part of code, as you did say it's exactly as it's exampled, it just colored it all in, but I am not sure how BNE is useful when I want to make a line in the middle of the number of the code instead from any number to zero. And I'm not sure how to write it in a way it can go vertically [up and down] instead of always left and right.
-
Is there any history or motivation about programming and 6502 beside the one posted before this? I want to force myself to be encouraged, but I keep feeling it's just myself, and it's not other stuff..
DocWaluigean wrote:
And I'm not sure how to write it in a way it can go vertically [up and down] instead of always left and right.
Drawing horizontally is easier because the screen is arranged in rows, so adding one goes one pixel to the right, subtracting one goes one pixel to the left. To move up and down, you need to skip an entire row. Each row is 32 pixels, so you need to add (to go down) or subtract (to go up) 32 to/from the current position in order to move vertically.
What makes this slightly more complicated is that the entire screen doesn't fit in 256 bytes (it's actually 1024 bytes), so you can't go everywhere using just one 8-bit index register (X or Y) as you can with horizontal lines.
The best way to do this would be to use indirect indexed addressing, but I'm not sure if you learned that yet. The basic idea is that the address to access is not in the instruction, it's in the memory location indicated by the instruction. That's why it's called "indirect".
LDA $0050, Y will load a byte from the address $0050+y, while
LDA ($50), Y will load a byte from the address formed by the numbers at $0050 and $0051, plus Y (e.g. if $0050 contains $07, $0051 contains $90, and Y contains $04,
LDA ($50), Y will read the byte at $9007 + $04 = $900B).
I'm not gonna show any code for drawing vertical lines because it might not be time for that yet, but keep in mind that it is somewhat more complex and will most likely require the new addressing mode I mentioned before (indirect indexed). It might be a good idea to make a subroutine to draw lines too, to encapsulate that complexity so that the code that does the drawing can remain simple, just making calls to this subroutine whenever a line is needed.
Quote:
as you did say it's exactly as it's exampled,
Except for the ldx #$1F above it. Like I said, you did not initialize X above the HATLOOP label.
Compare:
Code:
LDA #$04
LDX #$1F
TOPHAT1:
STA $0200, X
DEX
BNE TOPHAT1
to
Code:
HATLOOP:
STA $03A0, X
DEX
BNE HATLOOP
At the TOPHAT1 label, X is #$1F, so it draws 31 pixels.
At the HATLOOP label, X is #$00 (because it never changes after BNE TOPHAT1 doesn't branch), so it loops 256 times.
To fix it, add an ldx #$1F above the HATLOOP label.
Quote:
I am not sure how BNE is useful when I want to make a line in the middle of the number of the code instead from any number to zero.
Use an address that's the middle of a line. If X is 0, you get the given address. The given address doesn't have to be at the start of a line.
2 pixels starting from the top left corner:
Code:
LDA #$04;Color
LDX #$02;2 pixels
loop:
STA $0200, X
DEX
BNE loop
STA $0200;Do the last pixel
2 pixels starting from three pixels to the right of the top left corner.
Code:
LDA #$04;Color
LDX #$02;2 pixels
loop:
STA $0203, X
DEX
BNE loop
STA $0203;Do the last pixel
Tokumaru covered why vertical is trickier. This is why I assigned only horizontal lines since you don't yet have those concepts.
Quote:
I want to force myself to be encouraged
I may have said this before, but I feel like that's a backwards way to go about motivation. If you don't already have something that motivates you to learn, why are you learning it? Learning 6502 isn't the difference between getting a degree or not, or something like that. If what you want to use it for isn't motivating enough, you can stop or take a break or anything else. There are no consequences for stopping.
I only understand forcing motivation if it's to do something you don't want to do AND there are consequences for not doing it. Here you're no worse off if you stop for a day, for a week or forever.
Edit: If you learn the things vertical lines will require, you can actually start making a pixel "character" move around. But I make no commitment to teaching those things, I am still here because I felt it'd be pretty bad to not check the last assignment after the deadline.
Kasumi wrote:
Quote:
as you did say it's exactly as it's exampled,
Except for the ldx #$1F above it. Like I said, you did not initialize X above the HATLOOP label.
Compare:
Code:
LDA #$04
LDX #$1F
TOPHAT1:
STA $0200, X
DEX
BNE TOPHAT1
to
Code:
HATLOOP:
STA $03A0, X
DEX
BNE HATLOOP
At the TOPHAT1 label, X is #$1F, so it draws 31 pixels.
At the HATLOOP label, X is #$00 (because it never changes after BNE TOPHAT1 doesn't branch), so it loops 256 times.
To fix it, add an ldx #$1F above the HATLOOP label.
Quote:
I am not sure how BNE is useful when I want to make a line in the middle of the number of the code instead from any number to zero.
Use an address that's the middle of a line. If X is 0, you get the given address. The given address doesn't have to be at the start of a line.
2 pixels starting from the top left corner:
Code:
LDA #$04;Color
LDX #$02;2 pixels
loop:
STA $0200, X
DEX
BNE loop
STA $0200;Do the last pixel
2 pixels starting from three pixels to the right of the top left corner.
Code:
LDA #$04;Color
LDX #$02;2 pixels
loop:
STA $0203, X
DEX
BNE loop
STA $0203;Do the last pixel
Tokumaru covered why vertical is trickier. This is why I assigned only horizontal lines since you don't yet have those concepts.
Quote:
I want to force myself to be encouraged
I may have said this before, but I feel like that's a backwards way to go about motivation. If you don't already have something that motivates you to learn, why are you learning it? Learning 6502 isn't the difference between getting a degree or not, or something like that. If what you want to use it for isn't motivating enough, you can stop or take a break or anything else. There are no consequences for stopping.
I only understand forcing motivation if it's to do something you don't want to do AND there are consequences for not doing it. Here you're no worse off if you stop for a day, for a week or forever.
Edit: If you learn the things vertical lines will require, you can actually start making a pixel "character" move around. But I make no commitment to teaching those things, I am still here because I felt it'd be pretty bad to not check the last assignment after the deadline.
I'm not sure what you mean about motivation if I think way too hard.
I'm learning it because why not? I said before that when I saw DahrkDaiz, when I saw Shiru, then I saw NIKI homebrews about NES, along with NESMaker which I still can't do atm, it's a form of childhood reasons why I am still trying to learn; can't explain why I want to learn, but something in heart [originated from childhood] knows why I REALLY want to learn. Looking at DSi games like WarioWare: D.I.Y. graphics kind of helps me, then I remember about the lessons, which I still feel iffy about it.
After this lesson, can we learn about how to turn program on
from scratch with blank screen before we can go on to the next lesson? I don't want to feel like I'm learning only by reading, and then I feel I didn't code at all. I re-read about branching yesterday, and I understand way more, as I'm believing Unregistered was right.
So my question on the lecture:
-Do I ALWAYS have to put LDX #$## at the start of each? or Each label always reset if outside of the labels or the BME/BDA labels stuff?
[I'm re-reading this lesson, as it takes time a little since I keep getting different result like the code I show earlier.]
@DocWaluigean
If your goal is to make a nes game only then you don't need to write code in asm: you can write it in C too. This is a lot easier to write actually.
Even though I understand enough 6502 asm, I write my code in C and asm based on my need. For experimenting with the nes, you don't need asm, C is more than enough. Since you mention Shiru, most of his game were in C too so it's possible to write C only code and only write ASM when there is no other way.
So if you goal is only making game, asm is not required. Just my opinion, the rest is up to you. It will make you life a lot easier.
Banshaku wrote:
@DocWaluigean
If your goal is to make a nes game only then you don't need to write code in asm: you can write it in C too. This is a lot easier to write actually.
Even though I understand enough 6502 asm, I write my code in C and asm based on my need. For experimenting with the nes, you don't need asm, C is more than enough. Since you mention Shiru, most of his game were in C too so it's possible to write C only code and only write ASM when there is no other way.
So if you goal is only making game, asm is not required. Just my opinion, the rest is up to you. It will make you life a lot easier.
Since I'm complex to understand or explain [If you weren't reading the whole thread], I'll try to explain this:
When I see more what I could do with 6502 Assembly, I admire and value the code more and more as time progresses. If I change my learning desires, I would feel terrible losing my knowledge or wasting my skills from 6502 to C. I believe you when C is easier; there's C++, there's C# which is hybrid of Java, and the C code is often the answer for everyone who want's to, BY BASE, get started on learning to code. But for 6502, there aren't many good tutorials or really effective tutorials for people who is "down-to-earth" determined to try and pay attention and know how it works. [At least for me.]
What I see for 6502, that language is much more than a toy. Much more than Minecraft if on hypnosis attitude [Or like Steve Jobs when he stare at program and see extreme potentials.]
On usual random days of taking breaks, I see JP homebrews utilizing NES not just for games, but also for image slideshow, for music, for other things. Maybe I'm wrong because I haven't see image slideshows, but maybe I'm right if I saw the music-only programs made by NIKI/NIKKI.
Or I'm being delusional. Again. By saying the same thing earlier.
But to the point:
I would feel waste of time if I go to C/C++/C#, and 6502 is one of the least elementary-documented popular languages for homebrews, [at least for me], and I want to help out in any way to make it understand not just for me, but for all. If I want to learn C, I want to learn 6502 first to understand comparison. Alongside, I understand enough that it's too late for me to go back. Register, Program Counter, etc. I don't know why I feel avoidances on this assignment... Going to try and re-read it the third time. If I finally understood the Branching, I could finally understand this. I said earlier I don't want anyone going through what I've been through..
No problem
If you want to use 6502 asm only it's fine too. What I just meant is C could have been easier if you just want to make a game.
When you know enough 6502 you can try to use your 6502 with some C and that will be quite interesting to do! Knowing how 6502 and nes work is quite useful when you do C code so what you are learning is not wasted: it will be used later.
Kasumi wrote:
Help me help you. What specifically don't you understand about the concepts? Assume whenever I make a post, I feel I have already made it as simple and clear as I can.
So telling me the explanation is complicated is not really feedback I can use beyond trying to explain some different way which may not target the part you don't understand. If I reexplain addressing modes (which I've done in the the rest of the post), but your issue is with looping then no one has won. You've got to be specific about the issues you're having or I have to guess.
In the ,x addressing mode. X is treated as a number. The 16 bit address before the ,x (not the value stored in that address) is treated as a number. These two numbers are added together to get a new number. This new number is the address that gets used.
In LDA, the value from the new address is copied to A.
In STA, the value in A is stored to the new address.
Edit: To help you help me, with the descriptions above, look at the code examples. The behavior exactly matches. Which of the steps from which example gives you a result you do not fully understand? Walk through each step of what should happen. (X is added to the address. So the result in the example should be this.) And stop whenever your result following the steps is different than what I said the result should be. And then I'll try to explain that difference.
Edit2: Assuming the paintbrush error you described was in your last piece of code. Above the "TOPHAT1" label, you initialize X to 31. Then you use dex and bne in a loop together. This loops 31 times, because to get below the bne, X must be zero.
Above the "HATLOOP" label, you do not initialize X. This means it is still zero from after the TOPHAT1 loop. You still use dex and bne in a loop together. This loops 256 times, because to get below the bne, X must be zero.
It starts at 0. 1 is subtracted to get 255. 255 is not equal to zero, so it loops.
Then 254, etc.
-The Register limits added:
A : You
CANNOT use Register A for absolute effect! [Only X and Y can do it.]
A : You
CANNOT INCrement A directly!
A : ??????????
---
Code:
lda #$0F
sta $0200
lda #$02
sta $0201
lda #$08
sta $0202
ldx #1
lda $0200,x;A now holds the value 2. $0200+X (which holds 1) is $0201. Inside $0201 is #$02
inx;Now X = 2
lda $0200,x;A now holds the value 8. $0200+X (which holds 2) is $0202. Inside $0201 is #$08
-The Absolute Effect [Or The "
Compass-Comma" I made it up] is making certain codes that can potentially make it get treated like a file cabinet? The numbers in STA 200/1/2 is treated as a file cabinet, and when you did LDA 200,X which is 1, you "basically pull out the file cabinet box, and take the numbers that's stored into Address Code $0201, which is 2." And that result, Register A is now holding number 2?
-So yeah... it feels more of "Cabinet Comma" over "Compass-Comma" which is somewhat like go-to codings.. or the "Compass-Comma" is actually the BNE/BEQ...?
- I'm guessing I have to nickname each code name to make it easier. BNE would be,
"Begone, No-Equations!" [Meaning if it's number zero, it will "GO TO" the labels needed or loop back to the beignning of code / beginning of where label is, otherwise if it's OTHER than zero, it will pass like a door.]
-BEQ would be,
"Begone, Equated Quell!" [Meaning if it's any number that is not zero, it will "GO TO" to the labels needed or go back to the beginning of code / beginning of where label is. Otherwise, it will go through or pass like a door.]
The quell is, ironically, synonym of "contain" which is the best word for making it easier I guess. I'm also guessinf Equated is the same similar word of "Equations"???
=====
Way shorter, yes? And to briefly explain this one. Imagine you want to draw a 2 pixel line.
You'd load X with 1. After a single dex, there wouldn't be a branch and you've only drawn one pixel. So you draw the next one after the loop. If you had loaded X with 2, it would take two dex before the branches would stop. ETC.
Your assignment this time is to convert ALL horizontal lines in your old face code to loops like this.Re-reading it again, Oooooh. Just horizontal [at least most-horizontal lines] line of the code, not the entire thing... I hope this doesn't demotivate me if I didn't understand it.
But you see what I mean about names with BNE and BEQ. [[Come to think of it, I'm finally starting to recognize BNE or BEQ since I made up names. Every teacher should know this for elementary school if they keep asking to teach programming at young ages..]]
Banshaku wrote:
No problem
If you want to use 6502 asm only it's fine too. What I just meant is C could have been easier if you just want to make a game.
When you know enough 6502 you can try to use your 6502 with some C and that will be quite interesting to do! Knowing how 6502 and nes work is quite useful when you do C code so what you are learning is not wasted: it will be used later.
The C++/C#/C and 6502 hybrid would be the MOST amazing thing ever! ^^ But I don't know how yet sadly. Also, I seen far more than potentials to just use 6502 for games, so...yes?
If I want to make a game, I would use Game-Maker, Unreal / Unity, etc. And coding would be wayyy longer for me to learn C++ / C# / C if I'm going that road atm.
I don't know if I'm explaining right. It's a curse of mentalities. T-T But it would give insight if I know the differences of C / C++ / C# [Even though it's off-topic. but not sure how implemented and similarities it can be to put 6502 code languages into those.]
I don't know why no responses on other things that could help give insights; a lot of teachers in the past is willing to answer different questions that could help out students more. Being there for students even most ridiculous questions [at least in topic] raises confidences, curiosity, and trust....
But nvm. Here.
Code:
lda #$04
ldx #$1F
toplineloop:
sta $0200,x
dex
bne toplineloop
sta $0200
;===
sta $0220 ; Hat Vertically [Up/Down]
sta $023F
sta $0240
sta $025F
sta $0260
sta $027F
sta $0280
sta $029F
sta $02A0
sta $02BF
sta $02C0
sta $02DF
sta $02E0
sta $02FF
sta $0300
sta $031F
sta $0320
sta $033F
sta $0340
sta $035F
sta $0360
sta $037F
sta $0380
sta $039F
;==========
sta $03A0
sta $03A1
sta $03A2
sta $03A3
sta $03A4
sta $03A5
sta $03A6
sta $03BF
sta $03BE
sta $03BD
sta $03BC
sta $03BB
sta $03BA
sta $03B9
;=========
sta $0398
sta $0397
sta $0396
sta $0395
sta $0394
sta $0387
sta $0388
sta $0389
sta $038A
sta $038B
;=========
sta $0370
sta $0371
sta $0372
sta $0373
sta $036F
sta $036E
sta $036D
sta $036C
;========
ldx #$0D ; Eye Color Light Green Left
stx $038C
stx $03AC
stx $03CC
stx $03EC
ldy #$0E ; Eye Color Light Blue Right
sty $0393
sty $03B3
sty $03D3
sty $03F3
;========
lda #$01 ; Lip color White
sta $04AA
sta $04CB
sta $04CC
sta $04CD
sta $04CE
sta $04CF
sta $04D0
sta $04D1
sta $04D2
sta $04D3
sta $04D4
sta $04B5
;---
lda #$08
sta $03C0
sta $03DF
sta $03E0
sta $03FF
sta $0400
sta $041F
sta $0420
sta $043F
sta $0440
sta $045F
sta $0460
sta $047F
sta $0480
sta $049F
sta $04A0
sta $04BF
sta $04C0
sta $04DF
sta $04E0
sta $04FF
sta $0500
sta $051F
sta $0520
sta $053F
sta $0540
sta $055F
sta $0560
sta $057F
sta $0580
sta $059F
sta $05A0
sta $05BF
sta $05C0
sta $05DF
;***********************
LDX #$E0
bottomlineloop:
sta $05DF,x
dex
bne bottomlineloop
Here's the problem; I don't know how It supposed to work with the number from, "IF 0, GOTO LABEL" style. At this knowledge, there is no, "IF #==#, GOTO LABEL" style. When I tried the zero, it painted a lot of things until the X = 0. The only thing I got it good is on the last part of coding.
For "if # == #, go to label", use "if # - # == 0, go to label". This is what the cmp instruction is for: it performs a subtraction and sets NZC flags appropriately, but it doesn't write the full results back to A.
EDIT: I appear to have been mistaken about the V flag. Corrected.
Expanding tepples'
cmp explanation:
Let's say you want to branch somewhere if Happy == 255. You might use:
Code:
lda Happy
cmp #255
beq somewhere
...
somewhere:
Though, for me, it's usually much better to change that branch to "bne +" and place the code you want run directly afterward. That way the branch is taken unless Happy == 255 and so the strived for code only runs if Happy == 255 (and if you place the + after that code).
To make it crystal clear:
cmp never affects a's value. It only does the subtraction and affects the NZC flags accordingly (at least those are the flags listed in the first edition of MOS Technology's Programming Manual's Appendix B... probably another mistake... why wouldn't
cmp affect the V flag too?
tepples is trustworthy ).
cmp can be used, followed by whatever branch you choose, and you can still use a's value following those instructions as if they weren't there. No need to take time and space afterward by loading the same value into the accumulator.
cpx and
cpy work exactly as
cmp works; except, replace both "a"s in the preceeding paragraph with "x" or "y".
edit: and, this is probably obvious, but also replace "the accumulator" with "index x" or "index y".
unregistered wrote:
Expanding tepples'
cmp explanation:
Let's say you want to branch somewhere if Happy == 255. You might use:
Code:
lda Happy
cmp #255
beq somewhere
...
somewhere:
Though, for me, it's usually much better to change that branch to "bne +" and place the code you want run directly afterward. That way the branch is taken unless Happy == 255 and so the strived for code only runs if Happy == 255 (and if you place the + after that code).
To make it crystal clear:
cmp never affects a's value. It only does the subtraction and affects the NZC flags accordingly (at least those are the flags listed in the first edition of MOS Technology's Programming Manual's Appendix B... probably another mistake... why wouldn't
cmp affect the V flag too?
tepples is trustworthy ).
cmp can be used, followed by whatever branch you choose, and you can still use a's value following those instructions as if they weren't there. No need to take time and space afterward by loading the same value into the accumulator.
cpx and
cpy work exactly as
cmp works; except, replace both "a"s in the preceeding paragraph with "x" or "y".
edit: and, this is probably obvious, but also replace "the accumulator" with "index x" or "index y".
THIS looks interesting.
So CMP is used to make "N = 100" stuff? or it's used as "number-alternated" BEQ / BNE? I was about to write code examples, but I got confused a liittle.
CMP compares two values, modifying the CPU flags accordingly, and you can use that information to make decisions in you program (branch or not branch based on the state of the different flags).
tokumaru wrote:
CMP compares two values, modifying the CPU flags accordingly, and you can use that information to make decisions in you program (branch or not branch based on the state of the different flags).
I'm going to have to figure out ways to make drawings of it so it would be easier to understand....
So CMP is a flag-modifier code that "tricks" it into thinking it's a zero flag or N flag?
Code:
[[[Happy == 255 ]]]
lda Happy
cmp #255
beq somewhere
So for this code examples, "Usually, BEQ means we don't allow any number BUT zero to pass through. Buuut since you have the CMP permission, you [255] may pass to the label 'somewhere'."
Is this correct?
tokumaru wrote:
Sounds correct.
REALLY?! ...THAT SIMPLE ANSWER?!...
......??!
Anyway, so this gets the opposite if it were BNE, correct? or BNE is not compatible with CMP? What else is CMP not compatible or is compatible?
Consider the following instructions:
Code:
lda firstVar
cmp secondVar
b?? somewhereElse
The
cmp instruction sets up the flags such that the following instructions (which replace
b?? above) do the following:
For
bcc (branch if carry clear): Jump if the value at address
firstVar is
less than the value at
secondVar as an unsigned number
For
bcs (branch if carry set): Jump if the value at address
firstVar is
greater than or equal to the value at
secondVar as an unsigned number
For
bne (branch if not equal): Jump if the value at address
firstVar is
not equal to the value at
secondVarFor
beq (branch if not equal): Jump if the value at address
firstVar is
not equal to the value at
secondVarFor
bpl (branch if plus): Jump if the value at address
firstVar is
greater than or equal to the value at
secondVar as a signed number
For
bmi (branch if minus): Jump if the value at address
firstVar is
less than the value at
secondVar as a signed number
tepples wrote:
Consider the following instructions:
Code:
lda firstVar
cmp secondVar
b?? somewhereElse
The
cmp instruction sets up the flags such that the following instructions (which replace
b?? above) do the following:
For
bcc (branch if carry clear): Jump if the value at address
firstVar is
less than the value at
secondVar as an unsigned number
For
bcs (branch if carry set): Jump if the value at address
firstVar is
greater than or equal to the value at
secondVar as an unsigned number
For
bne (branch if not equal): Jump if the value at address
firstVar is
not equal to the value at
secondVarFor
beq (branch if not equal): Jump if the value at address
firstVar is
not equal to the value at
secondVarFor
bpl (branch if plus): Jump if the value at address
firstVar is
greater than or equal to the value at
secondVar as a signed number
For
bmi (branch if minus): Jump if the value at address
firstVar is
less than the value at
secondVar as a signed number
So...
:
BCC : V1 < V2 = teleport / GOTO
BCS : V1 >= V2 = teleport / GOTO
BNE : V1 != V2 = teleport / GOTO
BEQ : V1 == V2 = teleport / GOTO
BPL : V1 >= V2 = teleport / GOTO
BMI : V1 < Vs = teleport / GOTO
and WITHOUT using CMP:
BCC: ?????
BCS: ?????
BNE: 0 = teleport / GOTO : 1-255 = Passage / IGNORE [A wall on numbers, a door on zero.]
BEQ: 1-255 = teleport / GOTO : 0 = Passage / IGNORE [A door on numbers, a wall on zero.]
BPL: ?????
BMI: ????? ;[Hilariously, absolutely nothing to do with weight and obese measurement.]
I also noticed a "signed" number... don't you mean "a selected number that's RIGHT NOW being used in Register A / X / Y, or just A." ?
[I strangely didn't get replied if I am right about the one above or not...]
"Signed" means "a number that can be either positive or negative, when interpreted in
two's complement".
Two's complement is a way of representing negative numbers by adding 256 ($100). For example, 255 ($FF) means -1, 254 ($FE) means -2, 253 ($FD) means -3, etc. This works because addition and subtraction in the 6502 are modulo 256. To represent -4, you use 252 ($FC) which is 256 - 4. Then 252 plus 5 equals 257 which in turn equals 1, which is -4 plus 5.
tepples wrote:
"Signed" means "a number that can be either positive or negative, when interpreted in
two's complement".
Two's complement is a way of representing negative numbers by adding 256 ($100). For example, 255 ($FF) means -1, 254 ($FE) means -2, 253 ($FD) means -3, etc. This works because addition and subtraction in the 6502 are modulo 256. To represent -4, you use 252 ($FC) which is 256 - 4. Then 252 plus 5 equals 257 which in turn equals 1, which is -4 plus 5.
So this has to do with the N flag, the one Kasumi mentioned?
So how do I make it signed...?
EDIT: This looks very annoying for people who is tired of my questions... I understood, but... without questions, we'd be more less mindful on things than before if everyone asked so many questions.
I know I repeated what I said before. "The worst questions is question that's never asked."
All numbers are signed and unsigned at the same time. That may sound confusing, but the great thing about 2's complement is that all binary operations are correct for signed and unsigned values. The only difference is how YOU interpret the results and make decisions based on them.
$FF is 255 unsigned, or -1 signed, both at the same time. If you subtract 2 from it, the result is correct either way:
$FF - $02 = $FD
Unsigned: 255 - 2 = 253
Signed: -1 - 2 = -3
The answer is correct either way. The CPU uses the carry flag to signal unsigned overflows/underflows, and the V flag to signal signed overflows/underflows. Depending on what you need the numbers for, you'll use one flag or the other (or the N flag, which's also useful after signed operations) to make decisions.
tokumaru wrote:
All numbers are signed and unsigned at the same time. That may sound confusing, but the great thing about 2's complement is that all binary operations are correct for signed and unsigned values. The only difference is how YOU interpret the results and make decisions based on them.
$FF is 255 unsigned, or -1 signed, both at the same time. If you subtract 2 from it, the result is correct either way:
$FF - $02 = $FD
Unsigned: 255 - 2 = 253
Signed: -1 - 2 = -3
The answer is correct either way. The CPU uses the carry flag to signal unsigned overflows/underflows, and the V flag to signal signed overflows/underflows. Depending on what you need the numbers for, you'll use one flag or the other (or the N flag, which's also useful after signed operations) to make decisions.
The answer on this one? Or the answer about what I wrote earlier before the questioned about signed/unsigned numbers?
So it's like a mirror-mirror style of positive and negative where...............
255 is positive [unsigned]
and 1 is negative [signed]
-
251 is positive [unsigned]
and 5 is negative [signed]
-
190 is positive [unsigned]
and 64 is negative [signed]
255
-65
---
190?????
I would see the pattern if that's correct..? Which is why BCC and BCS / BPL and BMI exists?
In two's complement, 0 through 127 ($00 through $7F) are positive, and 128 through 255 ($80 through $FF) are treated as negative. They represent -128 through -1. All the positive numbers have bit 7 clear (0), and all the negative numbers have bit 7 set (1). This is why BPL (branch if plus) jumps if the last result had bit 7 clear, and BPL (branch if minus) jumps if the last result had bit 7 set.
BCC and BCS are used if you're comparing two unsigned numbers, and BPL and BMI are used if you're comparing two signed numbers. You also use BPL in a loop that counts down to 0 and stops once the index has passed zero:
Code:
ldy #4
loop:
; Y will equal 4, then 3, then 2, then 1, then 0.
; Do something with Y each time (omitted).
; Now count down: 4 becomes 3, 3 becomes 2, ..., 0 becomes -1
dey
; If Y hasn't become negative, stay in the loop
bpl loop
tepples wrote:
In two's complement, 0-127 are positive, and 128-255 are treated as negative. They represent -128 through -1.
.......
But that's single.. what about what tokumaru wrote about that they're signed and unsigned at same time?
So in Tokumaru part, it's a mirror of positive and negative of +255 and -1, and it can go down into +3 and -253.
And in your part, it's two parts where 0-127 is positive lever, and 128-255 is negative lever, also known as -1 and -128..?
[Obviously[[?]], zero is a positive number.]
The number $C0 can represent 192, or it can represent -64. The 6502 itself couldn't give a care. In practice, it depends on the context of the code around it. As an assembly language programmer, you are responsible for imbuing numbers with semantics, defining what each value means in context.
Zero is traditionally neither negative nor positive. But the BPL and BMI branches treat a zero result as nonnegative, as if it were positive. To treat zero differently from positive numbers proper, you'll need to use both a BNE or BEQ and a BPL or BMI. You'll need to do this, for example, to distinguish a stopped character from one moving to the right.
tepples wrote:
The number $C0 can represent 192, or it can represent -64. The 6502 itself couldn't give a care. In practice, it depends on the context of the code around it. As an assembly language programmer, you are responsible for imbuing numbers with semantics, defining what each value means in context.
Zero is traditionally neither negative or positive. But the BPL and BMI branches treat a zero result as nonnegative, as if it were positive. To treat zero differently from positive numbers proper, you'll need to use both a BNE or BEQ and a BPL or BMI.
So there's an opcode where it let me define a numbers in favor for "Mirror-+" or "half -+" styles? Or what does 6502, in form if NES, support only?
If you write
lda #<-10, ca65 will treat that as a two's complement number and translate it into
lda #246.
- The # means that lda will load an immediate value, as opposed to reading from a memory address.
- The < means "keep the low byte". An assembler on a 32-bit platform, such as a PC, will internally process all values as 32-bit values. In 32-bit two's complement, -10 is $FFFFFFF6, and the < operator tells the assembler to cut the value down to 8-bit.
tepples wrote:
If you write
lda #<-10, ca65 will treat that as a two's complement number and translate it into
lda #246.
- The # means that lda will load an immediate value, as opposed to reading from a memory address.
- The < means "keep the low byte". An assembler on a 32-bit platform, such as a PC, will internally process all values as 32-bit values. In 32-bit two's complement, -10 is $FFFFFFF6, and the < operator tells the assembler to cut the value down to 8-bit.
...ca65 is part of Colecovision that Unregistered is part of, or the 6502?..
I'm starting to get confused on how it works, with your answer and Tokumaru answer.
ca65 is a 6502 assembler. It has nothing to do with Coleco.
But what about the NESASM6 part? Or ca65 better choice?
There's no "NESASM6"... There's NESASM and ASM6, two separate assemblers. NESASM and ASM6 are much more newbie friendly, but ca65 has more features than both combined. Because NESASM has some weird quirks, I usually suggest ASM6 to beginners.
Keep in mind that any of them can be used to make any kind of NES game, the difference is that ca65 has some features that make larger projects easier to manage, if you know how to use said features.
Note: I can't be part of Colecovision; I've never even touched a Colecovision.
DocWaluigean wrote:
tokumaru wrote:
All numbers are signed and unsigned at the same time. That may sound confusing, but the great thing about 2's complement is that all binary operations are correct for signed and unsigned values. The only difference is how YOU interpret the results and make decisions based on them.
$FF is 255 unsigned, or -1 signed, both at the same time. If you subtract 2 from it, the result is correct either way:
$FF - $02 = $FD
Unsigned: 255 - 2 = 253
Signed: -1 - 2 = -3
The answer is correct either way. The CPU uses the carry flag to signal unsigned overflows/underflows, and the V flag to signal signed overflows/underflows. Depending on what you need the numbers for, you'll use one flag or the other (or the N flag, which's also useful after signed operations) to make decisions.
The answer on this one? Or the answer about what I wrote earlier before the questioned about signed/unsigned numbers?
So it's like a mirror-mirror style of positive and negative where...............
255 is positive [unsigned]
and 1 is negative [signed]
-
Note: we will deal with #255 as the hardware (the 6502) sees it... in binary: #11111111b
11111111 is positive [unsigned]
and 11111111 is negative [signed]
because, like tepples said, bit7 is set and so the "signed" way of using 11111111 makes that represent a negative number (-1).
You can experiment with Windows 10's Calculator to better understand signed and unsigned. Open Calculator, click the three horizontal lines in the upper left, click "Programmer's Mode". Click on the QWORD until it reads BYTE. Click on BIN. Type or click 11111111. Notice that the signed decimal value, next to DEC, reads -1. Now click BYTE again and it will goto QWORD. Then click the C to clear the calculator. Next type or click 11111111 again. Now the value next to DEC will read 255 (that's the unsigned version of #11111111b).
Windows 10's Calculator's Programmer's Mode always switches the decimal version (next to DEC) to signed when the left most bit of the value is set. Have to go... sorry.
tokumaru wrote:
There's no "NESASM6"... There's NESASM and ASM6, two separate assemblers. NESASM and ASM6 are much more newbie friendly, but ca65 has more features than both combined. Because NESASM has some weird quirks, I usually suggest ASM6 to beginners.
Keep in mind that any of them can be used to make any kind of NES game, the difference is that ca65 has some features that make larger projects easier to manage, if you know how to use said features.
Ooooh. What features does ca65 have that ASM6 doesn't?
unregistered wrote:
Note: I can't be part of Colecovision; I've never even touched a Colecovision.
DocWaluigean wrote:
tokumaru wrote:
All numbers are signed and unsigned at the same time. That may sound confusing, but the great thing about 2's complement is that all binary operations are correct for signed and unsigned values. The only difference is how YOU interpret the results and make decisions based on them.
$FF is 255 unsigned, or -1 signed, both at the same time. If you subtract 2 from it, the result is correct either way:
$FF - $02 = $FD
Unsigned: 255 - 2 = 253
Signed: -1 - 2 = -3
The answer is correct either way. The CPU uses the carry flag to signal unsigned overflows/underflows, and the V flag to signal signed overflows/underflows. Depending on what you need the numbers for, you'll use one flag or the other (or the N flag, which's also useful after signed operations) to make decisions.
The answer on this one? Or the answer about what I wrote earlier before the questioned about signed/unsigned numbers?
So it's like a mirror-mirror style of positive and negative where...............
255 is positive [unsigned]
and 1 is negative [signed]
-
Note: we will deal with #255 as the hardware (the 6502) sees it... in binary: #11111111b
11111111 is positive [unsigned]
and 11111111 is negative [signed]
because, like tepples said, bit7 is set and so the "signed" way of using 11111111 makes that represent a negative number (-1).
You can experiment with Windows 10's Calculator to better understand signed and unsigned. Open Calculator, click the three horizontal lines in the upper left, click "Programmer's Mode". Click on the QWORD until it reads BYTE. Click on BIN. Type or click 11111111. Notice that the signed decimal value, next to DEC, reads -1. Now click BYTE again and it will goto QWORD. Then click the C to clear the calculator. Next type or click 11111111 again. Now the value next to DEC will read 255 (that's the unsigned version of #11111111b).
Windows 10's Calculator's Programmer's Mode always switches the decimal version (next to DEC) to signed when the left most bit of the value is set. Have to go... sorry.
It's alright.. I'm a little confused though.
So...
00000000 is unsigned
00100000 is unsigned
01000000 is signed
10000000 is signed
11000000 is signed
11010101 is signed
Is this what it means?...
I got to ask even extremely ridiculous question even if there's chance I got right or not so I can find and understand in the most simplest or elementary explanation even toddler can understand. Just a reminder if I said this before?
DocWaluigean wrote:
What features does ca65 have that ASM6 doesn't?
A more robust macro system that allows you to automate repetitive tasks, more advanced memory management that allows you to fill ROM and RAM non-linearly (i.e. source code organized by context), modular assembly (you can assemble parts of your program separately and combine them later), and so on.
Most of these are things you don't know you need when you're starting out, but as your programs grow more complex, you start to wish there were better ways to organize the source code and keep everything easy to maintain, and that's when you realize that ca65 can help you.
tokumaru wrote:
DocWaluigean wrote:
What features does ca65 have that ASM6 doesn't?
A more robust macro system that allows you to automate repetitive tasks, more advanced memory management that allows you to fill ROM and RAM non-linearly (i.e. source code organized by context), modular assembly (you can assemble parts of your program separately and combine them later), and so on.
Most of these are things you don't know you need when you're starting out, but as your programs grow more complex, you start to wish there were better ways to organize the source code and keep everything easy to maintain, and that's when you realize that ca65 can help you.
It sounds like something I'd do if I was in charge of NESMaker but for free.Ah. But unfortunately it's all in CMD right?
The 8-bit value itself isn't signed or unsigned. The context is signed or unsigned, and the value has an interpretation within that context.
In an unsigned context:
%00000101 means 5
%11111011 means 251
The same 8-bit values in a signed context:
%00000101 means 5
%11111011 means -5
The context is distinguished implicitly by what instructions occur around them, such as what thresholds are used in CMP, which branch instructions, and the like. There's no "unsigned mode" or "signed mode" that you have to put the processor into, the way there are "8-bit mode" and "16-bit mode" on a different CPU.
If you need a mouse-driven front-end to ca65, as opposed to something that works from command prompts, batch files, and makefiles, you could try NESICIDE.
DocWaluigean wrote:
unregistered wrote:
Note: we will deal with #255 as the hardware (the 6502) sees it... in binary: #11111111b
11111111 is positive [unsigned]
and 11111111 is negative [signed]
because, like tepples said, bit7 is set and so the "signed" way of using 11111111 makes that represent a negative number (-1).
You can experiment with Windows 10's Calculator to better understand signed and unsigned. Open Calculator, click the three horizontal lines in the upper left, click "Programmer's Mode". Click on the QWORD until it reads BYTE. Click on BIN. Type or click 11111111. Notice that the signed decimal value, next to DEC, reads -1. Now click BYTE again and it will goto QWORD. Then click the C to clear the calculator. Next type or click 11111111 again. Now the value next to DEC will read 255 (that's the unsigned version of #11111111b).
Windows 10's Calculator's Programmer's Mode always switches the decimal version (next to DEC) to signed when the left most bit of the value is set. Have to go... sorry.
It's alright.. I'm a little confused though.
So...
00000000 is unsigned
00100000 is unsigned
01000000 is signed
10000000 is signed
11000000 is signed
11010101 is signed
Is this what it means?...
Not quite... like tepples just said, signed and unsigned are just contexts or ways of thinking about binary values... i.e.
00000000 binary is interpreted as 0 (unsigned decimal) and 0 (signed decimal)
10000000 binary is interpreted as 128 (unsigned decimal) or -128 (signed decimal)
Signed (there are various ways of signed) and unsigned were created in many students'
Master's Theses. A day was spent by me searching through part of the UT in Austin library with Master's Theses. It was so exciting for me to just
hold look at some of the documents where these cool ways, of using binary values, were birthed!
Those Theses were written a little bit after the time-frame when the computer was discovered/invented/implemented, I think.
The contexts, as tepples wisely taught, are only relevant to certain code... i.e.
Code:
lda Potatoe
bmi +n
;code for positive signed values here
+n
;code for negative signed values here
;this bmi branches with signed decimal values -1 through -128. But, for this simple code it may be preferrable to think that this bmi branches for all binary values with bit7 set. Those are just two valid ways of thinking of this code. :)
edit: Remember to play with Windows' Calculator. If you open the Calculator app in Windows 10 and change it into "Programmer" mode as was explained on the previous page and in the quote above... it's super helpful!
If you change "Programmer" mode use 8-bits (BYTE), and then click the up arrow key, you can play with RoL and RoR. Click the up arrow again to change those buttons back to Lsh and Rsh. 6502 equivalents are: rol, ror, asl, and lsr.
final edit: if you decide to use an assembler that requires CMD, like ASM6, make sure to create a batch file. My batch file is named "assemble.bat" and it contains:
Code:
asm6 -L yourfilename.asm yourgamefilename.nes
@echo on %date% at %time% :)
Now all I have to do to build my .nes file is open CMD, change to the directory containing my "assemble.bat", and type
assemble and press enter.
Typing out the first line each time caused me problems after a while and tokumaru helped me to start using a batch file.
(Note: the second line is susposed to start with
@added 10/08/2018
Quote:
After this lesson, can we learn about how to turn program on from scratch with blank screen before we can go on to the next lesson?
No. Like I said, the 18th was basically the end. I don't have time anymore for more lessons. Even assuming I did have time, still no. There's a lot more I'd teach before doing anything at all with the NES. It's not to be mean. It's just not a good idea to try to avoid all the things you don't yet know while trying to build a ROM.
Quote:
-Do I ALWAYS have to put LDX #$## at the start of each? or Each label always reset if outside of the labels or the BME/BDA labels stuff?
You put # when you want a number, and you don't put # when you want an address. Branches work with addresses, so you don't want a #. I am not sure what you mean by labels resetting.
Quote:
A : You CANNOT use Register A for absolute effect! [Only X and Y can do it.]
You can totally use A with the absolute addressing mode. There's no such thing as absolute,a like absolute,x or absolute,y if that's what you mean.
Quote:
-The Absolute Effect [Or The "Compass-Comma" I made it up]
Don't make up terms! And especially don't introduce made up terms before you define them. You used your new term absolute effect in the quote above "You CANNOT use Register A for absolute effect!" but how am I supposed to know what that is when you only defined it below, right here?
For more than 30 years, the already existing terms have been in use. You are creating a barrier for experienced people understanding you when you make up new things.
Quote:
The numbers in STA 200/1/2 is treated as a file cabinet, and when you did LDA 200,X which is 1, you "basically pull out the file cabinet box, and take the numbers that's stored into Address Code $0201, which is 2." And that result, Register A is now holding number 2?
Yes.
Quote:
I don't know why no responses on other things that could help give insights; a lot of teachers in the past is willing to answer different questions that could help out students more. Being there for students even most ridiculous questions [at least in topic] raises confidences, curiosity, and trust....
I said three weeks ago, and a couple times since that I would not have much time for this anymore after September 18th. It is far after September 18th.
This is a horizontal line that can be made a loop.
Code:
;==========
sta $03A0
sta $03A1
sta $03A2
sta $03A3
sta $03A4
sta $03A5
sta $03A6
As is this:
Code:
sta $03BF
sta $03BE
sta $03BD
sta $03BC
sta $03BB
sta $03BA
sta $03B9
;=========
Note that it's writing to sequential addresses, it's just backwards. ($03B9 is first.) If you rearrange them like this:
Code:
sta $03B9
sta $03BA
sta $03BB
sta $03BC
sta $03BD
sta $03BE
sta $03BF
;=========
It should make it more clear that it's a sequence.
Quote:
Here's the problem; I don't know how It supposed to work with the number from, "IF 0, GOTO LABEL" style. At this knowledge, there is no, "IF #==#, GOTO LABEL" style. When I tried the zero, it painted a lot of things until the X = 0. The only thing I got it good is on the last part of coding.
Because that's how the loops end. With a branch on zero. If you want to check other numbers, yes, you need to learn a new instruction. But you don't need to do so to complete the assignment, or I'd have taught it.
For the purposes of this assignment, If you want to stop at any random address, that's the address you use before the ",x". This works because zero plus anything equals that thing.
zero plus $456 = $456. zero plus $03B9 equals $03B9. You can stop on any address when X equals zero.
So if X is zero, sta $456,x will store the value in A to $456. If X is zero, sta $03B9,x will store the value in A to $03B9.
I'm not gonna get into signed/unsigned stuff that really requires a new lesson and I have much more sporadic time now. Apologies if the next post is in another week.
There's videos on youtube explaining binary math.
If I stay too long in this lesson, I will surely be feeling to quit, so I don't want to take the risk. I can always go back and perfect it.
Code:
lda #$04
ldx #$1F
toplineloop:
sta $0200,x
dex
bne toplineloop
sta $0200
;===
sta $0220 ; Hat Vertically [Up/Down]
sta $023F
sta $0240
sta $025F
sta $0260
sta $027F
sta $0280
sta $029F
sta $02A0
sta $02BF
sta $02C0
sta $02DF
sta $02E0
sta $02FF
sta $0300
sta $031F
sta $0320
sta $033F
sta $0340
sta $035F
sta $0360
sta $037F
sta $0380
sta $039F
;==========
;XXXXXXXXXXXXXXXXXXXXXXXX
;LDA #$04
;LDX #$9
;middle1:
;sta $03A0,x
;DEX
;CMP $03B9
;BEQ middle1
;XXXXXXXXXXXXXXXXXXXXXXXXX
;---------------
;XXXXXXXXXXXXXXXXXXXXX
;lda #$04
;ldx #$B9
;j:
;sta $03A0,x
;dex
;bne j
;sta $0200
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;-----------
sta $03A0
sta $03A1
sta $03A2
sta $03A3
sta $03A4
sta $03A5
sta $03A6
sta $03BF
sta $03BE
sta $03BD
sta $03BC
sta $03BB
sta $03BA
sta $03B9
;=========
sta $0398
sta $0397
sta $0396
sta $0395
sta $0394
sta $0387
sta $0388
sta $0389
sta $038A
sta $038B
;=========
sta $0370
sta $0371
sta $0372
sta $0373
sta $036F
sta $036E
sta $036D
sta $036C
;========
ldx #$0D ; Eye Color Light Green Left
stx $038C
stx $03AC
stx $03CC
stx $03EC
ldy #$0E ; Eye Color Light Blue Right
sty $0393
sty $03B3
sty $03D3
sty $03F3
;========
lda #$01 ; Lip color White
sta $04AA
sta $04CB
sta $04CC
sta $04CD
sta $04CE
sta $04CF
sta $04D0
sta $04D1
sta $04D2
sta $04D3
sta $04D4
sta $04B5
;---
lda #$08
sta $03C0
sta $03DF
sta $03E0
sta $03FF
sta $0400
sta $041F
sta $0420
sta $043F
sta $0440
sta $045F
sta $0460
sta $047F
sta $0480
sta $049F
sta $04A0
sta $04BF
sta $04C0
sta $04DF
sta $04E0
sta $04FF
sta $0500
sta $051F
sta $0520
sta $053F
sta $0540
sta $055F
sta $0560
sta $057F
sta $0580
sta $059F
sta $05A0
sta $05BF
sta $05C0
sta $05DF
;***********************
LDX #$E0
bottomlineloop:
sta $05DF,x
dex
bne bottomlineloop
If lesson is stopped for a while, or long time, I want to thank you so much Kasumi for helping me progress immensely compare to my previous knowledge of 6502 when I sign up here.
Now... even though I don't know all knowledge, I need to find someway to keep learning or to get to learning on turning on NES. So I made an animation with Aseprite to show the example of what I want after the 3 2 1 stuff.
Attachment:
Sprite-0002.gif [ 3.18 KiB | Viewed 7157 times ]
So if the lesson is done for now or for long time at this timeline, the first test I need is to make NES turn on 100% without using any already-created templates. Like the first posts, I got ASM6 and Notepad ++. And then something about iNES mirror something...? Around in those CPU NES, there's an Address Code I gotta find that "If it get's STA'd into 1, the entire system will be on for NES."
DocWaluigean wrote:
The first test I need is to make NES turn on 100% without using any already-created templates.
There are many beginning steps in a running NES game/program, each of which can be considered "turned on at 100%" by various people.
- The cartage is in and the CPU loads bytes $fffc and $fffd into the Program Counter (PC). The emulator equivalent would be to successfully load a ROM without it throwing an error at you.
- The graphics chip (PPU) is warmed up a few thousand CPU cycles later.
- Various NES and Cartridge hardware have been initialized to a sane state.
- Memory is cleared, and or your own program logic is initialized.
- The contents of your first screen or scene is loaded and displayed.
- The game/program is waiting for the next frame, and or input from the controller pads.
At which point would you consider it 100% booted?
If it's to the point where that animated GIF is animating on the NES, Then the step of setting up the contents of your scene is going to be very complicated. This would require knowing how to format all those animated GIF frames into data suitable for the graphics chip, or being able to use tools that can do that job for you.
JRoatch wrote:
DocWaluigean wrote:
The first test I need is to make NES turn on 100% without using any already-created templates.
There are many beginning steps in a running NES game/program, each of which can be considered "turned on at 100%" by various people.
- The cartage is in and the CPU loads bytes $fffc and $fffd into the Program Counter (PC). The emulator equivalent would be to successfully load a ROM without it throwing an error at you.
- The graphics chip (PPU) is warmed up a few thousand CPU cycles later.
- Various NES and Cartridge hardware have been initialized to a sane state.
- Memory is cleared, and or your own program logic is initialized.
- The contents of your first screen or scene is loaded and displayed.
- The game/program is waiting for the next frame, and or input from the controller pads.
At which point would you consider it 100% booted?
For my view of 100% booted:
-It shows gray, default color.
-ABSOULTELY NO error upon boot-up.
-Able to place any code into the ASM after boot-up succeed.
-It can be turn on WITHOUT pre-made preset, template, NROM template that koisuki maded, anything pre-made and pre-created
-You can put ANY any code into the booted ASM without facing limit or problems because of pre-made or something.
-If it's easy for me to study to make the lesson elementary.
I sometimes repeat myself, but I want to know the core-corest details about 6502 Assembly, and for NES. So with knowledge of booting up NES and others:
Outside of knowledge, it will strongly motivate me to keep going in NES more persistence than before.
Inside of knowledge, I will able to pull Satoru Iwata and able to be "The Superman" of 6502 like his extreme knowledge of programming many years ago, and I could successfully make teachings for kids at best rate possible.
[I might not explain well?]
EDIT:
About animating? That's the few steps after I got it boot up. The animation with chalkboard is a type of objective or mission of my idea.
Also, it would be good if I could just put "Hello World!" in similar style of difficulty as just typing out "PRINT "HELLO WORLD!", but with tiles instead.
When the default gray color shows, that's when the the graphics chip has warmed up. All you'll need is a valid
.nes file. Frankly it's kind of odd you specifically don't want a template for this part as that is basically all you need to succeed in generating such a file. It's like saying we need a 8.5 by 11 inch piece of paper but it can't be precut.
Sorry if I got lost in the thread, which assembler will you be using?
JRoatch wrote:
When the default gray color shows, that's when the the graphics chip has warmed up. All you'll need is a valid
.nes file. Frankly it's kind of odd you specifically don't want a template for this part as that is basically all you need to succeed in generating such a file. It's like saying we need a 8.5 by 11 inch piece of paper but it can't be precut.
Sorry if I got lost in the thread, which assembler will you be using?
If I use a template, I will literally be missing out on everything on starting to make the base for .NES ASM stuff. I may never learn how to make it compatible for mapper, support NES music of N106, etc. if I rely on template too much.
Besides, in real life, the paper made by hand is verry out-dated and difficult to make for pre-cut. XD I'd love to make a canvas for watercolor and acrylic, but it gets too complex and real life money for me to do it.
They mention NESASM3 is the most popular for beginners because of Bunnyboy. Tokumaru saided ASM6 [NESASM6 I call it.] is the best for beginners, and ca65 is for advanced homebrewers atm.
I feel I'll go with ASM6.
Ok, so let's see if we can get asm6 to work.
in a
plain text editor such as Windows Notepad enter and save the following as "test.asm"
Code:
.db "hello world", $0d, $0a, "Second line", $0d, $0a
In a round about way, this will basically instruct asm6 to make a file that is just 2 lines of plain text (not a nes file or anything yet).
Then in a command line window tell asm6 to assemble it
Code:
asm6.exe test.asm output.txt
This step might difficult if you don't know what a command line window is, or how to use it. I'm assuming a lot here.
If successful there will be a file named "output.txt" that contains the text
Code:
hello world
Second line
JRoatch wrote:
Ok, so let's see if we can get asm6 to work.
in a
plain text editor such as Windows Notepad enter and save the following as "test.asm"
Code:
.db "hello world", $0d, $0a, "Second line", $0d, $0a
In a round about way, this will basically instruct asm6 to make a file that is just 2 lines of plain text (not a nes file or anything yet).
Then in a command line window tell asm6 to assemble it
Code:
asm6.exe test.asm output.txt
This step might difficult if you don't know what a command line window is, or how to use it. I'm assuming a lot here.
If successful there will be a file named "output.txt" that contains the text
Code:
hello world
Second line
Okay. Elaborate or explain each by each about the code.
Unless this is actually cmd hello world code?
DocWaluigean wrote:
If I use a template, I will literally be missing out on everything on starting to make the base for .NES ASM stuff.
Quite the contrary! It's better to study/dissect/break a known good template to figure it out than start from nothing without knowing what to do. You need quite a bit of knowledge about the NES architecture and how assemblers work to be able to create a valid .NES file on your own from scratch, and most newbies *don't* have that knowledge. You can't become a painter only from studying how paints and paintbrushes work, you have to see how other painters do it in practice.
Quote:
I may never learn how to make it compatible for mapper, support NES music of N106, etc. if I rely on template too much.
It's waaaaaaaaay too soon to be thinking about mappers and audio expansions.
Quote:
They mention NESASM3 is the most popular for beginners because of Bunnyboy.
If you plan on following the Nerdy Nights tutorials to the letter, then NESASM is the way to go.
Quote:
Tokumaru saided ASM6 [NESASM6 I call it.] is the best for beginners
Please don't make up names for stuff, it's confusing. ASM6 and NESASM are equally easy to use, but they have slightly different syntax. The number 1 annoying thing about NESASM is that it forces you to use 8KB banks, regardless of the actual bank size of the mapper you're using.
DocWaluigean wrote:
Unless this is actually cmd hello world code?
He's teaching you the basics of ASM6 so you understand how it translates a source file into a binary file. Once you get that, you can start changing the source file so the output is not any binary file, but a valid NES file.
Yes it's is a "hello world" of sorts, but with the intention that we know that we can use asm6.
Like many command line programs, asm6 reads input, does some processing, and writes some output.
The input and output are files. In this case should contain what the first and last code boxes have.
The second code box is what you type in the command line prompt to command asm6 to do it's thing.
If you get stuck, explain a bit of what you tried when figuring out my instructions.
tokumaru wrote:
DocWaluigean wrote:
If I use a template, I will literally be missing out on everything on starting to make the base for .NES ASM stuff.
Quite the contrary! It's better to study/dissect/break a known good template to figure it out than start from nothing without knowing what to do. You need quite a bit of knowledge about the NES architecture and how assemblers work to be able to create a valid .NES file on your own from scratch, and most newbies *don't* have that knowledge. You can't become a painter only from studying how paints and paintbrushes work, you have to see how other painters do it in practice.
That's true. But unfortunately, it may be difficult as there's a picky situations where I want something and what I don't want something from template: Like I want 1MB graphic, but I don't want music-limit stuff, which requires me to understand more about templates or mapper.
Quote:
It's waaaaaaaaay too soon to be thinking about mappers and audio expansions.
True. Although chances where I may learn very fast if the guide is really good!
Quote:
If you plan on following the Nerdy Nights tutorials to the letter, then NESASM is the way to go.
Not at this time. I'm still giving NHC a try to learn many.
Quote:
Please don't make up names for stuff, it's confusing. ASM6 and NESASM are equally easy to use, but they have slightly different syntax. The number 1 annoying thing about NESASM is that it forces you to use 8KB banks, regardless of the actual bank size of the mapper you're using.
If I can't make up names for codes, there's chances for me [or anyone] to forget connective mnemonics for me [or anyone] to understand or recognize the opcodes or other words. I would've struggle more with ,x / ,y / ,a if I never made up the name, "Charter Comma". Think about if I were young man [like 11 or 14] who really wants to learn 6502, but struggles with complex words like increments. It's one of obstacles where I want to tackle, and also help for autistic people.
Quote:
He's teaching you the basics of ASM6 so you understand how it translates a source file into a binary file. Once you get that, you can start changing the source file so the output is not any binary file, but a valid NES file.
Ah, I understand.
DocWaluigean wrote:
If I can't make up names for codes, there's chances for me [or anyone] to forget connective mnemonics for me [or anyone] to understand or recognize the opcodes or other words. I would've struggle more with ,x / ,y / ,a if I never made up the name, "Charter Comma".
Would "index comma" have worked?
tepples wrote:
DocWaluigean wrote:
If I can't make up names for codes, there's chances for me [or anyone] to forget connective mnemonics for me [or anyone] to understand or recognize the opcodes or other words. I would've struggle more with ,x / ,y / ,a if I never made up the name, "Charter Comma".
Would "index comma" have worked?
Not likely, because I [or others] may get fixated on Index Finger or other terms I somehow failed to remember about. If I think about Index, maybe I'm thinking about a type of word-map of where the name, pages, etc. goes, but they called it Glossary? or possibly something geometry or mathematics.
Quote:
Quite the contrary! It's better to study/dissect/break a known good template to figure it out than start from nothing without knowing what to do. You need quite a bit of knowledge about the NES architecture and how assemblers work to be able to create a valid .NES file on your own from scratch, and most newbies *don't* have that knowledge. You can't become a painter only from studying how paints and paintbrushes work, you have to see how other painters do it in practice.
So which template is the best of the best, yet most basic, to start off?
Also, I'm having little trouble downloading ASM6 and Notepad ++ for the .nes cmd stuff.
asm6 download from nesdev wiki Sorry, I don't remember loopy's new website url.
(Maybe that's his new site... 3dscapture.com)edit: I started our game's journey with "NES 101 Tutorial" by Michael Martin; however, I don't think any of his tutorial code exists in our game now. But, it was a very helpful start, for me, when I started to learn NES.
Try searching nesdev wiki for NES 101 Tutorialedit2.
unregistered wrote:
asm6 download from nesdev wiki Sorry, I don't remember loopy's new website url.
edit: I started our game's journey with "NES 101 Tutorial" by Michael Martin; however, I don't think any of his tutorial code exists in our game. But, it was a very helpful start, for me, when I beginning to learn NES.
Ah! Thank you very much! Although to be honest, I'm a little scared attempting to do this since I feel I may go insane or mad if I failed. ^^;
I remember feeling that way too... but, I said a prayer and my heart was enveloped in peace.
Hopefully, you'll be able to do this too.
unregistered wrote:
I remember feeling that way too... but, I said a prayer and my heart was enveloped in peace.
Hopefully, you'll be able to do this too.
As I believe you about religion, you gotta know that maybe[?] God want's us to do things ourselves for a while, like "Learn to take baby steps by yourself." So the prayer might annoy Him or Christ for abusing their helps? Sorry? Let's take it easy for now.
viewtopic.php?p=58138#p58138According to this template, I am not sure which should I go specific on first. And which one I can disassemble to where I can open up with the fewest of fewest code possible.
DocWaluigean wrote:
unregistered wrote:
I remember feeling that way too... but, I said a prayer and my heart was enveloped in peace.
Hopefully, you'll be able to do this too.
As I believe you about religion, you gotta know that maybe[?] God want's us to do things ourselves for a while, like "Learn to take baby steps by yourself." So the prayer might annoy Him or Christ for abusing their helps?
Read Phillipians 4:6-7 and notice that word "everything".
I'm sorry again; in my quote above, my "this" was ment to only refer to what you were worried about doing; I should be more careful in my writting.
Sorry, I have to go.
unregistered wrote:
DocWaluigean wrote:
unregistered wrote:
I remember feeling that way too... but, I said a prayer and my heart was enveloped in peace.
Hopefully, you'll be able to do this too.
As I believe you about religion, you gotta know that maybe[?] God want's us to do things ourselves for a while, like "Learn to take baby steps by yourself." So the prayer might annoy Him or Christ for abusing their helps?
Read Phillipians 4:6-7 and notice that word "everything".
I'm sorry again; in my quote above, my "this" was ment to only refer to what you were worried about doing; I should be more careful in my writting.
Sorry, I have to go.
Ah, I'm sorry. And it's alright. No need to apologize. I already and always forgiven you.
And it's alright. ttyl.
-
Code:
;----------------------------------------------------------------
; constants
;----------------------------------------------------------------
PRG_COUNT = 1 ;1 = 16KB, 2 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen
This is the NROM template. So I am not sure why there's no "ines." in beginning.
And constants ; does it also mean any letter of alphabet that is NOT vowels [A E I O U] ? EDIT: it's consonant, not constants. Alongside, constant would also mean "keep going" in certain words like, "At constant rate..."?
PRG COUNT as maximum byte for 32000 byte, huh. Is it possible to get 1MB [or 1GB for the master coder of all master coder of 6502 NES coder?] or 2MB of it? Like PRG_COUNT = 255?
With the %, I'm calling that it's binary.
So 1 is vertical, 0 is horizontal, and 8 is four-screen...? Is the "MIRRORING" the support code?
I'm assuming you got ASM6 to work. If not, I've prepared a video if you wish to see.
DocWaluigean wrote:
Code:
;----------------------------------------------------------------
; constants
;----------------------------------------------------------------
PRG_COUNT = 1 ;1 = 16KB, 2 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen
This is the NROM template. So I am not sure why there's no "ines." in beginning.
The actual iNES header is computed and written to the output file at the "iNES header" section.
That first part is there so that you can easily change some parts of the configuration without having to dig through the "iNES header" section
DocWaluigean wrote:
PRG COUNT as maximum byte for 32000 byte, huh. Is it possible to get 1MB [or 1GB for the master coder of all master coder of 6502 NES coder?] or 2MB of it? Like PRG_COUNT = 255?
Not in this case. Because this is NROM, you can only choose
1 or
2 for
PRG_COUNT.
DocWaluigean wrote:
With the %, I'm calling that it's binary.
Correct
DocWaluigean wrote:
So 1 is vertical, 0 is horizontal, and 8 is four-screen...? Is the "MIRRORING" the support code?
It's Mirroring as in
Nametable Mirroring. The NES has memory to lay out 2 screens of tiles, but the NES can scroll to display varying amounts of
4 different screens. So this Mirroring setting tells the NES how to duplicate the 2 actual screens. Best to leave this at
%0001 so you can have more horizontal space to work with later, because with a setting of
%0000 one screen will be duplicated (or mirrored) in the horizontal direction.
If you wish to know where you code begins, it's at the "program bank(s)" section where the
Reset: label is. The is where the CPU starts when the power button or the reset button is pressed. The reason this is so is because the address for the
Reset: label is placed at $fffc in the "interrupt vectors" section.
One last thing to note is that because of the
.incbin in the "CHR-ROM bank" section you'll need a 8KiB file for the 512 graphic tiles of CHR-ROM. If you just want a quick way to get a gray screen, we can replace the line
.incbin "tiles.chr" with
.dsb 8192, 0 to fill CHR-ROM with all blank tiles until we can make a
tiles.chr file with a NES tile editing tool of some sort.
JRoatch wrote:
I'm assuming you got ASM6 to work. If not, I've prepared a video if you wish to see.
DocWaluigean wrote:
Code:
;----------------------------------------------------------------
; constants
;----------------------------------------------------------------
PRG_COUNT = 1 ;1 = 16KB, 2 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen
This is the NROM template. So I am not sure why there's no "ines." in beginning.
The actual iNES header is computed and written to the output file at the "iNES header" section.
That first part is there so that you can easily change some parts of the configuration without having to dig through the "iNES header" section
DocWaluigean wrote:
PRG COUNT as maximum byte for 32000 byte, huh. Is it possible to get 1MB [or 1GB for the master coder of all master coder of 6502 NES coder?] or 2MB of it? Like PRG_COUNT = 255?
Not in this case. Because this is NROM, you can only choose
1 or
2 for
PRG_COUNT.
DocWaluigean wrote:
With the %, I'm calling that it's binary.
Correct
DocWaluigean wrote:
So 1 is vertical, 0 is horizontal, and 8 is four-screen...? Is the "MIRRORING" the support code?
It's Mirroring as in
Nametable Mirroring. The NES has memory to lay out 2 screens of tiles, but the NES can scroll to display varying amounts of
4 different screens. So this Mirroring setting tells the NES how to duplicate the 2 actual screens. Best to leave this at
%0001 so you can have more horizontal space to work with later, because with a setting of
%0000 one screen will be duplicated (or mirrored) in the horizontal direction.
If you wish to know where you code begins, it's at the "program bank(s)" section where the
Reset: label is. The is where the CPU starts when the power button or the reset button is pressed. The reason this is so is because the address for the
Reset: label is placed at $fffc in the "interrupt vectors" section.
One last thing to note is that because of the
.incbin in the "CHR-ROM bank" section you'll need a 8KiB file for the 512 graphic tiles of CHR-ROM. If you just want a quick way to get a gray screen, we can replace the line
.incbin "tiles.chr" with
.dsb 8192, 0 to fill CHR-ROM with all blank tiles until we can make a
tiles.chr file with a NES tile editing tool of some sort.
Yes please. I'm so sorry for being delayance...
So NROM is a limited but beginner-friendly template.
Ahhh, like the "double screen same" from the debug style.
On the last one, I mean making gray screen but with 100% code-placement friendly, like a piece of paper, and a pencil, and ready to "code" by drawing.
DocWaluigean wrote:
JRoatch wrote:
I'm assuming you got ASM6 to work. If not, I've prepared a video if you wish to see.
Yes please. I'm so sorry for being delayance...
How to use asm6.exe on windows 10.
Please excuse my accent. I'm not good with a microphone, and at times I could be mistaken for the english dub of Dr. Light from megaman 8. I hope you can follow along anyway. Let me know if this is actually harder to understand then just reading text.
DocWaluigean wrote:
So NROM is a limited but beginner-friendly template.
Being that it represents the most basic hardware configuration, it would be beginner-friendly.
DocWaluigean wrote:
On the last one, I mean making gray screen but with 100% code-placement friendly, like a piece of paper, and a pencil, and ready to "code" by drawing.
Once asm6.exe is working, you'll copy and paste the whole NROM template into your asm6.exe input file ("input.txt" in my video) and for your Command Prompt window type
asm6.exe input.txt output.nes. If that works the file
output.nes will be a valid nes rom and will successfully load and run in a emulator.
From there your code will begin at where the
Reset: label is.
JRoatch wrote:
DocWaluigean wrote:
JRoatch wrote:
I'm assuming you got ASM6 to work. If not, I've prepared a video if you wish to see.
Yes please. I'm so sorry for being delayance...
How to use asm6.exe on windows 10.
Please excuse my accent. I'm not good with a microphone, and at times I could be mistaken for the english dub of Dr. Light from megaman 8. I hope you can follow along anyway. Let me know if this is actually harder to understand then just reading text.
DocWaluigean wrote:
So NROM is a limited but beginner-friendly template.
Being that it represents the most basic hardware configuration, it would be beginner-friendly.
DocWaluigean wrote:
On the last one, I mean making gray screen but with 100% code-placement friendly, like a piece of paper, and a pencil, and ready to "code" by drawing.
Once asm6.exe is working, you'll copy and paste the whole NROM template into your asm6.exe input file ("input.txt" in my video) and for your Command Prompt window type
asm6.exe input.txt output.nes. If that works the file
output.nes will be a valid nes rom and will successfully load and run in a emulator.
From there your code will begin at where the
Reset: label is.
I thank you so much for the video tutorial. Really.
I won't go much details on why absences. Let's say that I have rough time smiling for months. So...
viewtopic.php?f=10&t=17454&start=270 According to the long list of reviewing what I [hopefully we] learnt, I feel I need to try and write this down for attempting to imagine something so if cartoons for 6502 learning works:
- Number system of Binary = Playing with a giant block like Croquet sport, where block turns from 0 to 1 somewhat.
- LDAXY / STAXY = A crane machine where A is Red, X is Blue, and Y is Yellow, and the fluffy bunny doll represent numbers and what it does. [A fluffy bunny represent the sprite code for the main character which is the fluffy bunny.]
- Register = ???????????? [To be edited]
- TAX / TAY = A same crane that can be given number or decimals to each others. The prize is actually radioactive nitroglycerin, and cannot be in same room with X and Y togather, hence it only transfer between A and X or A and Y.
- INC / DEC = simple scene of math plus and minus, just comedic references about being too smart and Oxford about it.
- JMP = ??????? [ To be edited. Something about using countries and continent as a references??]
- BEQ / BNE / ... = ?!?!?!?!?! [Most recent issues, it could be inspector or legal police officer, or the alerter scenes about how it works.] [To be edited.]
---
I feel I got certain jots down a little while. I hope I do not get penalize for long term issues. It will take me a while a LITTLE while to re-assume what to learn about the inside the NROM header thingy.[? or the templates?]
As a relatively new nesdever I'd recommend not worrying too much about tools in the beginning. You will gain a better understanding of how things are put together the longer you keep things basic. Following a simple tutorial with whatever tools used there will be enough to get you started. It's gonna take time but so does anything worth pursuing, right?
DocWaluigean wrote:
- LDAXY / STAXY = A crane machine where A is Red, X is Blue, and Y is Yellow, and the fluffy bunny doll represent numbers and what it does. [A fluffy bunny represent the sprite code for the main character which is the fluffy bunny.]
- Register = ???????????? [To be edited]
- TAX / TAY = A same crane that can be given number or decimals to each others. The prize is actually radioactive nitroglycerin, and cannot be in same room with X and Y togather, hence it only transfer between A and X or A and Y.
...
I feel I got certain jots down a little while. I hope I do not get penalize for long term issues. It will take me a while a LITTLE while to re-assume what to learn about the inside the NROM header thingy.[? or the templates?]
Welcome back.
Going with your crane machine analogy a Register would be the chute where the bunny is dropped at (but read on on why this description may be flawed), and JMP and Bxx would be oddly affecting the crane operator/player somehow?
I think most object analogies like this crane machine confuses one important fact about how the CPU works: Every tiny operation that's called a "move" or a "transfer" is actually copying.
In real life (as we all know) when a thing moves from one spot to another that thing no longer exists at the old location.
In the computer realm, the action that we call "moving" leaves the old pattern of bits exactly as it is, while causing the pattern of bits in the new location to be same as the old.
You could think of this a having many chalkboards (or just a single chalkboard divided up).
So to move a number from chalkboard X to chalkboard Y, chalkboard Y must first be erased then the number in chalkboard X is read and written to chalkboard Y.
You may think the CPU could just erase chalkboard X automatically after the copy, but that's a waste of real mechanical effort, so the old chalkboard X remains the same.
There was one part of an old book I used to read as a child that helped me really understand how the CPU of computers really function.
The book was
Usborne Guide to Computers: A simple and colourful introduction for beginnersand in it there was 2 pages describing an activity where you cut out a long strip of paper with simple instructions and that long strip was feed through a small paper view, and you followed the instructions in that view which included steps like moving the viewer to a numbered part of the paper strip.
http://www.asciimation.co.nz/bb/wpg2?g2_itemId=5489I can't seem to find the book any more, but I found a through review of it at
http://www.asciimation.co.nz/bb/2013/10/28/usborne-guide-to-computers
pwnskar wrote:
As a relatively new nesdever I'd recommend not worrying too much about tools in the beginning. You will gain a better understanding of how things are put together the longer you keep things basic. Following a simple tutorial with whatever tools used there will be enough to get you started. It's gonna take time but so does anything worth pursuing, right?
Thank you for tip, but that's what I'm trying to figure out or something, which is making the tutorial so easy to understand.
JRoatch wrote:
DocWaluigean wrote:
- LDAXY / STAXY = A crane machine where A is Red, X is Blue, and Y is Yellow, and the fluffy bunny doll represent numbers and what it does. [A fluffy bunny represent the sprite code for the main character which is the fluffy bunny.]
- Register = ???????????? [To be edited]
- TAX / TAY = A same crane that can be given number or decimals to each others. The prize is actually radioactive nitroglycerin, and cannot be in same room with X and Y togather, hence it only transfer between A and X or A and Y.
...
I feel I got certain jots down a little while. I hope I do not get penalize for long term issues. It will take me a while a LITTLE while to re-assume what to learn about the inside the NROM header thingy.[? or the templates?]
Welcome back.
Going with your crane machine analogy a Register would be the chute where the bunny is dropped at (but read on on why this description may be flawed), and JMP and Bxx would be oddly affecting the crane operator/player somehow?
I think most object analogies like this crane machine confuses one important fact about how the CPU works: Every tiny operation that's called a "move" or a "transfer" is actually copying.
In real life (as we all know) when a thing moves from one spot to another that thing no longer exists at the old location.
In the computer realm, the action that we call "moving" leaves the old pattern of bits exactly as it is, while causing the pattern of bits in the new location to be same as the old.
You could think of this a having many chalkboards (or just a single chalkboard divided up).
So to move a number from chalkboard X to chalkboard Y, chalkboard Y must first be erased then the number in chalkboard X is read and written to chalkboard Y.
You may think the CPU could just erase chalkboard X automatically after the copy, but that's a waste of real mechanical effort, so the old chalkboard X remains the same.
There was one part of an old book I used to read as a child that helped me really understand how the CPU of computers really function.
The book was
Usborne Guide to Computers: A simple and colourful introduction for beginnersand in it there was 2 pages describing an activity where you cut out a long strip of paper with simple instructions and that long strip was feed through a small paper view, and you followed the instructions in that view which included steps like moving the viewer to a numbered part of the paper strip.
http://www.asciimation.co.nz/bb/wpg2?g2_itemId=5489I can't seem to find the book any more, but I found a through review of it at
http://www.asciimation.co.nz/bb/2013/10/28/usborne-guide-to-computersI think Unregistered has the website for it! Or is it some other one who goes by..? , because I keep getting off track a little. Anyway, I thank for constructive criticism, as sad as I can't explain well, so I'm going to be a little descrete:
-Let's say the claw is grabbing 8-ball [#$08] that's the letter A. It's in a different rooms
-The #$08 is being assigned to a specific bin which is like Address $0022
-The claw of A [Accelerator] is mobing the 8-ball to the cubical bin of Address $0022 and drops it, and it performs special actions.
---
Anyway, I'll try and see what each by each works as I'm re-reading my early post.
Code:
;----------------------------------------------------------------
; variables
;----------------------------------------------------------------
.enum $0000
;NOTE: declare variables using the DSB and DSW directives, like this:
;MyVariable0 .dsb 1
;MyVariable1 .dsb 3
.ende
;NOTE: you can also split the variable declarations into individual pages, like this:
;.enum $0100
;.ende
;.enum $0200
;.ende
Okay, there's PPU map, CPU map, and
https://wiki.nesdev.com/w/index.php/PPU_memory_map other maps that I got lost so here's two things:
$0000 = Internal map of RAM, which is random access memory. I get fixated on words, so I may think this is "RAM is how much work CPU got to do before performing actions."
OR
$0000 = Pattern Table 0 . The place that is a home for the sprites and graphics.
Alongside, I do not know about, ".enum" and ".ende". Am I guessing it's the name of map? Ende is CPU Map, and Enum is PPU Map? I need a full explainations about the way "Variable" table goes, and why each code does like that.
DocWaluigean wrote:
-Let's say the claw is grabbing 8-ball [#$08] that's the letter A. It's in a different rooms
-The #$08 is being assigned to a specific bin which is like Address $0022
-The claw of A [Accelerator] is mobing the 8-ball to the cubical bin of Address $0022 and drops it, and it performs special actions.
The cubical bin is RAM which keeps the thing that was last dropped into. in this case the 8-ball.
Some places that the 8-ball can be dropped into are not cubical bins, but instead chutes that leads to things like a large button that flashes lights (PPU Registers).
All the while, due to strange laws of computer physics the Accumulator Claw still has a 8-ball despite the claw dropping it so many times.
DocWaluigean wrote:
Anyway, I'll try and see what each by each works as I'm re-reading my early post.
I think you got the general idea that the CPU and PPU have different address spaces which is why address $0000 can refer to two different things.
So instead lets see if we can make sense of what this piece of code is doing (which has nothing to do with differing address buses).
tldr/summary: All labels between
.enum $xxxx and
.ende goes to RAM starting at $xxxx and not ROM.
------
First remember these are instructions to the
assembler.
We are attempting to command the assembler to generate the contents of a ROM that will be later executed by a 6502 CPU in a NES machine.
By default most assembler instructions will generate 1 or more bytes in the resulting ROM. It'll also keep track of how many bytes it has written so that when a label like
MyVariable0: comes along the assembler will know what byte the label means.
Code:
.enum $0000
This says a couple things on how the assembler should behave for the code that follows:
First
.enum says that until the assembler sees a
.ende it should not generate any bytes to the ROM, but to still track how many bytes instructions would of taken. That way labels still work.
The second part
$0000 sets what address it's label tracking byte count starts at. asm6 still keeps it's old counter which it'll revert to once it gets to the
.endeIf you remove the
; from the lines after the note, those lines will become active assembler instructions.
Code:
MyVariable0: .dsb 1
Normally
.dsb generates a number of filler bytes, but since the assembler is in a
enum block, it won't actually write that to ROM. It'll simply add 1 to the assembler's internal address counter (properly called the Program Counter).
The result of this instruction is that the label
MyVariable0: is $0000, and the next label (if any) will be $0001.
Code:
MyVariable1: .dsb 3
The Program Counter is $0001, so the label
MyVariable1: is $0001. Program Counter is increased by 3 so the next label will be $0004.
Code:
.ende
As explained above the assembler exits it's enum mode, restoring the Program Counter to whatever it was before, and generating more ROM bytes as it encounters more instructions.
So why does the assembler have this whole enum mechanism anyway? Labels that automatically add up their sizes are useful to work with, but the automatic generating of bytes into ROM becomes a hindrance when working in a area that doesn't exist in the ROM at all. Namely the RAM.
The term enum is shorten from the word enumeration which is the process of giving ordered numbers to a list of things, and that's basically the purpose this asm6 assembler mode.
The rest of that code then repeats these enum blocks for you to put more non-ROM things located at $0100 and $0200.
JRoatch wrote:
DocWaluigean wrote:
-Let's say the claw is grabbing 8-ball [#$08] that's the letter A. It's in a different rooms
-The #$08 is being assigned to a specific bin which is like Address $0022
-The claw of A [Accelerator] is mobing the 8-ball to the cubical bin of Address $0022 and drops it, and it performs special actions.
The cubical bin is RAM which keeps the thing that was last dropped into. in this case the 8-ball.
Some places that the 8-ball can be dropped into are not cubical bins, but instead chutes that leads to things like a large button that flashes lights (PPU Registers).
All the while, due to strange laws of computer physics the Accumulator Claw still has a 8-ball despite the claw dropping it so many times.
DocWaluigean wrote:
Anyway, I'll try and see what each by each works as I'm re-reading my early post.
I think you got the general idea that the CPU and PPU have different address spaces which is why address $0000 can refer to two different things.
So instead lets see if we can make sense of what this piece of code is doing (which has nothing to do with differing address buses).
tldr/summary: All labels between
.enum $xxxx and
.ende goes to RAM starting at $xxxx and not ROM.
------
First remember these are instructions to the
assembler.
We are attempting to command the assembler to generate the contents of a ROM that will be later executed by a 6502 CPU in a NES machine.
By default most assembler instructions will generate 1 or more bytes in the resulting ROM. It'll also keep track of how many bytes it has written so that when a label like
MyVariable0: comes along the assembler will know what byte the label means.
Code:
.enum $0000
This says a couple things on how the assembler should behave for the code that follows:
First
.enum says that until the assembler sees a
.ende it should not generate any bytes to the ROM, but to still track how many bytes instructions would of taken. That way labels still work.
The second part
$0000 sets what address it's label tracking byte count starts at. asm6 still keeps it's old counter which it'll revert to once it gets to the
.endeIf you remove the
; from the lines after the note, those lines will become active assembler instructions.
Code:
MyVariable0: .dsb 1
Normally
.dsb generates a number of filler bytes, but since the assembler is in a
enum block, it won't actually write that to ROM. It'll simply add 1 to the assembler's internal address counter (properly called the Program Counter).
The result of this instruction is that the label
MyVariable0: is $0000, and the next label (if any) will be $0001.
Code:
MyVariable1: .dsb 3
The Program Counter is $0001, so the label
MyVariable1: is $0001. Program Counter is increased by 3 so the next label will be $0004.
Code:
.ende
As explained above the assembler exits it's enum mode, restoring the Program Counter to whatever it was before, and generating more ROM bytes as it encounters more instructions.
So why does the assembler have this whole enum mechanism anyway? Labels that automatically add up their sizes are useful to work with, but the automatic generating of bytes into ROM becomes a hindrance when working in a area that doesn't exist in the ROM at all. Namely the RAM.
The term enum is shorten from the word enumeration which is the process of giving ordered numbers to a list of things, and that's basically the purpose this asm6 assembler mode.
The rest of that code then repeats these enum blocks for you to put more non-ROM things located at $0100 and $0200.
So .enum and .ende [French?] is ASM-languages and not 6502-languages? Also, is it the reservation code?
I'm still a little confused on .dsb stuff. Is it the "COUNT 3" like it goes 3 steps up or down?
I feel like this isn't part of NES programming, and more of the custom-made ASM programming where it gives options, about if it can hold 64 or 16kb?
DocWaluigean wrote:
So .enum and .ende [French?] is ASM-languages and not 6502-languages?
.ENUM and .ENDE (not French, just short for "end enum") are assembler directives. Even though they aren't part of the 6502 specification, every assembler has a set of directives that are meant to make the programmer's job easier. They are used to organize the output, automate tedious tasks, and so on.
Quote:
Also, is it the reservation code?
The .ENUM directive provides a convenient way to declare variables. Instead of hardcoding addresses to each variable (e.g. MyVariable = $043B), which is tedious, error-prone and hard to manage should you need to move your variables around later on, you simply start from a base address and reserve as much space is needed for each variable.
Quote:
I'm still a little confused on .dsb stuff.
.DSB is what reserves the bytes. Here's a typical .ENUM block, commented:
Code:
.enum $0300 ;temporarily change the address to $0300, so that labels defined here start from that address, and inhibit output
CurrentLevel .dsb 1 ;reserve 1 byte
PlayerHealth .dsb 1 ;reserve 1 byte
PlayerX .dsb 2 ;reserve 2 bytes, as this is a 16-bit variable
PlayerY .dsb 2 ;reserve 2 bytes, as this is a 16-bit variable
.ende ;restores the address to what it was before, start outputting assembled code again
The code above creates 4 variables, starting from $0300, but you don't need to define the address of each one manually. Since you tell the assembler how big each one is, it knows that
CurrentLavel = $0300,
PlayerHealth = $0301,
PlayerX = $0302 and
PlayerY = $0304. If you need to put the variables elsewhere for whatever reason, you can just copy/paste their lines around, without needing to manually change any addresses.
Quote:
Is it the "COUNT 3" like it goes 3 steps up or down?
I don't understand the question. Where is this "COUNT" you're talking about.
Quote:
I feel like this isn't part of NES programming, and more of the custom-made ASM programming where it gives options, about if it can hold 64 or 16kb?
Yeah, it's not exactly 6502 code, but you need these directives if you want to be able to code efficiently. You need to format the output so that it has the structure of a valid cartridge image. You need to mange banks and variables. Assemblers exist to help you with that. You know, you could ignore everything about directives, labels, etc. and code NES programs by writing hex numbers in an hex editor (there's at least 1 crazy member here in the forum that does this!), but that's VERY error-prone and hard to maintain.
I'm back again.
Thankfully, I still remember the Register and the some other part. I would be really depressed if I didn't understand this on today.
So, here's what I'm gonna do.
I'm going to write Psudocodes to get idea of what I want for NES ROM making and others, and try to understand the address map, going to try to leech out on many details of information of what each by each address code is for.
I'm going to draw images right now to give examples of what I want to accomplish.
Attachment:
NES exmp 1.png [ 75.18 KiB | Viewed 4301 times ]
For the first demo I want to make, it's a white background with my OC sprite walking from left to right, and repeat from left to right.-
I just got back at night, so I really hope I can keep going with this tomorrow, so let me try to make mockup of Address of what I think of NES CPU addresses:
Attachment:
cpumemmap.png [ 3.63 KiB | Viewed 4301 times ]
Obviously this, but if I want to start coding, I need to know what's inside of each by each...
Tomorrow, I think it will take me hours to remember what I need to learn about.. I think I'm thinking too ahead, so I haven't read the comment clearly now..
Just for self-confidence and motivation:
You'd be surprised by how many people have said that, but either "forgot" or just gave up on NES development. ...I will not, or hopefully never, make that/the same mistake.
Welcome back DocW, maybe this has already been discussed in this thread, but regardless:
2KB INTERNAL RAM is memory that can be written to while the program (nes game) is running (i.e. variables).
PPU I/O PORTS are addresses that allow access to the PPU Picture Processing Unit
APU/CONTROLLER I/O PORTS are addresses that allow access to the APU Audio Processing Unit or allow access to the nes Controllers
8KB CARTIDGE RAM (WRAM) is the spot where it's possible to allow the saving of game-play progress
32KB CARTRIDGE ROM is the dwelling place of your game's code (ROM is Read Only Memory and can't be physically written to. Note: sta $E000 can allow mapper MMC1 to understand that it needs to do something, but
don't consider enabling a different mapper right now.
In other words, don't replace the simple NROM mapper that you, me, and most others have startted out using.)
NMI/RESET/IRQ VECTORS are three 16bit addresses that show the initial locations of your NMI, RESET, and IRQ functions (code) to the NES so it can use them when needed.
Much more info on the above definitions can be found at
http://wiki.nesdev.com/.
unregistered wrote:
Welcome back DocW, maybe this has already been discussed in this thread, but regardless:
2KB INTERNAL RAM is memory that can be written to while the program (nes game) is running (i.e. variables).
PPU I/O PORTS are addresses that allow access to the PPU Picture Processing Unit
APU/CONTROLLER I/O PORTS are addresses that allow access to the APU Audio Processing Unit or allow access to the nes Controllers
8KB CARTIDGE RAM (WRAM) is the spot where it's possible to allow the saving of game-play progress
32KB CARTRIDGE ROM is the dwelling place of your game's code (ROM is Read Only Memory and can't be physically written to. Note: sta $E000 can allow mapper MMC1 to understand that it needs to do something, but
don't consider enabling a different mapper right now.
In other words, don't replace the simple NROM mapper that you, me, and most others have startted out using.)
NMI/RESET/IRQ VECTORS are three 16bit addresses that show the initial locations of your NMI, RESET, and IRQ functions (code) to the NES so it can use them when needed.
Much more info on the above definitions can be found at
http://wiki.nesdev.com/.
Thank you very much for warm welcoming!
I know this discussion in the previous thread, but not
core details about what the Address does.
Attachment:
ppumemmap.png [ 6.4 KiB | Viewed 4184 times ]
Obviously, Bunnyboy helps out some parts, but there is always missing parts of it:
$2001 - Masking screen with colors
[I'll write more because it's nighttime. I'm trying, while at same time, not to stress too much about learning.]
You're welcome.
Sprite Palette is a 16byte variable that explains to the NES what colors sprites can be drawn with. Those 16bytes are best interpreted as four palettes, each consisting of 4bytes, aka palettes 0, 1, 2 , and 3. The first byte of each palette is
usually the "background" color. So each palette really only has 3 unique colors. (I said
usually bc maybe there might be a way to specify 4 unique colors, but I can't remember what I've read and, nevertheless, my sister decided to create sprites using 3 unique colors as explained above. It must be impossible or extremely difficult to use 4 unique colors in each palette.)
---
Background Palette is set up the same as the Sprite Palette, but it explains to the NES what colors can be used for displaying the background-(the screen's image not considering sprites). (If you are using the Mesen emulator, Options>Video>Palette should show you the colors available on the NES. If
Show color indexes is checked that will display each color's byte representation. i.e. If byte $3F00, $3F04, $3F08, and $3F0C are all #$01 then your background's "background" color would appear dark blue.)
---
Attribute Table is the 64byte specification to the NES PPU that explains how to apply the Background Palette so that the game's background may be displayed correctly. (i.e. Attribute Table 3 can only apply to Nametable 3, this application of Attribute Tables to Nametables must be specified in each NES game's header section. You've already set this specification up.
An attribute byte can be #01010101b or #%01010101 to specify that the NES should color that 32bitx32bit screen location all with Background Palette's palette 1. NES games are restricted into forcing each 16bitx16bit section of the screen (background) to use the same palette (either palette 0, 1, 2 , or 3). This restriction does not encompass/affect sprite coloring.)
---
Name Table is the 960bytes that
make allow the NES to display certain images from Pattern Table 0.
---
Pattern Table 1 is the image (actually a bunch, 256, of 8pixelx8pixel tiny images) that allows the ppu to draw a specific 8pixelx8pixel image when reading certain bytes from its sprite definitions.
---
Pattern Table 0 is the image (actually a bunch, 256, of 8pixelx8pixel tiny images) that allows the ppu to draw a specific 8pixelx8pixel image when reading each byte from the appropriate section of a Name Table that is attempting to be displayed.
Again: "
core details" for each of the definitions above can be found at
https://wiki.nesdev.com/w/index.php/Nesdev_Wiki.
edit: replaced "make" with "allow" bc making the PPU display nametable bytes requires setting PPU I/O PORTS (aka PPU REGISTERS)... the exact process can be found on the nesdev wiki.
edit Note: 960bytes per Name Table is quite a lot of space for each screen... this large amount of bytes per screen can be reduced for games
using many screens by incorporating the use of metatiles and maybe further reduced by RLE use. Using metatiles and/or RLE takes even more learning; wanted to place this note here for some of the other people reading your thread.
final edit: posted secure wiki link; it seems like
rainwarrior's findings he posted about on Nov. 23, 2017 are still around today... the wiki redirect doesn't keep the original http or https, rather it always redirects to http.