Jump to content

Photo

Session 8: Our First Kernel


32 replies to this topic

#1 Andrew Davie ONLINE  

Andrew Davie

    Stargunner

  • 1,746 posts
  • Dr.Boo
  • Location:Tasmania

Posted Sat May 24, 2003 12:12 AM

We're going to jump right in, now that we know what a kernal needs to do. Seen below, and in the attached file, is the source code for a working '2600 kernel. It displays the image you see here. Not bad for just a few lines of code. Over the next few sessions we'll learn how to modify this code, and assemble it - and, of course, what all those strange words mean.

For now, have a look at the structure of the code and note how closely it relates to the structure of the TV frame diagram in the earlier sessions. Don't expect to understand everything - we'll walk through every line soon. For now, all you need to know is that the "sta WSYNC" is where the 6502 is telling the TIA to halt the 6502 until the start of the next horizontal blank period (which is at the start of the next scanline, at TIA colour clock 0). So each of those lines is where one complete scanline has been sent to the TV by the TIA. Have a close look at those lines, and see how there are 3, followed by 37 (vertical blank period), followed by 192 (picture) followed by 30 (overscan) - and how this exactly matches our TV frame diagram, above.

Yes, this is a complete kernel. It's not that difficult!

Here's the source-code...




            processor 6502

            include "vcs.h"

            include "macro.h"



            SEG

            ORG $F000



Reset

StartOfFrame



   ; Start of vertical blank processing



            lda #0

            sta VBLANK



            lda #2

            sta VSYNC

            

               ; 3 scanlines of VSYNCH signal...



                sta WSYNC

                sta WSYNC

                sta WSYNC



            lda #0

            sta VSYNC           



               ; 37 scanlines of vertical blank...



                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

            





               ; 192 scanlines of picture...

 

                ldx #0

                REPEAT 192; scanlines



                    inx

                    stx COLUBK

                    sta WSYNC



                REPEND



 

            lda #%01000010

            sta VBLANK                     ; end of screen - enter blanking



               ; 30 scanlines of overscan...



                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC

                sta WSYNC



            jmp StartOfFrame





            ORG $FFFA



            .word Reset          ; NMI

            .word Reset          ; RESET

            .word Reset          ; IRQ



    	END





Next session we'll have a look at how to actually assemble this code using DASM, and how to make modifications so you can play with it and test it on the emulator to see what effect your changes have.

Attached Thumbnails

  • kernel1.png

Attached Files



#2 MegaManFan OFFLINE  

MegaManFan

    NNID: MrMegaManFan

  • 18,965 posts
  • Mega Man, Mega Man, does whatever a Mega can!
  • Location:Casa de J

Posted Sat May 24, 2003 12:29 AM

Andrew, I hate to say this, but can you SLOW DOWN a little bit? You've probably crammed two weeks worth of comp sci programming classes into two days, and while I'm following it pretty well a little time to absorb and review the lessons between one update and the next would help! Just MHO of course, feel free to pay in no mind, but hopefully I'm not the only one who wants to get the most out of this valuable service you're providing us without being completely overwhelmed! :D

#3 NE146 ONLINE  

NE146

    Dumbass Atari Fan

  • 14,491 posts
  • Location:Seattle, WA

Posted Sat May 24, 2003 12:33 AM

this is good stuff 8)

#4 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Sat May 24, 2003 1:05 AM

Andrew, I hate to say this, but can you SLOW DOWN a little bit?  You've probably crammed two weeks worth of comp sci programming classes into two days, and while I'm following it pretty well a little time to absorb and review the lessons between one update and the next would help!  Just MHO of course, feel free to pay in no mind, but hopefully I'm not the only one who wants to get the most out of this valuable service you're providing us without being completely overwhelmed! :D

It's taken me 1 hour to read all this.
Go through it at your own pace.
I say full steam ahead. :D

#5 MegaManFan OFFLINE  

MegaManFan

    NNID: MrMegaManFan

  • 18,965 posts
  • Mega Man, Mega Man, does whatever a Mega can!
  • Location:Casa de J

Posted Sat May 24, 2003 1:43 AM

It's taken me 1 hour to read all this.
Go through it at your own pace.
I say full steam ahead. :D


I can read an 800 page book in one night (have done before) but that doesn't mean you'll absorb everything in it to the degree you would reading a few chapters a night over a longer period of time; and this isn't even fiction, it's teaching - something you DEFINITELY need to take the time for. But it's his choice, my humble opinion. Hopefully someone's logging all this for the AA archives anyway.

#6 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Sat May 24, 2003 2:00 AM

I can read an 800 page book in one night (have done before) but that doesn't mean you'll absorb everything in it to the degree you would reading a few chapters a night over a longer period of time; and this isn't even fiction, it's teaching - something you DEFINITELY need to take the time for.  But it's his choice, my humble opinion.  Hopefully someone's logging all this for the AA archives anyway.

It's all written down. this could be 800 pages long by tomorrow but it's up
to you the reader how you absorb it, not the Author.

Anyway I'm a hands-on kind of learner so we're just getting to my favorite part :D

#7 MegaManFan OFFLINE  

MegaManFan

    NNID: MrMegaManFan

  • 18,965 posts
  • Mega Man, Mega Man, does whatever a Mega can!
  • Location:Casa de J

Posted Sat May 24, 2003 2:13 AM

Honestly, if it was me, I'd post one "lesson" a day. Four reasons:

(1.) Give the people on the boards something to anticipate each new day.
(2.) Give the people a full 24 hours to work on the previous day's material.
(3.) Give people time to ask any questions they have about the lesson.
(4.) Give people time to save copies of past lessons before more emerge.

#8 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Sat May 24, 2003 3:04 AM

Honestly, if it was me, I'd post one "lesson" a day.  Four reasons:
 
(1.) Give the people on the boards something to anticipate each new day.
(2.) Give the people a full 24 hours to work on the previous day's material.
(3.) Give people time to ask any questions they have about the lesson.
(4.) Give people time to save copies of past lessons before more emerge.

Thats a good idea :D


I think all those WSYNC's look ugly so I thought I'd share this with the class ;)

            processor 6502

            include "vcs.h"

            include "macro.h"



            SEG

            ORG $F000



Reset

StartOfFrame



   ; Start of vertical blank processing



            lda #0

            sta VBLANK



            lda #2

            sta VSYNC

           

               ; 3 scanlines of VSYNCH signal...



                sta WSYNC

                sta WSYNC

                sta WSYNC

  lda #0

  sta VSYNC           



               ; 37 scanlines of vertical blank...



                REPEAT 37; scanlines

                     sta WSYNC



                REPEND

           





               ; 192 scanlines of picture...



                ldx #1

                REPEAT 192; scanlines

                    inx

                    stx COLUBK

                    sta WSYNC



                REPEND





            lda #%01000010

            sta VBLANK                     ; end of screen - enter blanking



               ; 30 scanlines of overscan...



           REPEAT 30 

                   sta WSYNC



                REPEND



            jmp StartOfFrame





            ORG $FFFA



            .word Reset          ; NMI

            .word Reset          ; RESET

            .word Reset          ; IRQ



       END

:P :D

Z26 must default to PAL because it's not using the whole screen :ponder:
I changed 192 to 242 and it works fine :) but does the vertical blank and overscan need to be adjusted?

#9 Andrew Davie ONLINE  

Andrew Davie

    Stargunner

  • Topic Starter
  • 1,746 posts
  • Dr.Boo
  • Location:Tasmania

Posted Sat May 24, 2003 3:41 AM

I think all those WSYNC's look ugly so I thought I'd share this with the class  

[snip/snip]

Z26 must default to PAL because it's not using the whole screen :ponder:  
I changed 192 to 242 and it works fine :) but does the vertical blank and overscan need to be adjusted?



I welcome questions - after all, this is supposed to be an interactive tutorial/forum.

I tried to make the code sample as UNDERSTANDABLE as possible. It is certainly not the most efficient code - for it uses too many bytes of ROM to achieve its effect. But we're learning, and what's important right now is understanding how things work.

It's as good a time as any to explain a little bit about the assembler - DASM. As you have probably gathered by now, we make our changes to the source code - which is meant to be a human-readable form of the program. We feed that source code to the assembler - and provided the assembler doesn't find any errors in the format of the code, it will convert the human-readable format into a binary format which is directly runnable on the '2600 (burn it to an EPROM, plug the EPROM into a cartridge, and plug the cartridge into a '2600) or on an emulator (just load the binary into the emulator).

Consider the following snippet of code...


        sta	WSYNC

        sta	WSYNC

        sta	WSYNC


That's 3 scanlines of 6502-halting. DASM has a nice feature where it can output a listing file which shows both our original source code, but also the binary numbers it replaces that code with. We'll have a close look at this feature later (and how to 'drive' DASM) - but those wishing to look through the DASM documentation should look for the "-l" switch.

When the above code fragment (from our original kernel) is assembled, the listing file contains the following...


     25  f008         85 02        sta	WSYNC

     26  f00a         85 02        sta	WSYNC

     27  f00c         85 02        sta	WSYNC



The leftmost number is the line-number in our original source. The next 4-digit hexadecimal number is the address in ROM of the code. Don't worry too much about that now - but do notice that each line of code is taking 2 bytes of ROM. That is, the first line starts at F008 and the next line starts at F00A (2 bytes different). That's because the "sta WSYNC" assembles to two bytes - $85 and $02. In fact, there's a 1:1 correspondence here between the mnemonic ("abbreviation") of our instruction - the human readable form - and the binary - the machine-readable form. The "sta" instruction (which stands for store-accumulator) has an opcode of $85. Whenever the 6502 fetches an instruction from ROM, and that instruction opcode is $85, it will execute the "store accumulator" instruction.

The above code fragment, then, shows three consecutive "$85 $02" pairs, corresponding exactly to our three consecutive "sta WSYNC" pairs. Can you guess the actual address of the TIA WSYNC register? If you need a clue, load up the "vcs.h" file and see what you can find in there. It should be clear to you that the assembler has simply replaced the WSYNC with an actual numerical value. To be exact, after assembling the file, it has decided that the correct value for WSYNC is 2 - and replaced all occurences of WSYNC with the number 2 in the binary image.

OK, so that was pretty straightforward - now let's do what HappyDood did, and insert that "REPEAT" thingy...


     REPEAT 3

          sta WSYNC

     REPEND


This does do exactly the same thing, as he has surmised - but not, I suspect, quite in the way that he thinks. Let's have a look at the listing file for this one...


     31  f008           REPEAT	3

     32  f008         85 02        sta	WSYNC

     31  f008           REPEND

     32  f00a         85 02        sta	WSYNC

     31  f00a           REPEND

     32  f00c         85 02        sta	WSYNC

     33  f00e           REPEND


If you look carefully, you can see in the source code at right, we still have exactly 3 lines of code - the "sta WSYNC" code - and in the middle, we still have 3 pairs of "$85 $02" bytes in our binary. All that has changed, really, is that our source code was smaller and easier to write (especially if we're considering dozens of lines of "sta WSYNC"s.

DASM is a pretty good assembler - and it is loaded with features which make writing code easier. Happy has used one of these features to simplify the writing of the code. That feature is the "repeat" construct. Wrap any code with "REPEAT n" (where n is a number > 0), and "REPEND" and the assembler will automatically duplicate the surrounded code in the binary n times.

Note, we're not saving ROM, we're just having an easier time writing the code in the first place.

So this highlights, I hope, that it is possible to include things in your source code which are directions to the assembler - basically a guide to the assembler about how to interpret the code. REPEAT is one of those. There are several others, and we will no doubt learn about these in future sessions.

I won't introduce too much more 6502 at this stage - but what HappyDood was striving to do was simplify the code. The repeat structure was a way to do that visually, but it does not reduce ROM usage. One way (of several) to do that is to incorporate the "sta WSYNC" into a loop, which iterates 37 times. Here's a teaser...


               ; 37 scanlines of vertical blank...



                ldx #0

VerticalBlank   sta WSYNC

                inx

                cpx #37

                bne VerticalBlank



Remember, the 6502 has three "registers" named "X", "Y", and "A". In the code above, we initialise one register to the value 0 through "ldx #0", then we do the halt "sta WSYNC" which will halt the 6502 until the TIA finishes the current scanline. Then we increment the x-register "inx" by one, then we compare the x-register with 37 "cpx #37". This is in essence asking "have we done this 37 times yet". The final line "bne VerticalBlank" transfers control of the program back to the line "VerticalBlank" if the comparison returned (in effect) "no".

The actual listing file for that code contains the following...


     41  f012         a2 00        ldx	#0

     42  f014         85 02    VerticalBlank sta	WSYNC

     43  f016         e8        inx

     44  f017         e0 25        cpx	#37

     45  f019         d0 f9        bne	VerticalBlank


If we count the number of bytes in the binary output we can see that this code takes just 9 bytes of ROM. If we had 37 "sta WSYNC" instructions, at two bytes each, that's 74 bytes of ROM. Using the REPEAT structure, as noted, will still take 74 bytes of ROM. So looping is a much more efficient way to do this sort of thing. There are even MORE efficient ways, but let's not get ahead of ourselves.

We are a bit ahead of ourselves here, so don't panic. Just remember, though, that DASM is a tool designed to aid us humans. It is full of things which make the code more readable (less "ugly") but taking lines of code out does not necessarily mean our code is more efficient - or uses less ROM :)

#10 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Sat May 24, 2003 4:16 AM

I was going to post asking why I was still getting a 4K file even after using
the loops when I noticed this

            ORG $FFFA

I spent a good 10 minutes figuring that one out :lol:

#11 Andrew Davie ONLINE  

Andrew Davie

    Stargunner

  • Topic Starter
  • 1,746 posts
  • Dr.Boo
  • Location:Tasmania

Posted Sat May 24, 2003 4:30 AM

I was going to post asking why I was still getting a 4K file even after using  
the loops when I noticed this  


            ORG $FFFA

I spent a good 10 minutes figuring that one out :lol:


The ORG statement is one of those DASM-things which we talked about, which helps DASM to assemble the code into a binary of the correct form.

In this case, the ORG statement tells DASM what address the following code should start at. So at the beginning of the code we have ORG $F000 - which tells DASM to start putting code at $F000 (of course), and at the end we have ORG $FFFA - which telss DASM to put the next bit of code at $FFFA.

That next bit of code happens to be the "interrupt vectors". We'll cover those later, but in essence they are there to help the 6502 go to the right bit of code when it first powers-on. There are three vectors, pointing to bits of code (they contain the address of the code). When you press RESET on your '2600, the 6502 looks in location $FFFC, retrieves the two bytes starting there, and uses those bytes to form a 16-bit address where it starts running your program from.

In the case of our first sample code, that address is at $F000 - which corresponds to our "label" "Reset".

#12 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Sat May 24, 2003 4:50 AM

How do you see how big the file really is? do you just coment out the Org line
or is there something Dasm can do?

When you press RESET on your '2600, the 6502 looks in location $FFFC, retrieves the two bytes starting there, and uses those bytes to form a 16-bit address where it starts running your program from.

Then how do 2K roms work?

I'm jumping ahead a bit much here. I see you haven't tolde everyone how to
use Dasm to compile the source. I know I had trouble with that when I first started.

#13 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,552 posts
  • Location:The land of Gorch

Posted Sat May 24, 2003 4:54 AM

Next session we'll have a look at how to actually assemble this code using DASM



#14 Andrew Davie ONLINE  

Andrew Davie

    Stargunner

  • Topic Starter
  • 1,746 posts
  • Dr.Boo
  • Location:Tasmania

Posted Sat May 24, 2003 5:08 AM

How do you see how big the file really is? do you just coment out the Org line
or is there something Dasm can do?

When you press RESET on your '2600, the 6502 looks in location $FFFC, retrieves the two bytes starting there, and uses those bytes to form a 16-bit address where it starts running your program from.

Then how do 2K roms work?

I'm jumping ahead a bit much here. I see you haven't tolde everyone how to
use Dasm to compile the source. I know I had trouble with that when I first started.


The only way to really be sure how big a ROM is, is to look at the size of the binary the assembler spits out. In our 4K ROMs, they will be 4096 bytes. In 2K ROMs they will, of course, be 2048 bytes.

2K ROMs start with a different origin...

ORG $F800

So the ROM "lives" at location $F800-$FFFF (2K in size), and the interrupt vectors are still at $FFFA onwards. Don't get too far ahead, now!

#15 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Sat May 24, 2003 5:26 AM

How do you see how big the file really is? do you just coment out the Org line
or is there something Dasm can do?

The only way to really be sure how big a ROM is, is to look at the size of the binary the assembler spits out. In our 4K ROMs, they will be 4096 bytes. In 2K ROMs they will, of course, be 2048 bytes.

O.k I could have worded that better.
How can you tell how much of the 4096 bytes (or 2048) you're actually using?

#16 Andrew Davie ONLINE  

Andrew Davie

    Stargunner

  • Topic Starter
  • 1,746 posts
  • Dr.Boo
  • Location:Tasmania

Posted Sat May 24, 2003 6:20 AM

O.k I could have worded that better.  
How can you tell how much of the 4096 bytes (or 2048) you're actually using?



Have a look at the listing file produced with the -l option of DASM. Here's an excerpt, from a variant of our first kernel...


     60  f02a      ; 30 scanlines of overscan...

     61  f02a

     62  f02a         a2 00        ldx	#0

     63  f02c         85 02    Overscan   sta	WSYNC

     64  f02e         e8        inx

     65  f02f         e0 1e        cpx	#30

     66  f031         d0 f9        bne	Overscan

     67  f033

     68  f033         4c 00 f0        jmp	StartOfFrame

     69  f036

     70  f036

     71  fffa           ORG	$FFFA

     72  fffa

     73  fffa         00 f0        .word.w	Reset; NMI

     74  fffc         00 f0        .word.w	Reset; RESET

     75  fffe         00 f0        .word.w	Reset; IRQ

     76  10000

     77  10000            END



Here we can see that the code itself ends at $F036. So it's using $F036 - $F000 bytes (= $36 = 54 decimal). There's also the interrupt vectors at the end - another 6 bytes. So the code sample I used to produce the above listing snippet is using just 60 of the 4096 available bytes.

Listing files are your friend.

#17 DEBRO OFFLINE  

DEBRO

    Stargunner

  • 1,911 posts
  • Location:Atlanta, GA

Posted Sat May 24, 2003 7:36 PM

O.k I could have worded that better.  
How can you tell how much of the 4096 bytes (or 2048) you're actually using?


You can use echo to report it after your ROM assembly.

For instance (using Andrew's example) the code starts at $F000. If you add the line...

    echo *-$F000, " ROM bytes used"
just before org $FFFA and you assemble the code, DASM should report the number of bytes used. I use this in Climber 5 to keep track of how many bytes I have free until I reach my limit.

*-$F000 means to take the current location (*) and subtract it from the given address ($F000).

You would place this before an org or align ### statement so you get an acurate count.

BTW excellent work Andrew :thumbsup: :thumbsup: :thumbsup:

#18 Happy_Dude OFFLINE  

Happy_Dude

    River Patroller

  • 4,212 posts
  • Forum Slacker
  • Location:Sydney, Australia

Posted Tue Jun 10, 2003 6:03 AM

I thought I'd post this here as it concerns this lesson
I think this saves 2 cycles per scanline and 1 byte.
it sounds trivial but you'll have more than 1 loop in your code right ;)

   ; 192 scanlines of picture...



                ldx #192

Picture         stx COLUBK

                dex

                sta WSYNC

                bne Picture



#19 Andrew Davie ONLINE  

Andrew Davie

    Stargunner

  • Topic Starter
  • 1,746 posts
  • Dr.Boo
  • Location:Tasmania

Posted Tue Jun 10, 2003 6:10 AM

I thought I'd post this here as it concerns this lesson
I think this saves 2 cycles per scanline and 1 byte.
it sounds trivial but you'll have more than 1 loop in your code right ;)


   ; 192 scanlines of picture...



                ldx #192

Picture         stx COLUBK

                dex

                sta WSYNC

                bne Picture


This is OK, but not functionally equivalent. In our early code our x-register (and hence colour value) was incrementing from 0 to 191 inclusive. So the colours went "up". In your example, x is decrementing from 192 to 1 inclusive, so the colours go "down". You get the same effect (colour rainbow), but it's up the other way, so to speak.

But yes, you are right. With the above code you don't need to do a comparision every loop. But remember, I'm introducing 6502 coding in stages, and the early examples are designed to be easy to understand, rather than efficient :)

#20 Pitfall Harry OFFLINE  

Pitfall Harry

    Stargunner

  • 1,993 posts
  • Location:Glendora, CA

Posted Mon Jun 23, 2003 3:40 PM

I'm still confused over a few technical aspects of the basic kernal.

Interrupt Vectors:

I understand that an interrupt vector is a two-byte address, pointing to where the microprocessor is to resume exectution whenever each of the three interrupts (NMI, RESET and IRQ) are triggered, and that the microprocessor looks for these three vectors at the specific addresses:

$FFFA - NMI
$FFFC - Reset
$FFFE - IRQ

Of the three interrupts, I really only have a handle on the RESET interrupt. I understand the RESET interrupt is triggered whenever the player hits the console Reset Switch, and it intuitively makes sense to me that this vector should point to the top of the game program code. But that's really as far as I understand interrupts. The other two interrupts, NMI and IRQ are a total mystery to me. So, here's my questions:

1. What triggers an NMI and an IRQ interrupt?
2. Why is it a good idea to set these two vectors to point to the top of the game Program code?
3. Is there any potential value to a game programmer in having them point elsewhere?
4. What are the consequences of having either NMI, IRQ or both set to point to $0000? (I have disassembled other game programs and seen them set like this).


Vertical Synchronizing:

In the code for the Basic Kernal...

Reset 

StartOfFrame 



   ; Start of vertical blank processing 

           

            lda #0 

            sta VBLANK 



            lda #2 

            sta VSYNC 

           

               ; 3 scanlines of VSYNCH signal... 



                sta WSYNC 

                sta WSYNC 

                sta WSYNC 



            lda #0 

            sta VSYNC      


...I see Vertical Blanking being turned off BEFORE VSYNC is enabled. Wouldn't it be better to wait until AFTER the three scanlines of VSYNC have finished before turning off Vertical Blanking? It doesn't make sense to me to allow the three scanlines worth of VSYNC to possibly be visible on the screen while things are synching up. Will VSYNC not work if Vertical Blanking is turned off first?

Entering into Vertical Blanking:

Vertical Blanking is turned on by writing a "1" to the D1 bit of VBLANK. Writing a #%00000010 to VBLANK will accomplish this, but I noticed the Basic Kernal writes #%01000010 to VBLANK instead. That is, both the D1 bit and the D6 bit of VBLANK are set in the example of the Basic Kernel. Why set the D6 bit when entering into Vertical Blanking?

As I read it from the Stella Programmer's Guide, setting the D6 bit of VBLANK "enables the latches for input ports INPT4 and INPT5. When enabled, the latch is set for logic one, and when disabled the microprocessor reads the logic level of the port directly."

The description in the Stella Programmer's Guide of how the D6 bit of VBLANK affects input ports INPT4 and INPT5 (the ports where the joystick Fire buttons are read) is as clear as mud to me. Does setting Bit D6 of VBLANK to "1" cause the status of the joystick fire buttons to be readable or unreadable? If D6="1" makes the input ports unreadable, why would you want to do that? By making the joysticks unreadable you would lose 30 out of 262 opportunities per NTSC frame to read the status of the joystick fire buttons. What would be the upside in making the joystick fire buttons unreadable during the oversan period?

Ben

#21 EricBall OFFLINE  

EricBall

    Dragonstomper

  • 787 posts
  • Location:Markham, Ontario, Canada

Posted Tue Jun 24, 2003 12:26 PM

I'm still confused over a few technical aspects of the basic kernal.
Interrupt Vectors  


The 6507 used in the 2600 doesn't have the NMI or IRQ pins, which trigger these interrupts on a normal 6502.

The 6502C used in the 7800 does have these pins. The MARIA graphics processor can trigger an NMI interrupt (to allow the game a chace to change the MARIA registers mid-screen) and the IRQ pin is connected to the cartridge port (don't know if any games used it).

But we're talking about the 2600. Although the 6507 doesn't have NMI or IRQ pins, it's good programming practice to have those vectors point somewhere, either the same as RESET or an RTI instruction. (And to include an SEI instruction in your initialization section.) That way if the 6507 flakes out it won't crash horribly.

While we're on the topic, you should also reserve $FFF8 & $FFF9 in any 2K or 4K games to make them compatible with the Supercharger. Stick in a version code or your initials in ASCII.

Vertical Synchronizing:


I'm still not 100% certain about what the correct timing of VSYNC / WSYNC is msyelf. And, unfortunately, I don't have a oscilliscope to check it out. Maybe I could brute force it with test programs on the SuperCharger.

Re: VBLANK, see my replies over in Session 13 for more info, but basically there is no required relationship.

#22 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!, Boulder Dash, THREE·S, Star Castle

  • 22,157 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Jun 24, 2003 12:34 PM

The 6507 used in the 2600 doesn't have the NMI or IRQ pins, which trigger these interrupts on a normal 6502.

:idea: Yes, but IRQ can also be triggered by BRK.

Some games (Parker Bros) even use BRK to call subroutines (I have explained that on [stella], it's quite strange and definitely not for newbies).

And you can use BRK for debugging. E.g. you can check if a branch is always taken by adding a BRK just behind it and point the IRQ vector to a special routine or simply to the RESET address.

#23 Pitfall Harry OFFLINE  

Pitfall Harry

    Stargunner

  • 1,993 posts
  • Location:Glendora, CA

Posted Wed Jun 25, 2003 12:02 AM

Thanks Eric, thanks Thomas. That cleared a few things up for me. :)

Ben

#24 CabaretVoltaire OFFLINE  

CabaretVoltaire

    Space Invader

  • 44 posts

Posted Wed Oct 12, 2005 6:53 AM

I'm sorry for replying to such an old thread and hope that noone minds. I am starting to follow these lessons now, as well as the Stella guide, and just want to make sure I am understanding this correctly:

At the start of a frame (or at the start of overscan period?) you have to set the VBLANK register to 2 which turns off the TV beam..

I think it would be best to turn off the beam at the start of overscan.. Which would mean my very first frame would have the beam turned on during vsync/vblank.. Is that ok to do? I notice in the example kernel it is done like this but just wanted to make sure...


..and then write 2 to VSYNC to say that we are vsync period.

VSYNC period is for 3 scanlines so I should write anything(?) to WSYNC 3 times. Can I do anything else during this time, is it possible to do:

;some code
sta WSYNC
;some more code
sta WSYNC
;even more code
sta WSYNC

aslong as the code, including the sta WSYNC, doesn't exceed 76 cycles? Or is it possible to skip the WSYNCs altogether as long as I have 76*3 cycles of code or code + a sta WSYNC that comes in at less than 76*3 cycles?

Then I should set VSYNC to 0 to say that we are no longer in the vsync period.

I then have 37 scanlines of vertical blank.. So essentially 37 "sta WSYNCs", again is it ok to put code here..

Now I should be drawing stuff right? So I have my 192 scanlines before overscan..
So at the start of overscan I think I have to set VBLANK to 2, and then I have 30 lines which I can treat in pretty much the same way as VBLANK right?


I am sorry if this seems stupid but I want to make sure that I understand all of this properly before moving on!

#25 Cybergoth OFFLINE  

Cybergoth

    Quadrunner

  • 8,801 posts
  • This is Sparta!
  • Location:Bavaria

Posted Wed Oct 12, 2005 8:22 AM

Hi there!

I think it would be best to turn off the beam at the start of overscan..  Which would mean my very first frame would have the beam turned on during vsync/vblank..  Is that ok to do?


Yup, that's fine.

Can I do anything else during this time, is it possible to do:

;some code
sta WSYNC
;some more code
sta WSYNC
;even more code
sta WSYNC

aslong as the code, including the sta WSYNC, doesn't exceed 76 cycles?  Or is it possible to skip the WSYNCs altogether as long as I have 76*3 cycles of code or code + a sta WSYNC that comes in at less than 76*3 cycles?


I can only recommend to not do anything during that period, especially don't write to any TIA registers. Best you can do here is including macro.h and then just let the

VERTICAL_SYNC

macro do the job for you.

Otherwise the screen can roll on various Consoles/TVs.

I then have 37 scanlines of vertical blank..  So essentially 37 "sta WSYNCs", again is it ok to put code here..


Yup. That's were it goes.

So at the start of overscan I think I have to set VBLANK to 2, and then I have 30 lines which I can treat in pretty much the same way as VBLANK right?


That's fine, yes.

Turn VBLANK on at the beginning of the overscan, turn it off at the start of the display and use the VERTICAL_SYNC macro. Following these few rules should always result in a stable screen. (If you do reasonable numbers of scanlines in all other sections (display/overscan/vblank) of course! :))

I am sorry if this seems stupid but I want to make sure that I understand all of this properly before moving on!


Nothing stupid here, just the standard beginners questions ;)

Greetings,
Manuel




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users