Jump to content

Photo

Session 8: Our First Kernel


27 replies to this topic

#26 Random Terrain ONLINE  

Random Terrain

    Visual batari Basic User

  • 24,977 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Fri Apr 22, 2011 1:09 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 :)


Does anyone familiar with the sessions know if the above info is covered in one of the sessions or does it need to be added?

Edited by Random Terrain, Fri Apr 22, 2011 1:10 AM.


#27 TerryMasters OFFLINE  

TerryMasters

    Combat Commando

  • 8 posts

Posted Thu Jan 26, 2012 5:09 PM

Hey everyone. Firstly let me say I am absolutely loving the guide. It's one of the few I can actually understand. So far everything was going great until I tried to compile this source code - the process went smoothly but the program itself runs with artifacts so to speak. I'm not sure if dasm/z26 was updated or if I'm screwing up somehow, but copying that source and compiling it with dasm atarit.asm -f3 -oatarit.bin (new and old) gives me this:

Posted Image

The end result spits out a thick green bar at the top, followed by a thin green bar at the bottom. For whatever reason, not even the example Andrew compiled himself seems to run properly in StellaX - no idea why but here's what I get:

Posted Image


Edit- This is what it says with -v5:

START OF PASS: 1
----------------------------------------------------------------------
SEGMENT NAME				 INIT PC  INIT RPC FINAL PC FINAL RPC
							 f000						    f000
RIOT					 [u] 0280						    0280
TIA_REGISTERS_READ	   [u] 0000						    0000
TIA_REGISTERS_WRITE	  [u] 0000						    0000
INITIAL CODE SEGMENT		 0000 ????					   0000 ????
----------------------------------------------------------------------
3 references to unknown symbols.
0 events requiring another assembler pass.
--- Symbol List (sorted by symbol)
0.FREE_BYTES			 0000
AUDC0				    0015
AUDC1				    0016
AUDF0				    0017
AUDF1				    0018
AUDV0				    0019
AUDV1				    001a
COLUBK				   0009			  (R )
COLUP0				   0006
COLUP1				   0007
COLUPF				   0008
CTRLPF				   000a
CXBLPF				   0006
CXCLR				    002c
CXM0FB				   0004
CXM0P				    0000
CXM1FB				   0005
CXM1P				    0001
CXP0FB				   0002
CXP1FB				   0003
CXPPMM				   0007
ENABL				    001f
ENAM0				    001d
ENAM1				    001e
GRP0					 001b
GRP1					 001c
HMBL					 0024
HMCLR				    002b
HMM0					 0022
HMM1					 0023
HMOVE				    002a
HMP0					 0020
HMP1					 0021
INPT0				    0008
INPT1				    0009
INPT2				    000a
INPT3				    000b
INPT4				    000c
INPT5				    000d
INTIM				    0284
NUSIZ0				   0004
NUSIZ1				   0005
PF0					  000d
PF1					  000e
PF2					  000f
REFP0				    000b
REFP1				    000c
RESBL				    0014
Reset				    f000			  (R )
RESM0				    0012
RESM1				    0013
RESMP0				   0028
RESMP1				   0029
RESP0				    0010
RESP1				    0011
RSYNC				    0003
StartOfFrame			 f000			  (R )
SWACNT				   0281
SWBCNT				   0283
SWCHA				    0280
SWCHB				    0282
T1024T				   0297
TIA_BASE_ADDRESS		 0000			  (R )
TIA_BASE_READ_ADDRESS    0000			  (R )
TIA_BASE_WRITE_ADDRESS   0000			  (R )
TIM1T				    0294
TIM64T				   0296
TIM8T				    0295
TIMINT				   0285
VBLANK				   0001			  (R )
VDELBL				   0027
VDELP0				   0025
VDELP1				   0026
VERSION_MACRO		    006a
VERSION_VCS			  0069
VSYNC				    0000			  (R )
WSYNC				    0002			  (R )
--- End of Symbol List.

Edited by TerryMasters, Thu Jan 26, 2012 5:43 PM.


#28 Pioneer4x4 OFFLINE  

Pioneer4x4

    River Patroller

  • 2,014 posts
  • Atari + R.O.B. = Completed
  • Location:PA

Posted Thu Jan 26, 2012 7:09 PM

Looks like it is being displayed as PAL in the second image.




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users