I've been trying to get started with the very most basic PPU programming. I took Blargg's simple demo (the one that just powers up the PPU and then plays a single note of sound) and added
lda #$1e ; turn rendering on
sta $2001
lda #$11 ; set universal background color to some kind of blue
sta $3F00
... and yet all I'm getting is grey when running my .nes in the emulator. What am I missing? I have no data in my char segment. Do I need to?
Good morning... what comes to my mind is that maybe you should change the color of the background before turning on rendering. Hope someone else can really help you with this.
Didn't help, but thanks anyway
Wait, you used a
sta $3f00
instruction ?!?
You probably mean something like :
lda #$3f
sta $2006
lda #$00
sta $2006
lda #$whatever
sta $2007
I was just about to write something similar, yes. I'd missed the part about not being able to write to PPU memory directly. Thanks!
EDIT: Weeee, it's working!
Don't forget to read $2002 before setting the PPU address, if you're at all not sure the state of the internal flag that keeps track of whether the next $2006 write sets the high or low byte of the address.
I figured that part out too. Thanks though!
I tried loading the resulting ROM in an emulator and it works as expected, but on my PowerPak I get a random mess of red and white (looks a lot like the pizza sprites from the TMNT games, but zoomed to 800%). I'm guessing it's because I don't have any CHR ROM so the game is just drawing whatever was in VRAM when starting the game (i.e. from the PowerPak menu). I should probably clear VRAM as well as CPU RAM after / during PPU warmup as well, right?
Nope, don't touch VRAM. You don't read it, so it doesn't need set up. Anything needing to be set up will be written by the routines to upload graphics, or will just be in ROM.
What about the pattern name tables, palettes and stuff? Don't they need to be cleared? (I might be confusing VRAM with something else.)
Why would they need "cleared"? They will be cleared when you write the data you need to be there to them. Unless you display a un-setup screen/palette.
Couldn't the same be said for CPU RAM, then? In the example code, CPU RAM is being cleared while waiting for the PPU to stabilize (as we don't know for sure it's all zeroes when starting up. My computer does the same when booting afaik). I guess it's more of a convenience rather than anything else, but still.
It's a little off-topic, but I added some code that changes the background color if the zapper trigger is pressed, and it results in what looks like a random nametable where non-zero characters are being spread out on the screen, mostly on the left edge. Is this because I'm writing to $2007 while not in VBLANK or something?
Yeah. But it's harder to code for the CPU because you use so many variables. While the program will control what you see on the screen, so there is 100% no reason to clear it, unless you're a bad programmer.
But you can not clear CPU RAM. It's just when that happens, it's VERY hard to make sure your game boots+runs right all the time, as you may go to check a variable that hasn't been initialized right.
I'm a pretty bad programmer until further notice (at least as far as NES and assembler are concerned), so I think I'll keep running the RAM clearing routine ^^
Writing to $3F00 only once during a frame seems to have fixed the issue. I'll keep that in mind.
That bug you described above is because you have to write $2000 and $2005 2x after doing all your $2006 stuff before the screen displays. You'll learn why when you get father in to the wiki.
Clearing RAM helps to stabilize some bugs, but it also gives a good chance for them to remain unnoticed. Some emulators clears RAM anyway, but HW does not, so when you don't clear RAM, it could be a surprise that program is unstable when running on the real HW. To clear or not to clear, that is the question. I think it may be a good idea to clear it, but sometimes try to change the clear value to something other than zero, just to see if you have forgot to initialize some variable.
Thanks for the advice.
(On a side note, I ******* love you guys. Had this been the average linux forum or something, I would have been called names and made fun of for asking things like this. Instead, I get my questions answered by
legends. So... thanks
)
So... I added some code to clear the nametables, and found that reading PPUSTATUS affects PPUSCROLL, which I now see is mentioned, but not really explained, in the wiki. Why does PPUSTATUS affect PPUSCROLL? Is this just a flaw in the hardware, or is it actually useful for something?
There is a 1-bit toggle in the PPU that tellswhether the next write to PPUSCROLL ($2005) or PPUADDR ($2006) should be treated as a first write or a second write. A first write to PPUSCROLL sets the horizontal position, which is made of a "coarse X" (tile column) and a "fine X" (background delay line length). A second write sets the vertical position, which is made of a "coarse Y" (tile row) and a "fine Y" (scanline within tile). Fine X takes effect immediately, coarse X takes effect at the end of the scanline, and Y takes effect at the start of the next frame.
Reading PPUSTATUS ($2002) tells the PPU to treat the next write as a first write.
So... in order to set PPUSCROLL to be actually 0,0 I need to write 0 to $2005 four consecutive times? And this must be done every time I've read PPUSTATUS? See, if I don't write to $2005 at all, my game starts scrolled down to 0,128 or something (in the emulator, at least), and for a while it seemed as if every time I read from PPUSTATUS it would go back to this scroll position unless I set PPUSCROLL, but I seem to have been mistaken...
No.
When $2002 is read, a " latch" is reset. The latch point to the number 1 or 0. Eevry time you write to $2006 or $2006, the latch toggles. So to write it, you need to set the latch to a known position. Reading it sets it to 0, or cleared. Then the next write to $2006/$2005 will go to the first position. The next will go to the 2nd position. then the 1st, 2nd, etc.
Read the Wiki page on PPU registers for a better understanding.
I understood the latch part, but I misunderstood coarse and fine x scroll as being two separate bytes. Which doesn't make sense, of course.
Still, I don't see why the game starts scrolled down, but nevermind. Thanks!
It's because $2006 is actually a $2005 write in a way...it's confusing. But to avoid it perfect, write to $2000 and $2005 (2 times) to make sure it doesn't happen. If you wanna know why, see
The skinny on NES scrolling.
You write only two bytes to $2005, but the bits in those bytes are sort of "scattered" in a way that makes sense for scrolling.
- The first write to $2005 writes to coarse and fine X at the same time. Bits 2-0 go to the fine X register that controls the delay line mux used for scrolling 0-7 pixels, while bits 7-3 go to the coarse X portion of a register called "t" by the "skinny" doc.
- The second write to $2005 writes to coarse and fine Y at the same time. The written bits go to two different parts of "t".
After you finish uploading data to VRAM through $2006 and $2007, "t" is corrupted. You need to fix "t" by writing to $2000 once and $2005 twice just before turning on rendering.
Roger. Certainly strange behavior, this. Some senior engineer at Nintendo was quoted somewhere as saying that the reason the guy who designed the NES (who was allegedly young and inexperienced) pulled it off was because he, unlike the others, didn't know it was impossible. I guess this type of weirdness is excusable in the light of... that.
Anyway, just to prove you're not completely wasting your time on me:
Dafydd wrote:
Certainly strange behavior, this.
It's not strange at all. The thing is that the PPU has a set of internal registers it uses to access VRAM. When you use $2006/$2007 to write/read to/from VRAM you mess with these registers, but the PPU uses these same registers to read data from VRAM as it renders the image. So every time you're finished using these registers you have to set them to a proper value that will cause rendering to start from the desired location. This is called "setting the scroll".
Well... when you put it that way, maybe not.
Dafydd wrote:
Well... when you put it that way, maybe not.
I'll try to dumb this down a bit:
The confusing part for most people pertains to the "general description" and "general use methodology" of the
registers $2005 and $2006 for the PPU. The confusion is further compounded when you realise those regs are "officially" labelled PPUSCROLL and PPUADDR. Even $2000 (PPUCTRL) plays a role.
At first glance they appear to be, respectively, a way to control the background X/Y offset (for "scrolling" the playfield/screen) and a way to specify a PPU RAM address that you plan on accessing using $2007. And for $2000, a "way to select which nametable to use". But in reality, all these regs do a
hell of a lot more under the hood -- and that is what tokumaru is talking about.
If you ever feel like learning the "real deal" of how it works, you can read (and you will need to READ it, not skim it!) the below wiki document:
http://wiki.nesdev.com/w/index.php/The_ ... _scrollingWarning up front: note that even though I "colourised" the Examples section (because it's really hard to mentally keep track of what bits are going into what internal PPU registers vs. what you're writing to $2005/$2006), I still don't have a 100% grasp on it (meaning I understand that the registers affect the internal PPU registers in such ways, but this is something you often have to keep in mind when writing an actual NES game/program).
The official NES/Famicom documents didn't outline any of this. This is why you'll find most first-generation Famicom games (ex. Battle City, Tennis, Pinball, and many others) being very simple -- none-to-little screen panning, everything looking very "simple", and so on. Hard to explain exactly, but I hope you get what I mean. Now fast forward some years and look at games like Wizards & Warriors*, Ninja Gaiden 2 or 3, Gradius 2 (Famicom), Crystalis, Super Mario Bros 2 and especially 3, and of course Battletoads (that thing is crazy). As time went on, companies/developers actually figured out how all this nonsense worked. As with any console, sure, the games generally get better as time goes on, but in the NES/Famicom's case, people appeared to be learning "how" the hardware worked under the hood and benefit greatly from that as time progressed.
* = I mention this game because of the status bar at the bottom, where if I remember right, the game changes the PPU palette mid-screen (i.e. outside of VBlank, while the electron gun is actively drawing pixels). On early NES emulators (including some Nesticle releases), this resulted in mass breakage -- simply because nobody knew how the above registers truly/internally worked.
koitsu wrote:
I'll try to dumb this down a bit:
Haha. I appreciate it
I know exactly what you mean about the early games being simple, even disregarding things like mappers enabling later games to do things the early ones couldn't do (though I think at least part of the explanation is many of them were ports of arcade games using simpler hardware). This is also very noticeable in the music, where late soundtracks are much more advanced than the early ones despite using the exact same hardware (more on-board memory and FamiCom expansion chips disregarded).
The game I'm trying to make is going to be very simple in terms of graphics and probably not use scrolling at all, but I still need to know how to use PPUSCROLL, apparently, so, yeah, some knowledge of how reading and writing to one PPU register affects the others is necessary, although I think reading that article in-depth can wait until I want to start doing some serious scrolling.
Again, I really appreciate how helpful you all are.
The wiki page I linked is actually about much more than just scrolling -- it shows how $2005 and $2006 affect the internal addressing registers of the PPU itself, which affect more than just ""scroll"" (they technically affect what/where the PPU reads/writes from). It's basically the reason why you'll encounter situations where you need to do
LDA #$00 ; STA $2006 ; STA $2006 ; STA $2006.
Here are a couple very short Youtube videos of an intro I wrote for Neo Demiforce's FF2j English translation which show quite clearly what happens when you don't understand the effects $2005/$2006 have on the underlying/internal PPU registers:
http://www.youtube.com/watch?v=kGuGP7h6hv4http://www.youtube.com/watch?v=Z9cQ4v6mtdsThe discussion about this starts here:
viewtopic.php?p=53107#p53107
Aww,
crap. I was hoping I could take a shortcut there
Yeah, I got that it affects more than just the scrolling. A schematic showing how it all happens à la Logisim or something would be really sweet. I'm not asking you to make one for me, but once I get to grips with this, I might make one myself and ask people to verify it for me.
koitsu wrote:
It's basically the reason why you'll encounter situations where you need to do LDA #$00 ; STA $2006 ; STA $2006 ; STA $2006.
You shouldn't ever have to
LDA #$00; STA $2006; STA $2006; (BTW, was the 3rd STA a typo?) though, because $2006 alone can't fully set the scroll (fine X scroll is left untouched). During VBlank you should ALWAYS favor the $2000-$2005-$2005 combo, because it's the cleanest way to (re)set the scroll. Outside of VBlank, $2006-$2005-$2005-$2006 should be used to completely (re)set the scroll, fine X scroll included.
LDA #$00; STA $2006; STA $2006; is what programmers do out of desperation when they don't know how to properly modify the scroll in all situations. It appears to fix problems most times, but could backfire under certain circumstances.
Dafydd wrote:
Aww,
crap. I was hoping I could take a shortcut there
Don't be scared by what koitsu is saying, he's exaggerating a bit. You don't need to know this stuff in order to code your first non-scrolling game. Just be sure to do the $2000-$2005-$2005 write combo to set the scroll to (0, 0) in the name table where your background is after you're done uploading data to VRAM and you'll be fine.
3rd STA was the result of an extra copy-paste, yep. Oops! :-)
koitsu wrote:
3rd STA was the result of an extra copy-paste, yep. Oops!
Thanks for clarifying - that part was a little confusing
tokumaru wrote:
koitsu wrote:
It's basically the reason why you'll encounter situations where you need to do LDA #$00 ; STA $2006 ; STA $2006 ; STA $2006.
You shouldn't ever have to
LDA #$00; STA $2006; STA $2006; (BTW, was the 3rd STA a typo?) ...
3rd STA was the result of an extra copy-paste, yep. Sorry about that.
tokumaru wrote:
Dafydd wrote:
Aww, crap. I was hoping I could take a shortcut there :P
Don't be scared by what koitsu is saying, he's exaggerating a bit. You don't need to know this stuff in order to code your first non-scrolling game. Just be sure to do the $2000-$2005-$2005 write combo to set the scroll to (0, 0) in the name table where your background is after you're done uploading data to VRAM and you'll be fine.
Agreed -- yes, please don't be scared, nor do you necessarily ***have*** to go and read that doc (it's a lot to take in, and I still don't fully 100% understand it at all times); I am exaggerating a bit, as I have a tendency to do.
You can ABSOLUTELY write a game without understanding that doc! But there may be edge cases during your game development where "weird things" happen on the screen which you didn't expect (see those Youtube videos I linked -- when I wrote the code it worked fine on emulators at the time (Nesticle and iNES) but on the actual hardware broke badly as you can see). If those things happen, that doc can often explain why, especially near the end of VBlank if you're adjusting $2005/$2006 in some way then when the electron gun starts drawing things, starts drawing "garbage" or the wrong stuff making you go "WTF!" (which was my reaction the first time I saw my intro code on an actual console).
You can work around all of those "edge cases" by simply doing what tokumaru says or I have said (i.e. "reset all the things!", haha :-) ) and you'll be fine.
If your game doesn't scroll, just structure your code so the last thing you do is write 2005 twice and then $2000. It's not that hard. You only have to understand the stuff behind the scene if you scroll with the Y co-ords changing. X scrolling you need no background, just sprite 0 then a write to $2005. But yeah, don't worry about it. Just make sure the last thing you do is write to $2000 and $2005 at the end of your VBlank code. It's dead simple to do, and not confusing in any way.
It is a little confusing when you say I should write to $2005 twice and then $2000, and someone else says I should write to $2000 first, then to $2005 twice. Does the order matter or not? (I guess this is the type of thing I wouldn't need to ask if I read the skinny...)
Dafydd wrote:
It is a little confusing when you say I should write to $2005 twice and then $2000, and someone else says I should write to $2000 first, then to $2005 twice. Does the order matter or not?
No, in this case it doesn't matter. $2000 can go first or last, your call.
Here's my take on scrolling:
The PPU was trying to offer a lot of functionality with little hardware. Scrolling, VRAM access address, and even rendering are implemented with some shared hardware. It's sort of like quantum physics, very involved and requires understanding how it all works.
There are simplified abstractions people have built on top of this, where if you do A, B, and C, it'll act in this simplified manner, but if you do anything else it falls apart and you have to go back to the full detail. These abstractions are solid and really do act as stated as long as you stay within the limits they state (e.g. one might require that you only write to $2005, $2006, and $2007 when rendering is disabled or during vblank, never anywhere else).
Even experienced NES programmers use simplified abstractions and know when to drop down to the quantum level when they're stepping outside the abstractions. Abstractions are effective ways to reduce mental load when dealing with things, and well worth it.
blargg wrote:
The PPU was trying to offer a lot of functionality with little hardware.
I think this is sort of what I was trying to say in my post excusing the strange behavior (I still think it's strange - had this thing been built today, it and its under-the-hood register hocus-pocus might have been more transparent, but I could be entirely wrong).
The more you work with hardware/devices developed in older times (circa 70s, 80s, and early 90s), the less likely you'll be inclined to think the behaviour is "strange". In the case of the NES/Famicom -- and as has been admitted by folks at Nintendo Co. during interviews -- the hardware was developed on a very minimal budget (intentionally)... yet it's one of the most revolutionary and memorable consoles ever. I actually started with the SNES/SFC first, then later did NES/FC. The SNES/SFC, from a programmers' perspective, is a much more easier-to-develop-for console; there's a lot less stuff you'd think is "strange", and a lot more memory-mapped registers that are for specific purposes and are documented.
<crotchety old koitsu rant>
No offence intended in the least (towards you or anyone) by this statement, but: anyone born after 1980 would do well to sit down and actually use and develop on a platform (of any sort) made during their birth-decade or a decade prior. Take away all the abstracted APIs -- make them work on bare metal. Make them work on a platform with no OS (excluding what comes with the on-board ROM, ex. Apple II series). Watch how many cry and pee themselves.
Computer science history lessons in a classroom and blabbity blab on Wikipedia don't do justice -- when you make people get their hands dirty, you can see who truly understands how something works vs. who can only grasp things at an abstract level and think what goes on under the hood is "truly just black magic". CS courses at college/uni do this to some degree, but they don't make you work on minimalist platforms, they instead teach you how to think or solve thing X with certain restraints. It's different when you have limited resources due to hardware limitations; there's no prof saying "naughty naughty you can't do that", instead there's the realisation that you've only 2KBytes of RAM and you'd better use it wisely.
The "black magic" for me, despite being low-level, is the hardware itself -- I don't do EE, I don't design circuits -- so as long as there's good documentation from the hardware or IC engineers, I'm generally content. Now compare that to people of today who are used to abstract APIs or whatever other nonsense that sits maybe 7 or 8 "layers" above the actual CPU (or GPU) itself.
When I see folks like yourself, Dafydd, younger but working on older platforms and actually struggling and advancing/learning in good ways, it makes me really happy to see. What you're learning now will actually help you in all sorts of ways outside of the NES/FC; the techniques, thought processes, and design choices that you're learning as you go will influence you.
Eventually you'll start wondering why present-day systems (usually x86/x64 Windows systems) bog down, aren't responsive, or just seem to "waste time" doing god-knows-what (all the abstraction makes it almost impossible to troubleshoot/debug/figure out). Or you'll look at some code somewhere (professionally or open-source) and say "WTF? This thing takes up 72MBytes of RAM and 40MBytes of disk space, yet all it does this one simple thing?!" -- then proceed to write the same thing but 1/100th smaller and a thousand times faster -- all because you worked on a very minimal (or embedded) platform made decades prior and got rid of reliance on horribly abstracted piles of crap (ex. Microsoft's .NET framework, highly abstracted languages, highly OO-focused languages, etc.). *waves hands* You don't need most of that crap. For present-day stuff, a C compiler (not even C++) will do you just fine.
I see the systems of today and I remember literally dreaming about such speeds and capacities. Yet here they are -- all running like molasses, wasting/abusing CPU time, disk space, RAM/resources, etc. *because* so much software and environments (I would border on saying even OSes in some cases) lack developers who have developed on minimalist platforms. Send 'em back in time and watch 'em suffer.
</crotchety old koitsu rant>
I agree completely, and the reasons you listed above are (not the only reasons, but most of them) why I'm doing this. If all I wanted was to make a game, I'd stick to XNA. If all I wanted was to make a game on the NES, I'd do it in C. I want to know how this thing works on a level where I can understand what the hardware is actually doing, but that doesn't mean there aren't things that will strike me as strange on the way (for the record, I also think it's strange people are using Java. For anything).
koitsu wrote:
I see the systems of today and I remember literally dreaming about such speeds and capacities. Yet here they are -- all running like molasses, wasting/abusing CPU time, disk space, RAM/resources, etc. *because* so much software and environments (I would border on saying even OSes in some cases) lack developers who have developed on minimalist platforms. Send 'em back in time and watch 'em suffer.
</crotchety old koitsu rant>
It's funny, because I started programming in assembly and learned high level languages later (I started programming in '05). I now work for a company where we program in VB and have a database that we manage. The first table I ever created on our database used bit flags to determine whether or not one of our stores would be closed on a given day of the week, and I was actually going to create the table so that those 7 bit flags would fit into 1 8-bit field, instead of using 7 "bit" fields, which all use 1 whole byte. I showed the table to my boss and he laughed, because I was being so conservative.
I also love when people refer to the days of 64k of RAM as if it were the lowest possible capacity. I will ALWAYS bring up the NES having 2k, and the Atari having 128 bytes! It's hard for some people, especially today, to wrap their mind around what you can accomplish wish such a small amount of resources.
Celius, where I hope to find work in the future, they make software that needs to be as fast and efficient as they possibly can. A lot of people don't seem to care about these things, but some people do.
Dafydd wrote:
for the record, I also think it's strange people are using Java. For anything
Before Adobe seriously beefed up ActionScript and browser makers added the new JavaScript APIs associated with HTML5, the Java applet environment was the primary way to deploy rich Internet applications with no "installation" step. A lot of early smart phones relied on Java MIDP for applications as well. And now that Android has become popular, Java is "in" again. XNA will just get you onto Xbox Live Indie Games and Windows Phone 7, both of which are becoming very obsolete very fast.
Celius wrote:
I also love when people refer to the days of 64k of RAM as if it were the lowest possible capacity. I will ALWAYS bring up the NES having 2k, and the Atari having 128 bytes!
There's a difference. The "64K" computers had to load programs from a magnetic disk before running them, while the NES more commonly uses
XIP (execute in place) ROM. To be honest, you need to compare them to the 44K of a Famicom with the FDS system card inserted.
But there's a tradeoff between runtime efficiency and maintainability (developer-time efficiency). This becomes especially important when the requirements of a product or service change often to meet market needs.
This is why tepples uses Python -- to meet market needs. *snickers* Sorry dude, you KNEW I had to take a jab. :P
The way this thread has gone for the past half page or so reminds me of a separate thread I've been dealing with on the FreeBSD mailing lists:
I had to debug someone else's code and lectured the author for the bugs; the segfaults I was seeing were explainable, but I threw in the towel once I started seeing stack smashing going on and him allocating a bunch of memory on the stack (vs. malloc()). This prompted an off-topic response from a kernel developer, who made an effort to argue that there's effectively no difference and that I'm basically bitching for no reason. I made my case in an itemised list, which was also backed by another fellow (pointing to an actual program that builds parts of FreeBSD itself which broke for him solely for that reason!). I provided a write up with a C program demonstrating the effects/facts. Of course he refuted this, and I responded this morning.
The modus operandi these days is often "who gives a shit" or "there's so many resources available it doesn't matter", even when presented with facts/information that show quite clearly it does matter. There's really no downside to developing software today with a "minimal" mentality. You don't have to necessarily worry about every single bit/byte -- no need to be that pedantic in most cases -- but resources being more available now than they were in the past is no reason to become lazy. It reminds me of the completely fucked up argument I've seen many times over the years: "unused memory is wasted memory". Yes, just malloc(999999999999999999), otherwise it's going to waste......
I hate having to discuss shit like this with people because it ALWAYS results in people asking me to effectively define things black-and-white, when I'm certain they know damn well the situations always vary. But really there is a mentality/approach that works universally, and that's "if you aren't sure when/why to use Method Y, just use Method X and you'll be fine". This is one of those cases, so I'm irritated that I'm having to further expand on/debate it.
P.S. -- For folks who have known me for a very long time (i.e. 15+ years), discussions like in the aforementioned linked threads are what effectively hardened me + turned me into a general prick. Usenet and mailing lists are full of this type of thing, then it moved to IRC, and today it's on forums. So in case you ever wanted to know why I'm such a hard-ass and why I have a condescending tone whenever I write something, it's because the above is more or less what I've dealt with for the vast majority of my online life. I'm a lot easier to talk to/get along with in person.
tepples wrote:
And now that Android has become popular, Java is "in" again.
I know, and it makes me sad.
tepples wrote:
XNA will just get you onto Xbox Live Indie Games and Windows Phone 7, both of which are becoming very obsolete very fast.
Yeah, I've noticed. But it does let you very quickly create 3D games running in Windows that look very nice, perform pretty well, and work out of the box (provided you have the XNA framework installed). There are upsides and downsides to everything.
I just wanted to say that I found this thread really helpful!
I've been struggling to understand how the PPU registers work and I think I finally start to get it.
I think I just didn't understand that the PPU uses the same registers for multiple tasks and I was confused by the names that loopy used and names like PPUSCROLL and so on. Maybe I can grasp it now :3
And about the topic of programming on a limited system:
I was born in the early 90s and I only know one other programmer in my age (personally!) who has tried to program something for a limited environment in assembly language. What got me interested in trying this myself was the Gameboy. When you just use it for playing games, it appears very limited, but when you start to look at the hardware it actually seems quite capable. Unfortunately only few games show this.
All other programmers (at least the ones in my age!) I talk to, just look at me weird when I explain them what RLE is or why one would program something on interrupt basis, instead of just accessing and updating data whenever it feels right to do so.
And once I say that I have a hard time understanding object oriented programming they start to laugh.
Sometimes this gives me the feeling that I try to learn things in a totally backwards way and just waste my time with it.
But then again I like to spend time reading the documentation of systems like the NES or the Gameboy and trying to figure out how these systems work. In the end I agree with you all in that it might help to make me a better programmer, because it is a worthwhile experience that more people should have.
I think the only way to get a similar experience nowadays without having an "obsession" with old systems is to program a microcontroller. I'm not talking about those highly capable ARM ones, but maybe a small ATMEGA/ATTINY or PIC. I think this could serve as a nice hands-on approach to anyone who has never tried something like this before.
Nevertheless, Python is my favourite programming language
Thanks guys for posting this really informative discussion!
Grumskiz wrote:
What got me interested in trying this myself was the Gameboy. When you just use it for playing games, it appears very limited, but when you start to look at the hardware it actually seems quite capable. Unfortunately only few games show this.
Game Boy games cost less than NES games at retail, pushing budgets down. Game Boy (pre-Pocket) had a primitive LCD, pushing achievable frame rates down. Game Boy had little vertical blank time; updates in horizontal blank interleaved with game logic may have been harder to adapt to. Game Boy had no software envelope without the audible click of restarting the note; music engines had more "plinky" instruments. Game Boy's speaker had no bass (GBA's speaker, for example, had a -18 dB/octave rolloff below 800 Hz); composition had to compensate. And Game Boy had an unfamiliar CPU to programmers not familiar with Nintendo's competitors' consoles.
Nintendo's arcades ran on Z80's, so NES is the odd one out. Not the GB.